This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,538 @@
//===-- llvm/Bitcode/Archive.h - LLVM Bitcode Archive -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header file declares the Archive and ArchiveMember classes that provide
// manipulation of LLVM Archive files. The implementation is provided by the
// lib/Bitcode/Archive library. This library is used to read and write
// archive (*.a) files that contain LLVM bitcode files (or others).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_ARCHIVE_H
#define LLVM_BITCODE_ARCHIVE_H
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/Path.h"
#include <map>
#include <set>
namespace llvm {
class MemoryBuffer;
// Forward declare classes
class Module; // From VMCore
class Archive; // Declared below
class ArchiveMemberHeader; // Internal implementation class
class LLVMContext; // Global data
/// This class is the main class manipulated by users of the Archive class. It
/// holds information about one member of the Archive. It is also the element
/// stored by the Archive's ilist, the Archive's main abstraction. Because of
/// the special requirements of archive files, users are not permitted to
/// construct ArchiveMember instances. You should obtain them from the methods
/// of the Archive class instead.
/// @brief This class represents a single archive member.
class ArchiveMember : public ilist_node<ArchiveMember> {
/// @name Types
/// @{
public:
/// These flags are used internally by the archive member to specify various
/// characteristics of the member. The various "is" methods below provide
/// access to the flags. The flags are not user settable.
enum Flags {
SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table
BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table
LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table
BitcodeFlag = 8, ///< Member is bitcode
HasPathFlag = 16, ///< Member has a full or partial path
HasLongFilenameFlag = 32, ///< Member uses the long filename syntax
StringTableFlag = 64 ///< Member is an ar(1) format string table
};
/// @}
/// @name Accessors
/// @{
public:
/// @returns the parent Archive instance
/// @brief Get the archive associated with this member
Archive* getArchive() const { return parent; }
/// @returns the path to the Archive's file
/// @brief Get the path to the archive member
const sys::Path& getPath() const { return path; }
/// The "user" is the owner of the file per Unix security. This may not
/// have any applicability on non-Unix systems but is a required component
/// of the "ar" file format.
/// @brief Get the user associated with this archive member.
unsigned getUser() const { return info.getUser(); }
/// The "group" is the owning group of the file per Unix security. This
/// may not have any applicability on non-Unix systems but is a required
/// component of the "ar" file format.
/// @brief Get the group associated with this archive member.
unsigned getGroup() const { return info.getGroup(); }
/// The "mode" specifies the access permissions for the file per Unix
/// security. This may not have any applicability on non-Unix systems but is
/// a required component of the "ar" file format.
/// @brief Get the permission mode associated with this archive member.
unsigned getMode() const { return info.getMode(); }
/// This method returns the time at which the archive member was last
/// modified when it was not in the archive.
/// @brief Get the time of last modification of the archive member.
sys::TimeValue getModTime() const { return info.getTimestamp(); }
/// @returns the size of the archive member in bytes.
/// @brief Get the size of the archive member.
uint64_t getSize() const { return info.getSize(); }
/// This method returns the total size of the archive member as it
/// appears on disk. This includes the file content, the header, the
/// long file name if any, and the padding.
/// @brief Get total on-disk member size.
unsigned getMemberSize() const;
/// This method will return a pointer to the in-memory content of the
/// archive member, if it is available. If the data has not been loaded
/// into memory, the return value will be null.
/// @returns a pointer to the member's data.
/// @brief Get the data content of the archive member
const char* getData() const { return data; }
/// @returns true iff the member is a SVR4 (non-LLVM) symbol table
/// @brief Determine if this member is a SVR4 symbol table.
bool isSVR4SymbolTable() const { return flags&SVR4SymbolTableFlag; }
/// @returns true iff the member is a BSD4.4 (non-LLVM) symbol table
/// @brief Determine if this member is a BSD4.4 symbol table.
bool isBSD4SymbolTable() const { return flags&BSD4SymbolTableFlag; }
/// @returns true iff the archive member is the LLVM symbol table
/// @brief Determine if this member is the LLVM symbol table.
bool isLLVMSymbolTable() const { return flags&LLVMSymbolTableFlag; }
/// @returns true iff the archive member is the ar(1) string table
/// @brief Determine if this member is the ar(1) string table.
bool isStringTable() const { return flags&StringTableFlag; }
/// @returns true iff the archive member is a bitcode file.
/// @brief Determine if this member is a bitcode file.
bool isBitcode() const { return flags&BitcodeFlag; }
/// @returns true iff the file name contains a path (directory) component.
/// @brief Determine if the member has a path
bool hasPath() const { return flags&HasPathFlag; }
/// Long filenames are an artifact of the ar(1) file format which allows
/// up to sixteen characters in its header and doesn't allow a path
/// separator character (/). To avoid this, a "long format" member name is
/// allowed that doesn't have this restriction. This method determines if
/// that "long format" is used for this member.
/// @returns true iff the file name uses the long form
/// @brief Determine if the member has a long file name
bool hasLongFilename() const { return flags&HasLongFilenameFlag; }
/// This method returns the status info (like Unix stat(2)) for the archive
/// member. The status info provides the file's size, permissions, and
/// modification time. The contents of the Path::StatusInfo structure, other
/// than the size and modification time, may not have utility on non-Unix
/// systems.
/// @returns the status info for the archive member
/// @brief Obtain the status info for the archive member
const sys::FileStatus &getFileStatus() const { return info; }
/// This method causes the archive member to be replaced with the contents
/// of the file specified by \p File. The contents of \p this will be
/// updated to reflect the new data from \p File. The \p File must exist and
/// be readable on entry to this method.
/// @returns true if an error occurred, false otherwise
/// @brief Replace contents of archive member with a new file.
bool replaceWith(const sys::Path &aFile, std::string* ErrMsg);
/// @}
/// @name Data
/// @{
private:
Archive* parent; ///< Pointer to parent archive
sys::PathWithStatus path; ///< Path of file containing the member
sys::FileStatus info; ///< Status info (size,mode,date)
unsigned flags; ///< Flags about the archive member
const char* data; ///< Data for the member
/// @}
/// @name Constructors
/// @{
public:
/// The default constructor is only used by the Archive's iplist when it
/// constructs the list's sentry node.
ArchiveMember();
private:
/// Used internally by the Archive class to construct an ArchiveMember.
/// The contents of the ArchiveMember are filled out by the Archive class.
explicit ArchiveMember(Archive *PAR);
// So Archive can construct an ArchiveMember
friend class llvm::Archive;
/// @}
};
/// This class defines the interface to LLVM Archive files. The Archive class
/// presents the archive file as an ilist of ArchiveMember objects. The members
/// can be rearranged in any fashion either by directly editing the ilist or by
/// using editing methods on the Archive class (recommended). The Archive
/// class also provides several ways of accessing the archive file for various
/// purposes such as editing and linking. Full symbol table support is provided
/// for loading only those files that resolve symbols. Note that read
/// performance of this library is _crucial_ for performance of JIT type
/// applications and the linkers. Consequently, the implementation of the class
/// is optimized for reading.
class Archive {
/// @name Types
/// @{
public:
/// This is the ilist type over which users may iterate to examine
/// the contents of the archive
/// @brief The ilist type of ArchiveMembers that Archive contains.
typedef iplist<ArchiveMember> MembersList;
/// @brief Forward mutable iterator over ArchiveMember
typedef MembersList::iterator iterator;
/// @brief Forward immutable iterator over ArchiveMember
typedef MembersList::const_iterator const_iterator;
/// @brief Reverse mutable iterator over ArchiveMember
typedef std::reverse_iterator<iterator> reverse_iterator;
/// @brief Reverse immutable iterator over ArchiveMember
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
/// @brief The in-memory version of the symbol table
typedef std::map<std::string,unsigned> SymTabType;
/// @}
/// @name ilist accessor methods
/// @{
public:
inline iterator begin() { return members.begin(); }
inline const_iterator begin() const { return members.begin(); }
inline iterator end () { return members.end(); }
inline const_iterator end () const { return members.end(); }
inline reverse_iterator rbegin() { return members.rbegin(); }
inline const_reverse_iterator rbegin() const { return members.rbegin(); }
inline reverse_iterator rend () { return members.rend(); }
inline const_reverse_iterator rend () const { return members.rend(); }
inline size_t size() const { return members.size(); }
inline bool empty() const { return members.empty(); }
inline const ArchiveMember& front() const { return members.front(); }
inline ArchiveMember& front() { return members.front(); }
inline const ArchiveMember& back() const { return members.back(); }
inline ArchiveMember& back() { return members.back(); }
/// @}
/// @name ilist mutator methods
/// @{
public:
/// This method splices a \p src member from an archive (possibly \p this),
/// to a position just before the member given by \p dest in \p this. When
/// the archive is written, \p src will be written in its new location.
/// @brief Move a member to a new location
inline void splice(iterator dest, Archive& arch, iterator src)
{ return members.splice(dest,arch.members,src); }
/// This method erases a \p target member from the archive. When the
/// archive is written, it will no longer contain \p target. The associated
/// ArchiveMember is deleted.
/// @brief Erase a member.
inline iterator erase(iterator target) { return members.erase(target); }
/// @}
/// @name Constructors
/// @{
public:
/// Create an empty archive file and associate it with the \p Filename. This
/// method does not actually create the archive disk file. It creates an
/// empty Archive object. If the writeToDisk method is called, the archive
/// file \p Filename will be created at that point, with whatever content
/// the returned Archive object has at that time.
/// @returns An Archive* that represents the new archive file.
/// @brief Create an empty Archive.
static Archive* CreateEmpty(
const sys::Path& Filename,///< Name of the archive to (eventually) create.
LLVMContext& C ///< Context to use for global information
);
/// Open an existing archive and load its contents in preparation for
/// editing. After this call, the member ilist is completely populated based
/// on the contents of the archive file. You should use this form of open if
/// you intend to modify the archive or traverse its contents (e.g. for
/// printing).
/// @brief Open and load an archive file
static Archive* OpenAndLoad(
const sys::Path& filePath, ///< The file path to open and load
LLVMContext& C, ///< The context to use for global information
std::string* ErrorMessage ///< An optional error string
);
/// This method opens an existing archive file from \p Filename and reads in
/// its symbol table without reading in any of the archive's members. This
/// reduces both I/O and cpu time in opening the archive if it is to be used
/// solely for symbol lookup (e.g. during linking). The \p Filename must
/// exist and be an archive file or an error will be returned. This form
/// of opening the archive is intended for read-only operations that need to
/// locate members via the symbol table for link editing. Since the archve
/// members are not read by this method, the archive will appear empty upon
/// return. If editing operations are performed on the archive, they will
/// completely replace the contents of the archive! It is recommended that
/// if this form of opening the archive is used that only the symbol table
/// lookup methods (getSymbolTable, findModuleDefiningSymbol, and
/// findModulesDefiningSymbols) be used.
/// @returns an Archive* that represents the archive file, or null on error.
/// @brief Open an existing archive and load its symbols.
static Archive* OpenAndLoadSymbols(
const sys::Path& Filename, ///< Name of the archive file to open
LLVMContext& C, ///< The context to use for global info
std::string* ErrorMessage=0 ///< An optional error string
);
/// This destructor cleans up the Archive object, releases all memory, and
/// closes files. It does nothing with the archive file on disk. If you
/// haven't used the writeToDisk method by the time the destructor is
/// called, all changes to the archive will be lost.
/// @brief Destruct in-memory archive
~Archive();
/// @}
/// @name Accessors
/// @{
public:
/// @returns the path to the archive file.
/// @brief Get the archive path.
const sys::Path& getPath() { return archPath; }
/// This method is provided so that editing methods can be invoked directly
/// on the Archive's iplist of ArchiveMember. However, it is recommended
/// that the usual STL style iterator interface be used instead.
/// @returns the iplist of ArchiveMember
/// @brief Get the iplist of the members
MembersList& getMembers() { return members; }
/// This method allows direct query of the Archive's symbol table. The
/// symbol table is a std::map of std::string (the symbol) to unsigned (the
/// file offset). Note that for efficiency reasons, the offset stored in
/// the symbol table is not the actual offset. It is the offset from the
/// beginning of the first "real" file member (after the symbol table). Use
/// the getFirstFileOffset() to obtain that offset and add this value to the
/// offset in the symbol table to obtain the real file offset. Note that
/// there is purposefully no interface provided by Archive to look up
/// members by their offset. Use the findModulesDefiningSymbols and
/// findModuleDefiningSymbol methods instead.
/// @returns the Archive's symbol table.
/// @brief Get the archive's symbol table
const SymTabType& getSymbolTable() { return symTab; }
/// This method returns the offset in the archive file to the first "real"
/// file member. Archive files, on disk, have a signature and might have a
/// symbol table that precedes the first actual file member. This method
/// allows you to determine what the size of those fields are.
/// @returns the offset to the first "real" file member in the archive.
/// @brief Get the offset to the first "real" file member in the archive.
unsigned getFirstFileOffset() { return firstFileOffset; }
/// This method will scan the archive for bitcode modules, interpret them
/// and return a vector of the instantiated modules in \p Modules. If an
/// error occurs, this method will return true. If \p ErrMessage is not null
/// and an error occurs, \p *ErrMessage will be set to a string explaining
/// the error that occurred.
/// @returns true if an error occurred
/// @brief Instantiate all the bitcode modules located in the archive
bool getAllModules(std::vector<Module*>& Modules, std::string* ErrMessage);
/// This accessor looks up the \p symbol in the archive's symbol table and
/// returns the associated module that defines that symbol. This method can
/// be called as many times as necessary. This is handy for linking the
/// archive into another module based on unresolved symbols. Note that the
/// Module returned by this accessor should not be deleted by the caller. It
/// is managed internally by the Archive class. It is possible that multiple
/// calls to this accessor will return the same Module instance because the
/// associated module defines multiple symbols.
/// @returns The Module* found or null if the archive does not contain a
/// module that defines the \p symbol.
/// @brief Look up a module by symbol name.
Module* findModuleDefiningSymbol(
const std::string& symbol, ///< Symbol to be sought
std::string* ErrMessage ///< Error message storage, if non-zero
);
/// This method is similar to findModuleDefiningSymbol but allows lookup of
/// more than one symbol at a time. If \p symbols contains a list of
/// undefined symbols in some module, then calling this method is like
/// making one complete pass through the archive to resolve symbols but is
/// more efficient than looking at the individual members. Note that on
/// exit, the symbols resolved by this method will be removed from \p
/// symbols to ensure they are not re-searched on a subsequent call. If
/// you need to retain the list of symbols, make a copy.
/// @brief Look up multiple symbols in the archive.
bool findModulesDefiningSymbols(
std::set<std::string>& symbols, ///< Symbols to be sought
SmallVectorImpl<Module*>& modules, ///< The modules matching \p symbols
std::string* ErrMessage ///< Error msg storage, if non-zero
);
/// This method determines whether the archive is a properly formed llvm
/// bitcode archive. It first makes sure the symbol table has been loaded
/// and has a non-zero size. If it does, then it is an archive. If not,
/// then it tries to load all the bitcode modules of the archive. Finally,
/// it returns whether it was successful.
/// @returns true if the archive is a proper llvm bitcode archive
/// @brief Determine whether the archive is a proper llvm bitcode archive.
bool isBitcodeArchive();
/// @}
/// @name Mutators
/// @{
public:
/// This method is the only way to get the archive written to disk. It
/// creates or overwrites the file specified when \p this was created
/// or opened. The arguments provide options for writing the archive. If
/// \p CreateSymbolTable is true, the archive is scanned for bitcode files
/// and a symbol table of the externally visible function and global
/// variable names is created. If \p TruncateNames is true, the names of the
/// archive members will have their path component stripped and the file
/// name will be truncated at 15 characters. If \p Compress is specified,
/// all archive members will be compressed before being written. If
/// \p PrintSymTab is true, the symbol table will be printed to std::cout.
/// @returns true if an error occurred, \p error set to error message;
/// returns false if the writing succeeded.
/// @brief Write (possibly modified) archive contents to disk
bool writeToDisk(
bool CreateSymbolTable=false, ///< Create Symbol table
bool TruncateNames=false, ///< Truncate the filename to 15 chars
std::string* ErrMessage=0 ///< If non-null, where error msg is set
);
/// This method adds a new file to the archive. The \p filename is examined
/// to determine just enough information to create an ArchiveMember object
/// which is then inserted into the Archive object's ilist at the location
/// given by \p where.
/// @returns true if an error occurred, false otherwise
/// @brief Add a file to the archive.
bool addFileBefore(
const sys::Path& filename, ///< The file to be added
iterator where, ///< Insertion point
std::string* ErrMsg ///< Optional error message location
);
/// @}
/// @name Implementation
/// @{
protected:
/// @brief Construct an Archive for \p filename and optionally map it
/// into memory.
explicit Archive(const sys::Path& filename, LLVMContext& C);
/// @param data The symbol table data to be parsed
/// @param len The length of the symbol table data
/// @param error Set to address of a std::string to get error messages
/// @returns false on error
/// @brief Parse the symbol table at \p data.
bool parseSymbolTable(const void* data,unsigned len,std::string* error);
/// @returns A fully populated ArchiveMember or 0 if an error occurred.
/// @brief Parse the header of a member starting at \p At
ArchiveMember* parseMemberHeader(
const char*&At, ///< The pointer to the location we're parsing
const char*End, ///< The pointer to the end of the archive
std::string* error ///< Optional error message catcher
);
/// @param ErrMessage Set to address of a std::string to get error messages
/// @returns false on error
/// @brief Check that the archive signature is correct
bool checkSignature(std::string* ErrMessage);
/// @param ErrMessage Set to address of a std::string to get error messages
/// @returns false on error
/// @brief Load the entire archive.
bool loadArchive(std::string* ErrMessage);
/// @param ErrMessage Set to address of a std::string to get error messages
/// @returns false on error
/// @brief Load just the symbol table.
bool loadSymbolTable(std::string* ErrMessage);
/// @brief Write the symbol table to an ofstream.
void writeSymbolTable(std::ofstream& ARFile);
/// Writes one ArchiveMember to an ofstream. If an error occurs, returns
/// false, otherwise true. If an error occurs and error is non-null then
/// it will be set to an error message.
/// @returns false if writing member succeeded,
/// returns true if writing member failed, \p error set to error message.
bool writeMember(
const ArchiveMember& member, ///< The member to be written
std::ofstream& ARFile, ///< The file to write member onto
bool CreateSymbolTable, ///< Should symbol table be created?
bool TruncateNames, ///< Should names be truncated to 11 chars?
std::string* ErrMessage ///< If non-null, place were error msg is set
);
/// @brief Fill in an ArchiveMemberHeader from ArchiveMember.
bool fillHeader(const ArchiveMember&mbr,
ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const;
/// @brief Maps archive into memory
bool mapToMemory(std::string* ErrMsg);
/// @brief Frees all the members and unmaps the archive file.
void cleanUpMemory();
/// This type is used to keep track of bitcode modules loaded from the
/// symbol table. It maps the file offset to a pair that consists of the
/// associated ArchiveMember and the Module.
/// @brief Module mapping type
typedef std::map<unsigned,std::pair<Module*,ArchiveMember*> >
ModuleMap;
/// @}
/// @name Data
/// @{
protected:
sys::Path archPath; ///< Path to the archive file we read/write
MembersList members; ///< The ilist of ArchiveMember
MemoryBuffer *mapfile; ///< Raw Archive contents mapped into memory
const char* base; ///< Base of the memory mapped file data
SymTabType symTab; ///< The symbol table
std::string strtab; ///< The string table for long file names
unsigned symTabSize; ///< Size in bytes of symbol table
unsigned firstFileOffset; ///< Offset to first normal file.
ModuleMap modules; ///< The modules loaded via symbol lookup.
ArchiveMember* foreignST; ///< This holds the foreign symbol table.
LLVMContext& Context; ///< This holds global data.
/// @}
/// @name Hidden
/// @{
private:
Archive() LLVM_DELETED_FUNCTION;
Archive(const Archive&) LLVM_DELETED_FUNCTION;
Archive& operator=(const Archive&) LLVM_DELETED_FUNCTION;
/// @}
};
} // End llvm namespace
#endif

View File

@@ -0,0 +1,187 @@
//===- BitCodes.h - Enum values for the bitcode format ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header Bitcode enum values.
//
// The enum values defined in this file should be considered permanent. If
// new features are added, they should have values added at the end of the
// respective lists.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_BITCODES_H
#define LLVM_BITCODE_BITCODES_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
namespace llvm {
namespace bitc {
enum StandardWidths {
BlockIDWidth = 8, // We use VBR-8 for block IDs.
CodeLenWidth = 4, // Codelen are VBR-4.
BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 16GB per block.
};
// The standard abbrev namespace always has a way to exit a block, enter a
// nested block, define abbrevs, and define an unabbreviated record.
enum FixedAbbrevIDs {
END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode.
ENTER_SUBBLOCK = 1,
/// DEFINE_ABBREV - Defines an abbrev for the current block. It consists
/// of a vbr5 for # operand infos. Each operand info is emitted with a
/// single bit to indicate if it is a literal encoding. If so, the value is
/// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed
/// by the info value as a vbr5 if needed.
DEFINE_ABBREV = 2,
// UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by
// a vbr6 for the # operands, followed by vbr6's for each operand.
UNABBREV_RECORD = 3,
// This is not a code, this is a marker for the first abbrev assignment.
FIRST_APPLICATION_ABBREV = 4
};
/// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO
/// block, which contains metadata about other blocks in the file.
enum StandardBlockIDs {
/// BLOCKINFO_BLOCK is used to define metadata about blocks, for example,
/// standard abbrevs that should be available to all blocks of a specified
/// ID.
BLOCKINFO_BLOCK_ID = 0,
// Block IDs 1-7 are reserved for future expansion.
FIRST_APPLICATION_BLOCKID = 8
};
/// BlockInfoCodes - The blockinfo block contains metadata about user-defined
/// blocks.
enum BlockInfoCodes {
// DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd
// block, instead of the BlockInfo block.
BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#]
BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name]
BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME:
// [id, name]
};
} // End bitc namespace
/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
/// This is actually a union of two different things:
/// 1. It could be a literal integer value ("the operand is always 17").
/// 2. It could be an encoding specification ("this operand encoded like so").
///
class BitCodeAbbrevOp {
uint64_t Val; // A literal value or data for an encoding.
bool IsLiteral : 1; // Indicate whether this is a literal value or not.
unsigned Enc : 3; // The encoding to use.
public:
enum Encoding {
Fixed = 1, // A fixed width field, Val specifies number of bits.
VBR = 2, // A VBR field where Val specifies the width of each chunk.
Array = 3, // A sequence of fields, next field species elt encoding.
Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._].
Blob = 5 // 32-bit aligned array of 8-bit characters.
};
explicit BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {}
explicit BitCodeAbbrevOp(Encoding E, uint64_t Data = 0)
: Val(Data), IsLiteral(false), Enc(E) {}
bool isLiteral() const { return IsLiteral; }
bool isEncoding() const { return !IsLiteral; }
// Accessors for literals.
uint64_t getLiteralValue() const { assert(isLiteral()); return Val; }
// Accessors for encoding info.
Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; }
uint64_t getEncodingData() const {
assert(isEncoding() && hasEncodingData());
return Val;
}
bool hasEncodingData() const { return hasEncodingData(getEncoding()); }
static bool hasEncodingData(Encoding E) {
switch (E) {
case Fixed:
case VBR:
return true;
case Array:
case Char6:
case Blob:
return false;
}
llvm_unreachable("Invalid encoding");
}
/// isChar6 - Return true if this character is legal in the Char6 encoding.
static bool isChar6(char C) {
if (C >= 'a' && C <= 'z') return true;
if (C >= 'A' && C <= 'Z') return true;
if (C >= '0' && C <= '9') return true;
if (C == '.' || C == '_') return true;
return false;
}
static unsigned EncodeChar6(char C) {
if (C >= 'a' && C <= 'z') return C-'a';
if (C >= 'A' && C <= 'Z') return C-'A'+26;
if (C >= '0' && C <= '9') return C-'0'+26+26;
if (C == '.') return 62;
if (C == '_') return 63;
llvm_unreachable("Not a value Char6 character!");
}
static char DecodeChar6(unsigned V) {
assert((V & ~63) == 0 && "Not a Char6 encoded character!");
if (V < 26) return V+'a';
if (V < 26+26) return V-26+'A';
if (V < 26+26+10) return V-26-26+'0';
if (V == 62) return '.';
if (V == 63) return '_';
llvm_unreachable("Not a value Char6 character!");
}
};
template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; };
/// BitCodeAbbrev - This class represents an abbreviation record. An
/// abbreviation allows a complex record that has redundancy to be stored in a
/// specialized format instead of the fully-general, fully-vbr, format.
class BitCodeAbbrev {
SmallVector<BitCodeAbbrevOp, 32> OperandList;
unsigned char RefCount; // Number of things using this.
~BitCodeAbbrev() {}
public:
BitCodeAbbrev() : RefCount(1) {}
void addRef() { ++RefCount; }
void dropRef() { if (--RefCount == 0) delete this; }
unsigned getNumOperandInfos() const {
return static_cast<unsigned>(OperandList.size());
}
const BitCodeAbbrevOp &getOperandInfo(unsigned N) const {
return OperandList[N];
}
void Add(const BitCodeAbbrevOp &OpInfo) {
OperandList.push_back(OpInfo);
}
};
} // End llvm namespace
#endif

View File

@@ -0,0 +1,558 @@
//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header defines the BitstreamReader class. This class can be used to
// read an arbitrary bitstream, regardless of its contents.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_BITSTREAMREADER_H
#define LLVM_BITCODE_BITSTREAMREADER_H
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/StreamableMemoryObject.h"
#include <climits>
#include <string>
#include <vector>
namespace llvm {
class Deserializer;
/// BitstreamReader - This class is used to read from an LLVM bitcode stream,
/// maintaining information that is global to decoding the entire file. While
/// a file is being read, multiple cursors can be independently advanced or
/// skipped around within the file. These are represented by the
/// BitstreamCursor class.
class BitstreamReader {
public:
/// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
/// These describe abbreviations that all blocks of the specified ID inherit.
struct BlockInfo {
unsigned BlockID;
std::vector<BitCodeAbbrev*> Abbrevs;
std::string Name;
std::vector<std::pair<unsigned, std::string> > RecordNames;
};
private:
OwningPtr<StreamableMemoryObject> BitcodeBytes;
std::vector<BlockInfo> BlockInfoRecords;
/// IgnoreBlockInfoNames - This is set to true if we don't care about the
/// block/record name information in the BlockInfo block. Only llvm-bcanalyzer
/// uses this.
bool IgnoreBlockInfoNames;
BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION;
void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION;
public:
BitstreamReader() : IgnoreBlockInfoNames(true) {
}
BitstreamReader(const unsigned char *Start, const unsigned char *End) {
IgnoreBlockInfoNames = true;
init(Start, End);
}
BitstreamReader(StreamableMemoryObject *bytes) {
BitcodeBytes.reset(bytes);
}
void init(const unsigned char *Start, const unsigned char *End) {
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
}
StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
~BitstreamReader() {
// Free the BlockInfoRecords.
while (!BlockInfoRecords.empty()) {
BlockInfo &Info = BlockInfoRecords.back();
// Free blockinfo abbrev info.
for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
i != e; ++i)
Info.Abbrevs[i]->dropRef();
BlockInfoRecords.pop_back();
}
}
/// CollectBlockInfoNames - This is called by clients that want block/record
/// name information.
void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
//===--------------------------------------------------------------------===//
// Block Manipulation
//===--------------------------------------------------------------------===//
/// hasBlockInfoRecords - Return true if we've already read and processed the
/// block info block for this Bitstream. We only process it for the first
/// cursor that walks over it.
bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
/// getBlockInfo - If there is block info for the specified ID, return it,
/// otherwise return null.
const BlockInfo *getBlockInfo(unsigned BlockID) const {
// Common case, the most recent entry matches BlockID.
if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
return &BlockInfoRecords.back();
for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
i != e; ++i)
if (BlockInfoRecords[i].BlockID == BlockID)
return &BlockInfoRecords[i];
return 0;
}
BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
if (const BlockInfo *BI = getBlockInfo(BlockID))
return *const_cast<BlockInfo*>(BI);
// Otherwise, add a new record.
BlockInfoRecords.push_back(BlockInfo());
BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back();
}
};
/// BitstreamEntry - When advancing through a bitstream cursor, each advance can
/// discover a few different kinds of entries:
/// Error - Malformed bitcode was found.
/// EndBlock - We've reached the end of the current block, (or the end of the
/// file, which is treated like a series of EndBlock records.
/// SubBlock - This is the start of a new subblock of a specific ID.
/// Record - This is a record with a specific AbbrevID.
///
struct BitstreamEntry {
enum {
Error,
EndBlock,
SubBlock,
Record
} Kind;
unsigned ID;
static BitstreamEntry getError() {
BitstreamEntry E; E.Kind = Error; return E;
}
static BitstreamEntry getEndBlock() {
BitstreamEntry E; E.Kind = EndBlock; return E;
}
static BitstreamEntry getSubBlock(unsigned ID) {
BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
}
static BitstreamEntry getRecord(unsigned AbbrevID) {
BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
}
};
/// BitstreamCursor - This represents a position within a bitcode file. There
/// may be multiple independent cursors reading within one bitstream, each
/// maintaining their own local state.
///
/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
/// be passed by value.
class BitstreamCursor {
friend class Deserializer;
BitstreamReader *BitStream;
size_t NextChar;
/// CurWord/word_t - This is the current data we have pulled from the stream
/// but have not returned to the client. This is specifically and
/// intentionally defined to follow the word size of the host machine for
/// efficiency. We use word_t in places that are aware of this to make it
/// perfectly explicit what is going on.
typedef uint32_t word_t;
word_t CurWord;
/// BitsInCurWord - This is the number of bits in CurWord that are valid. This
/// is always from [0...31/63] inclusive (depending on word size).
unsigned BitsInCurWord;
// CurCodeSize - This is the declared size of code values used for the current
// block, in bits.
unsigned CurCodeSize;
/// CurAbbrevs - Abbrevs installed at in this block.
std::vector<BitCodeAbbrev*> CurAbbrevs;
struct Block {
unsigned PrevCodeSize;
std::vector<BitCodeAbbrev*> PrevAbbrevs;
explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
};
/// BlockScope - This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
public:
BitstreamCursor() : BitStream(0), NextChar(0) {
}
BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) {
operator=(RHS);
}
explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) {
NextChar = 0;
CurWord = 0;
BitsInCurWord = 0;
CurCodeSize = 2;
}
void init(BitstreamReader &R) {
freeState();
BitStream = &R;
NextChar = 0;
CurWord = 0;
BitsInCurWord = 0;
CurCodeSize = 2;
}
~BitstreamCursor() {
freeState();
}
void operator=(const BitstreamCursor &RHS);
void freeState();
bool isEndPos(size_t pos) {
return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
}
bool canSkipToPos(size_t pos) const {
// pos can be skipped to if it is a valid address or one byte past the end.
return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
static_cast<uint64_t>(pos - 1));
}
uint32_t getWord(size_t pos) {
uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL);
return *reinterpret_cast<support::ulittle32_t *>(buf);
}
bool AtEndOfStream() {
return BitsInCurWord == 0 && isEndPos(NextChar);
}
/// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
unsigned getAbbrevIDWidth() const { return CurCodeSize; }
/// GetCurrentBitNo - Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
return NextChar*CHAR_BIT - BitsInCurWord;
}
BitstreamReader *getBitStreamReader() {
return BitStream;
}
const BitstreamReader *getBitStreamReader() const {
return BitStream;
}
/// Flags that modify the behavior of advance().
enum {
/// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does
/// not automatically pop the block scope when the end of a block is
/// reached.
AF_DontPopBlockAtEnd = 1,
/// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are
/// returned just like normal records.
AF_DontAutoprocessAbbrevs = 2
};
/// advance - Advance the current bitstream, returning the next entry in the
/// stream.
BitstreamEntry advance(unsigned Flags = 0) {
while (1) {
unsigned Code = ReadCode();
if (Code == bitc::END_BLOCK) {
// Pop the end of the block unless Flags tells us not to.
if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
return BitstreamEntry::getError();
return BitstreamEntry::getEndBlock();
}
if (Code == bitc::ENTER_SUBBLOCK)
return BitstreamEntry::getSubBlock(ReadSubBlockID());
if (Code == bitc::DEFINE_ABBREV &&
!(Flags & AF_DontAutoprocessAbbrevs)) {
// We read and accumulate abbrev's, the client can't do anything with
// them anyway.
ReadAbbrevRecord();
continue;
}
return BitstreamEntry::getRecord(Code);
}
}
/// advanceSkippingSubblocks - This is a convenience function for clients that
/// don't expect any subblocks. This just skips over them automatically.
BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
while (1) {
// If we found a normal entry, return it.
BitstreamEntry Entry = advance(Flags);
if (Entry.Kind != BitstreamEntry::SubBlock)
return Entry;
// If we found a sub-block, just skip over it and check the next entry.
if (SkipBlock())
return BitstreamEntry::getError();
}
}
/// JumpToBit - Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
assert(canSkipToPos(ByteNo) && "Invalid location");
// Move the cursor to the right word.
NextChar = ByteNo;
BitsInCurWord = 0;
CurWord = 0;
// Skip over any bits that are already consumed.
if (WordBitNo) {
if (sizeof(word_t) > 4)
Read64(WordBitNo);
else
Read(WordBitNo);
}
}
uint32_t Read(unsigned NumBits) {
assert(NumBits && NumBits <= 32 &&
"Cannot return zero or more than 32 bits!");
// If the field is fully contained by CurWord, return it quickly.
if (BitsInCurWord >= NumBits) {
uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits));
CurWord >>= NumBits;
BitsInCurWord -= NumBits;
return R;
}
// If we run out of data, stop at the end of the stream.
if (isEndPos(NextChar)) {
CurWord = 0;
BitsInCurWord = 0;
return 0;
}
uint32_t R = uint32_t(CurWord);
// Read the next word from the stream.
uint8_t Array[sizeof(word_t)] = {0};
BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array),
Array, NULL);
// Handle big-endian byte-swapping if necessary.
support::detail::packed_endian_specific_integral
<word_t, support::little, support::unaligned> EndianValue;
memcpy(&EndianValue, Array, sizeof(Array));
CurWord = EndianValue;
NextChar += sizeof(word_t);
// Extract NumBits-BitsInCurWord from what we just read.
unsigned BitsLeft = NumBits-BitsInCurWord;
// Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive.
R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft)))
<< BitsInCurWord);
// BitsLeft bits have just been used up from CurWord. BitsLeft is in the
// range [1..32]/[1..64] so be careful how we shift.
if (BitsLeft != sizeof(word_t)*8)
CurWord >>= BitsLeft;
else
CurWord = 0;
BitsInCurWord = sizeof(word_t)*8-BitsLeft;
return R;
}
uint64_t Read64(unsigned NumBits) {
if (NumBits <= 32) return Read(NumBits);
uint64_t V = Read(32);
return V | (uint64_t)Read(NumBits-32) << 32;
}
uint32_t ReadVBR(unsigned NumBits) {
uint32_t Piece = Read(NumBits);
if ((Piece & (1U << (NumBits-1))) == 0)
return Piece;
uint32_t Result = 0;
unsigned NextBit = 0;
while (1) {
Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;
if ((Piece & (1U << (NumBits-1))) == 0)
return Result;
NextBit += NumBits-1;
Piece = Read(NumBits);
}
}
// ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The
// chunk size of the VBR must still be <= 32 bits though.
uint64_t ReadVBR64(unsigned NumBits) {
uint32_t Piece = Read(NumBits);
if ((Piece & (1U << (NumBits-1))) == 0)
return uint64_t(Piece);
uint64_t Result = 0;
unsigned NextBit = 0;
while (1) {
Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;
if ((Piece & (1U << (NumBits-1))) == 0)
return Result;
NextBit += NumBits-1;
Piece = Read(NumBits);
}
}
private:
void SkipToFourByteBoundary() {
// If word_t is 64-bits and if we've read less than 32 bits, just dump
// the bits we have up to the next 32-bit boundary.
if (sizeof(word_t) > 4 &&
BitsInCurWord >= 32) {
CurWord >>= BitsInCurWord-32;
BitsInCurWord = 32;
return;
}
BitsInCurWord = 0;
CurWord = 0;
}
public:
unsigned ReadCode() {
return Read(CurCodeSize);
}
// Block header:
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
/// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for
/// the block.
unsigned ReadSubBlockID() {
return ReadVBR(bitc::BlockIDWidth);
}
/// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip
/// over the body of this block. If the block record is malformed, return
/// true.
bool SkipBlock() {
// Read and ignore the codelen value. Since we are skipping this block, we
// don't care what code widths are used inside of it.
ReadVBR(bitc::CodeLenWidth);
SkipToFourByteBoundary();
unsigned NumFourBytes = Read(bitc::BlockSizeWidth);
// Check that the block wasn't partially defined, and that the offset isn't
// bogus.
size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8;
if (AtEndOfStream() || !canSkipToPos(SkipTo/8))
return true;
JumpToBit(SkipTo);
return false;
}
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
/// the block, and return true if the block has an error.
bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0);
bool ReadBlockEnd() {
if (BlockScope.empty()) return true;
// Block tail:
// [END_BLOCK, <align4bytes>]
SkipToFourByteBoundary();
popBlockScope();
return false;
}
private:
void popBlockScope() {
CurCodeSize = BlockScope.back().PrevCodeSize;
// Delete abbrevs from popped scope.
for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
i != e; ++i)
CurAbbrevs[i]->dropRef();
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
BlockScope.pop_back();
}
//===--------------------------------------------------------------------===//
// Record Processing
//===--------------------------------------------------------------------===//
private:
void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op,
SmallVectorImpl<uint64_t> &Vals);
void readAbbreviatedField(const BitCodeAbbrevOp &Op,
SmallVectorImpl<uint64_t> &Vals);
void skipAbbreviatedField(const BitCodeAbbrevOp &Op);
public:
/// getAbbrev - Return the abbreviation for the specified AbbrevId.
const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
return CurAbbrevs[AbbrevNo];
}
/// skipRecord - Read the current record and discard it.
void skipRecord(unsigned AbbrevID);
unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
StringRef *Blob = 0);
//===--------------------------------------------------------------------===//
// Abbrev Processing
//===--------------------------------------------------------------------===//
void ReadAbbrevRecord();
bool ReadBlockInfoBlock();
};
} // End llvm namespace
#endif

View File

@@ -0,0 +1,548 @@
//===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header defines the BitstreamWriter class. This class can be used to
// write an arbitrary bitstream, regardless of its contents.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_BITSTREAMWRITER_H
#define LLVM_BITCODE_BITSTREAMWRITER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitCodes.h"
#include <vector>
namespace llvm {
class BitstreamWriter {
SmallVectorImpl<char> &Out;
/// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use.
unsigned CurBit;
/// CurValue - The current value. Only bits < CurBit are valid.
uint32_t CurValue;
/// CurCodeSize - This is the declared size of code values used for the
/// current block, in bits.
unsigned CurCodeSize;
/// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently
/// selected BLOCK ID.
unsigned BlockInfoCurBID;
/// CurAbbrevs - Abbrevs installed at in this block.
std::vector<BitCodeAbbrev*> CurAbbrevs;
struct Block {
unsigned PrevCodeSize;
unsigned StartSizeWord;
std::vector<BitCodeAbbrev*> PrevAbbrevs;
Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}
};
/// BlockScope - This tracks the current blocks that we have entered.
std::vector<Block> BlockScope;
/// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
/// These describe abbreviations that all blocks of the specified ID inherit.
struct BlockInfo {
unsigned BlockID;
std::vector<BitCodeAbbrev*> Abbrevs;
};
std::vector<BlockInfo> BlockInfoRecords;
// BackpatchWord - Backpatch a 32-bit word in the output with the specified
// value.
void BackpatchWord(unsigned ByteNo, unsigned NewWord) {
Out[ByteNo++] = (unsigned char)(NewWord >> 0);
Out[ByteNo++] = (unsigned char)(NewWord >> 8);
Out[ByteNo++] = (unsigned char)(NewWord >> 16);
Out[ByteNo ] = (unsigned char)(NewWord >> 24);
}
void WriteByte(unsigned char Value) {
Out.push_back(Value);
}
void WriteWord(unsigned Value) {
unsigned char Bytes[4] = {
(unsigned char)(Value >> 0),
(unsigned char)(Value >> 8),
(unsigned char)(Value >> 16),
(unsigned char)(Value >> 24) };
Out.append(&Bytes[0], &Bytes[4]);
}
unsigned GetBufferOffset() const {
return Out.size();
}
unsigned GetWordIndex() const {
unsigned Offset = GetBufferOffset();
assert((Offset & 3) == 0 && "Not 32-bit aligned");
return Offset / 4;
}
public:
explicit BitstreamWriter(SmallVectorImpl<char> &O)
: Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {}
~BitstreamWriter() {
assert(CurBit == 0 && "Unflused data remaining");
assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
// Free the BlockInfoRecords.
while (!BlockInfoRecords.empty()) {
BlockInfo &Info = BlockInfoRecords.back();
// Free blockinfo abbrev info.
for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
i != e; ++i)
Info.Abbrevs[i]->dropRef();
BlockInfoRecords.pop_back();
}
}
/// \brief Retrieve the current position in the stream, in bits.
uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
//===--------------------------------------------------------------------===//
// Basic Primitives for emitting bits to the stream.
//===--------------------------------------------------------------------===//
void Emit(uint32_t Val, unsigned NumBits) {
assert(NumBits && NumBits <= 32 && "Invalid value size!");
assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!");
CurValue |= Val << CurBit;
if (CurBit + NumBits < 32) {
CurBit += NumBits;
return;
}
// Add the current word.
WriteWord(CurValue);
if (CurBit)
CurValue = Val >> (32-CurBit);
else
CurValue = 0;
CurBit = (CurBit+NumBits) & 31;
}
void Emit64(uint64_t Val, unsigned NumBits) {
if (NumBits <= 32)
Emit((uint32_t)Val, NumBits);
else {
Emit((uint32_t)Val, 32);
Emit((uint32_t)(Val >> 32), NumBits-32);
}
}
void FlushToWord() {
if (CurBit) {
WriteWord(CurValue);
CurBit = 0;
CurValue = 0;
}
}
void EmitVBR(uint32_t Val, unsigned NumBits) {
assert(NumBits <= 32 && "Too many bits to emit!");
uint32_t Threshold = 1U << (NumBits-1);
// Emit the bits with VBR encoding, NumBits-1 bits at a time.
while (Val >= Threshold) {
Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
Val >>= NumBits-1;
}
Emit(Val, NumBits);
}
void EmitVBR64(uint64_t Val, unsigned NumBits) {
assert(NumBits <= 32 && "Too many bits to emit!");
if ((uint32_t)Val == Val)
return EmitVBR((uint32_t)Val, NumBits);
uint32_t Threshold = 1U << (NumBits-1);
// Emit the bits with VBR encoding, NumBits-1 bits at a time.
while (Val >= Threshold) {
Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) |
(1 << (NumBits-1)), NumBits);
Val >>= NumBits-1;
}
Emit((uint32_t)Val, NumBits);
}
/// EmitCode - Emit the specified code.
void EmitCode(unsigned Val) {
Emit(Val, CurCodeSize);
}
//===--------------------------------------------------------------------===//
// Block Manipulation
//===--------------------------------------------------------------------===//
/// getBlockInfo - If there is block info for the specified ID, return it,
/// otherwise return null.
BlockInfo *getBlockInfo(unsigned BlockID) {
// Common case, the most recent entry matches BlockID.
if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
return &BlockInfoRecords.back();
for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
i != e; ++i)
if (BlockInfoRecords[i].BlockID == BlockID)
return &BlockInfoRecords[i];
return 0;
}
void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
// Block header:
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
EmitCode(bitc::ENTER_SUBBLOCK);
EmitVBR(BlockID, bitc::BlockIDWidth);
EmitVBR(CodeLen, bitc::CodeLenWidth);
FlushToWord();
unsigned BlockSizeWordIndex = GetWordIndex();
unsigned OldCodeSize = CurCodeSize;
// Emit a placeholder, which will be replaced when the block is popped.
Emit(0, bitc::BlockSizeWidth);
CurCodeSize = CodeLen;
// Push the outer block's abbrev set onto the stack, start out with an
// empty abbrev set.
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex));
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
// If there is a blockinfo for this BlockID, add all the predefined abbrevs
// to the abbrev list.
if (BlockInfo *Info = getBlockInfo(BlockID)) {
for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size());
i != e; ++i) {
CurAbbrevs.push_back(Info->Abbrevs[i]);
Info->Abbrevs[i]->addRef();
}
}
}
void ExitBlock() {
assert(!BlockScope.empty() && "Block scope imbalance!");
// Delete all abbrevs.
for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
i != e; ++i)
CurAbbrevs[i]->dropRef();
const Block &B = BlockScope.back();
// Block tail:
// [END_BLOCK, <align4bytes>]
EmitCode(bitc::END_BLOCK);
FlushToWord();
// Compute the size of the block, in words, not counting the size field.
unsigned SizeInWords = GetWordIndex() - B.StartSizeWord - 1;
unsigned ByteNo = B.StartSizeWord*4;
// Update the block size field in the header of this sub-block.
BackpatchWord(ByteNo, SizeInWords);
// Restore the inner block's code size and abbrev table.
CurCodeSize = B.PrevCodeSize;
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
BlockScope.pop_back();
}
//===--------------------------------------------------------------------===//
// Record Emission
//===--------------------------------------------------------------------===//
private:
/// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev
/// record. This is a no-op, since the abbrev specifies the literal to use.
template<typename uintty>
void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) {
assert(Op.isLiteral() && "Not a literal");
// If the abbrev specifies the literal value to use, don't emit
// anything.
assert(V == Op.getLiteralValue() &&
"Invalid abbrev for record!");
}
/// EmitAbbreviatedField - Emit a single scalar field value with the specified
/// encoding.
template<typename uintty>
void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) {
assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!");
// Encode the value as we are commanded.
switch (Op.getEncoding()) {
default: llvm_unreachable("Unknown encoding!");
case BitCodeAbbrevOp::Fixed:
if (Op.getEncodingData())
Emit((unsigned)V, (unsigned)Op.getEncodingData());
break;
case BitCodeAbbrevOp::VBR:
if (Op.getEncodingData())
EmitVBR64(V, (unsigned)Op.getEncodingData());
break;
case BitCodeAbbrevOp::Char6:
Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6);
break;
}
}
/// EmitRecordWithAbbrevImpl - This is the core implementation of the record
/// emission code. If BlobData is non-null, then it specifies an array of
/// data that should be emitted as part of the Blob or Array operand that is
/// known to exist at the end of the record.
template<typename uintty>
void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
StringRef Blob) {
const char *BlobData = Blob.data();
unsigned BlobLen = (unsigned) Blob.size();
unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo];
EmitCode(Abbrev);
unsigned RecordIdx = 0;
for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
i != e; ++i) {
const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
if (Op.isLiteral()) {
assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
EmitAbbreviatedLiteral(Op, Vals[RecordIdx]);
++RecordIdx;
} else if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
// Array case.
assert(i+2 == e && "array op not second to last?");
const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
// If this record has blob data, emit it, otherwise we must have record
// entries to encode this way.
if (BlobData) {
assert(RecordIdx == Vals.size() &&
"Blob data and record entries specified for array!");
// Emit a vbr6 to indicate the number of elements present.
EmitVBR(static_cast<uint32_t>(BlobLen), 6);
// Emit each field.
for (unsigned i = 0; i != BlobLen; ++i)
EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]);
// Know that blob data is consumed for assertion below.
BlobData = 0;
} else {
// Emit a vbr6 to indicate the number of elements present.
EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
// Emit each field.
for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)
EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
}
} else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) {
// If this record has blob data, emit it, otherwise we must have record
// entries to encode this way.
// Emit a vbr6 to indicate the number of elements present.
if (BlobData) {
EmitVBR(static_cast<uint32_t>(BlobLen), 6);
assert(RecordIdx == Vals.size() &&
"Blob data and record entries specified for blob operand!");
} else {
EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
}
// Flush to a 32-bit alignment boundary.
FlushToWord();
// Emit each field as a literal byte.
if (BlobData) {
for (unsigned i = 0; i != BlobLen; ++i)
WriteByte((unsigned char)BlobData[i]);
// Know that blob data is consumed for assertion below.
BlobData = 0;
} else {
for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) {
assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob");
WriteByte((unsigned char)Vals[RecordIdx]);
}
}
// Align end to 32-bits.
while (GetBufferOffset() & 3)
WriteByte(0);
} else { // Single scalar field.
assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
EmitAbbreviatedField(Op, Vals[RecordIdx]);
++RecordIdx;
}
}
assert(RecordIdx == Vals.size() && "Not all record operands emitted!");
assert(BlobData == 0 &&
"Blob data specified for record that doesn't use it!");
}
public:
/// EmitRecord - Emit the specified record to the stream, using an abbrev if
/// we have one to compress the output.
template<typename uintty>
void EmitRecord(unsigned Code, SmallVectorImpl<uintty> &Vals,
unsigned Abbrev = 0) {
if (!Abbrev) {
// If we don't have an abbrev to use, emit this in its fully unabbreviated
// form.
EmitCode(bitc::UNABBREV_RECORD);
EmitVBR(Code, 6);
EmitVBR(static_cast<uint32_t>(Vals.size()), 6);
for (unsigned i = 0, e = static_cast<unsigned>(Vals.size()); i != e; ++i)
EmitVBR64(Vals[i], 6);
return;
}
// Insert the code into Vals to treat it uniformly.
Vals.insert(Vals.begin(), Code);
EmitRecordWithAbbrev(Abbrev, Vals);
}
/// EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
/// Unlike EmitRecord, the code for the record should be included in Vals as
/// the first entry.
template<typename uintty>
void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl<uintty> &Vals) {
EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef());
}
/// EmitRecordWithBlob - Emit the specified record to the stream, using an
/// abbrev that includes a blob at the end. The blob data to emit is
/// specified by the pointer and length specified at the end. In contrast to
/// EmitRecord, this routine expects that the first entry in Vals is the code
/// of the record.
template<typename uintty>
void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
StringRef Blob) {
EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob);
}
template<typename uintty>
void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
const char *BlobData, unsigned BlobLen) {
return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen));
}
/// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records
/// that end with an array.
template<typename uintty>
void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
StringRef Array) {
EmitRecordWithAbbrevImpl(Abbrev, Vals, Array);
}
template<typename uintty>
void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
const char *ArrayData, unsigned ArrayLen) {
return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData,
ArrayLen));
}
//===--------------------------------------------------------------------===//
// Abbrev Emission
//===--------------------------------------------------------------------===//
private:
// Emit the abbreviation as a DEFINE_ABBREV record.
void EncodeAbbrev(BitCodeAbbrev *Abbv) {
EmitCode(bitc::DEFINE_ABBREV);
EmitVBR(Abbv->getNumOperandInfos(), 5);
for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
i != e; ++i) {
const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
Emit(Op.isLiteral(), 1);
if (Op.isLiteral()) {
EmitVBR64(Op.getLiteralValue(), 8);
} else {
Emit(Op.getEncoding(), 3);
if (Op.hasEncodingData())
EmitVBR64(Op.getEncodingData(), 5);
}
}
}
public:
/// EmitAbbrev - This emits an abbreviation to the stream. Note that this
/// method takes ownership of the specified abbrev.
unsigned EmitAbbrev(BitCodeAbbrev *Abbv) {
// Emit the abbreviation as a record.
EncodeAbbrev(Abbv);
CurAbbrevs.push_back(Abbv);
return static_cast<unsigned>(CurAbbrevs.size())-1 +
bitc::FIRST_APPLICATION_ABBREV;
}
//===--------------------------------------------------------------------===//
// BlockInfo Block Emission
//===--------------------------------------------------------------------===//
/// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
void EnterBlockInfoBlock(unsigned CodeWidth) {
EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth);
BlockInfoCurBID = ~0U;
}
private:
/// SwitchToBlockID - If we aren't already talking about the specified block
/// ID, emit a BLOCKINFO_CODE_SETBID record.
void SwitchToBlockID(unsigned BlockID) {
if (BlockInfoCurBID == BlockID) return;
SmallVector<unsigned, 2> V;
V.push_back(BlockID);
EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V);
BlockInfoCurBID = BlockID;
}
BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
if (BlockInfo *BI = getBlockInfo(BlockID))
return *BI;
// Otherwise, add a new record.
BlockInfoRecords.push_back(BlockInfo());
BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back();
}
public:
/// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
/// BlockID.
unsigned EmitBlockInfoAbbrev(unsigned BlockID, BitCodeAbbrev *Abbv) {
SwitchToBlockID(BlockID);
EncodeAbbrev(Abbv);
// Add the abbrev to the specified block record.
BlockInfo &Info = getOrCreateBlockInfo(BlockID);
Info.Abbrevs.push_back(Abbv);
return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV;
}
};
} // End llvm namespace
#endif

View File

@@ -0,0 +1,336 @@
//===- LLVMBitCodes.h - Enum values for the LLVM bitcode format -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header defines Bitcode enum values for LLVM IR bitcode files.
//
// The enum values defined in this file should be considered permanent. If
// new features are added, they should have values added at the end of the
// respective lists.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_LLVMBITCODES_H
#define LLVM_BITCODE_LLVMBITCODES_H
#include "llvm/Bitcode/BitCodes.h"
namespace llvm {
namespace bitc {
// The only top-level block type defined is for a module.
enum BlockIDs {
// Blocks
MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID,
// Module sub-block id's.
PARAMATTR_BLOCK_ID,
PARAMATTR_GROUP_BLOCK_ID,
CONSTANTS_BLOCK_ID,
FUNCTION_BLOCK_ID,
UNUSED_ID1,
VALUE_SYMTAB_BLOCK_ID,
METADATA_BLOCK_ID,
METADATA_ATTACHMENT_ID,
TYPE_BLOCK_ID_NEW,
USELIST_BLOCK_ID
};
/// MODULE blocks have a number of optional fields and subblocks.
enum ModuleCodes {
MODULE_CODE_VERSION = 1, // VERSION: [version#]
MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N]
MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N]
MODULE_CODE_ASM = 4, // ASM: [strchr x N]
MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N]
// FIXME: Remove DEPLIB in 4.0.
MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N]
// GLOBALVAR: [pointer type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal]
MODULE_CODE_GLOBALVAR = 7,
// FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
// section, visibility, gc, unnamed_addr]
MODULE_CODE_FUNCTION = 8,
// ALIAS: [alias type, aliasee val#, linkage, visibility]
MODULE_CODE_ALIAS = 9,
// MODULE_CODE_PURGEVALS: [numvals]
MODULE_CODE_PURGEVALS = 10,
MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N]
};
/// PARAMATTR blocks have code for defining a parameter attribute set.
enum AttributeCodes {
// FIXME: Remove `PARAMATTR_CODE_ENTRY_OLD' in 4.0
PARAMATTR_CODE_ENTRY_OLD = 1, // ENTRY: [paramidx0, attr0,
// paramidx1, attr1...]
PARAMATTR_CODE_ENTRY = 2, // ENTRY: [paramidx0, attrgrp0,
// paramidx1, attrgrp1, ...]
PARAMATTR_GRP_CODE_ENTRY = 3 // ENTRY: [id, attr0, att1, ...]
};
/// TYPE blocks have codes for each type primitive they use.
enum TypeCodes {
TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries]
// Type Codes
TYPE_CODE_VOID = 2, // VOID
TYPE_CODE_FLOAT = 3, // FLOAT
TYPE_CODE_DOUBLE = 4, // DOUBLE
TYPE_CODE_LABEL = 5, // LABEL
TYPE_CODE_OPAQUE = 6, // OPAQUE
TYPE_CODE_INTEGER = 7, // INTEGER: [width]
TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty,
// paramty x N]
TYPE_CODE_HALF = 10, // HALF
TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
// These are not with the other floating point types because they're
// a late addition, and putting them in the right place breaks
// binary compatibility.
TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE
TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
TYPE_CODE_METADATA = 16, // METADATA
TYPE_CODE_X86_MMX = 17, // X86 MMX
TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N]
TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N]
TYPE_CODE_STRUCT_NAMED = 20,// STRUCT_NAMED: [ispacked, eltty x N]
TYPE_CODE_FUNCTION = 21 // FUNCTION: [vararg, retty, paramty x N]
};
// The type symbol table only has one code (TST_ENTRY_CODE).
enum TypeSymtabCodes {
TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N]
};
// The value symbol table only has one code (VST_ENTRY_CODE).
enum ValueSymtabCodes {
VST_CODE_ENTRY = 1, // VST_ENTRY: [valid, namechar x N]
VST_CODE_BBENTRY = 2 // VST_BBENTRY: [bbid, namechar x N]
};
enum MetadataCodes {
METADATA_STRING = 1, // MDSTRING: [values]
// 2 is unused.
// 3 is unused.
METADATA_NAME = 4, // STRING: [values]
// 5 is unused.
METADATA_KIND = 6, // [n x [id, name]]
// 7 is unused.
METADATA_NODE = 8, // NODE: [n x (type num, value num)]
METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)]
METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
// constant and maintains an implicit current type value.
enum ConstantsCodes {
CST_CODE_SETTYPE = 1, // SETTYPE: [typeid]
CST_CODE_NULL = 2, // NULL
CST_CODE_UNDEF = 3, // UNDEF
CST_CODE_INTEGER = 4, // INTEGER: [intval]
CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval]
CST_CODE_FLOAT = 6, // FLOAT: [fpval]
CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number]
CST_CODE_STRING = 8, // STRING: [values]
CST_CODE_CSTRING = 9, // CSTRING: [values]
CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval]
CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval]
CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands]
CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval]
CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval]
CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval]
CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval]
CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred]
CST_CODE_INLINEASM_OLD = 18, // INLINEASM: [sideeffect|alignstack,
// asmstr,conststr]
CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval]
CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands]
CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
CST_CODE_DATA = 22, // DATA: [n x elements]
CST_CODE_INLINEASM = 23 // INLINEASM: [sideeffect|alignstack|
// asmdialect,asmstr,conststr]
};
/// CastOpcodes - These are values used in the bitcode files to encode which
/// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums
/// have no fixed relation to the LLVM IR enum values. Changing these will
/// break compatibility with old files.
enum CastOpcodes {
CAST_TRUNC = 0,
CAST_ZEXT = 1,
CAST_SEXT = 2,
CAST_FPTOUI = 3,
CAST_FPTOSI = 4,
CAST_UITOFP = 5,
CAST_SITOFP = 6,
CAST_FPTRUNC = 7,
CAST_FPEXT = 8,
CAST_PTRTOINT = 9,
CAST_INTTOPTR = 10,
CAST_BITCAST = 11
};
/// BinaryOpcodes - These are values used in the bitcode files to encode which
/// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums
/// have no fixed relation to the LLVM IR enum values. Changing these will
/// break compatibility with old files.
enum BinaryOpcodes {
BINOP_ADD = 0,
BINOP_SUB = 1,
BINOP_MUL = 2,
BINOP_UDIV = 3,
BINOP_SDIV = 4, // overloaded for FP
BINOP_UREM = 5,
BINOP_SREM = 6, // overloaded for FP
BINOP_SHL = 7,
BINOP_LSHR = 8,
BINOP_ASHR = 9,
BINOP_AND = 10,
BINOP_OR = 11,
BINOP_XOR = 12
};
/// These are values used in the bitcode files to encode AtomicRMW operations.
/// The values of these enums have no fixed relation to the LLVM IR enum
/// values. Changing these will break compatibility with old files.
enum RMWOperations {
RMW_XCHG = 0,
RMW_ADD = 1,
RMW_SUB = 2,
RMW_AND = 3,
RMW_NAND = 4,
RMW_OR = 5,
RMW_XOR = 6,
RMW_MAX = 7,
RMW_MIN = 8,
RMW_UMAX = 9,
RMW_UMIN = 10
};
/// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
/// OverflowingBinaryOperator's SubclassOptionalData contents.
enum OverflowingBinaryOperatorOptionalFlags {
OBO_NO_UNSIGNED_WRAP = 0,
OBO_NO_SIGNED_WRAP = 1
};
/// PossiblyExactOperatorOptionalFlags - Flags for serializing
/// PossiblyExactOperator's SubclassOptionalData contents.
enum PossiblyExactOperatorOptionalFlags {
PEO_EXACT = 0
};
/// Encoded AtomicOrdering values.
enum AtomicOrderingCodes {
ORDERING_NOTATOMIC = 0,
ORDERING_UNORDERED = 1,
ORDERING_MONOTONIC = 2,
ORDERING_ACQUIRE = 3,
ORDERING_RELEASE = 4,
ORDERING_ACQREL = 5,
ORDERING_SEQCST = 6
};
/// Encoded SynchronizationScope values.
enum AtomicSynchScopeCodes {
SYNCHSCOPE_SINGLETHREAD = 0,
SYNCHSCOPE_CROSSTHREAD = 1
};
// The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
// can contain a constant block (CONSTANTS_BLOCK_ID).
enum FunctionCodes {
FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n]
FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval]
FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval]
FUNC_CODE_INST_GEP = 4, // GEP: [n x operands]
FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval]
FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval]
FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval]
FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval]
FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred]
FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...]
FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
// 14 is unused.
FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...]
// 17 is unused.
// 18 is unused.
FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align]
FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol]
// 21 is unused.
// 22 is unused.
FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty]
// This store code encodes the pointer type, rather than the value type
// this is so information only available in the pointer type (e.g. address
// spaces) is retained.
FUNC_CODE_INST_STORE = 24, // STORE: [ptrty,ptr,val, align, vol]
// 25 is unused.
FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
// fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to
// support legacy vicmp/vfcmp instructions.
FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
// new select on i1 or [N x i1]
FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands]
FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...]
// 32 is unused.
FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN
FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...]
FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal]
FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope]
FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
// align, vol,
// ordering, synchscope]
FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
// ordering, synchscope]
};
enum UseListCodes {
USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD.
};
} // End bitc namespace
} // End llvm namespace
#endif

View File

@@ -0,0 +1,154 @@
//===-- llvm/Bitcode/ReaderWriter.h - Bitcode reader/writers ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header defines interfaces to read and write LLVM bitcode files/streams.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_READERWRITER_H
#define LLVM_BITCODE_READERWRITER_H
#include <string>
namespace llvm {
class BitstreamWriter;
class MemoryBuffer;
class DataStreamer;
class LLVMContext;
class Module;
class ModulePass;
class raw_ostream;
/// getLazyBitcodeModule - Read the header of the specified bitcode buffer
/// and prepare for lazy deserialization of function bodies. If successful,
/// this takes ownership of 'buffer' and returns a non-null pointer. On
/// error, this returns null, *does not* take ownership of Buffer, and fills
/// in *ErrMsg with an error description if ErrMsg is non-null.
Module *getLazyBitcodeModule(MemoryBuffer *Buffer,
LLVMContext &Context,
std::string *ErrMsg = 0);
/// getStreamedBitcodeModule - Read the header of the specified stream
/// and prepare for lazy deserialization and streaming of function bodies.
/// On error, this returns null, and fills in *ErrMsg with an error
/// description if ErrMsg is non-null.
Module *getStreamedBitcodeModule(const std::string &name,
DataStreamer *streamer,
LLVMContext &Context,
std::string *ErrMsg = 0);
/// getBitcodeTargetTriple - Read the header of the specified bitcode
/// buffer and extract just the triple information. If successful,
/// this returns a string and *does not* take ownership
/// of 'buffer'. On error, this returns "", and fills in *ErrMsg
/// if ErrMsg is non-null.
std::string getBitcodeTargetTriple(MemoryBuffer *Buffer,
LLVMContext &Context,
std::string *ErrMsg = 0);
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, this returns null and fills in *ErrMsg if it is
/// non-null. This method *never* takes ownership of Buffer.
Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context,
std::string *ErrMsg = 0);
/// WriteBitcodeToFile - Write the specified module to the specified
/// raw output stream. For streams where it matters, the given stream
/// should be in "binary" mode.
void WriteBitcodeToFile(const Module *M, raw_ostream &Out);
/// createBitcodeWriterPass - Create and return a pass that writes the module
/// to the specified ostream.
ModulePass *createBitcodeWriterPass(raw_ostream &Str);
/// isBitcodeWrapper - Return true if the given bytes are the magic bytes
/// for an LLVM IR bitcode wrapper.
///
inline bool isBitcodeWrapper(const unsigned char *BufPtr,
const unsigned char *BufEnd) {
// See if you can find the hidden message in the magic bytes :-).
// (Hint: it's a little-endian encoding.)
return BufPtr != BufEnd &&
BufPtr[0] == 0xDE &&
BufPtr[1] == 0xC0 &&
BufPtr[2] == 0x17 &&
BufPtr[3] == 0x0B;
}
/// isRawBitcode - Return true if the given bytes are the magic bytes for
/// raw LLVM IR bitcode (without a wrapper).
///
inline bool isRawBitcode(const unsigned char *BufPtr,
const unsigned char *BufEnd) {
// These bytes sort of have a hidden message, but it's not in
// little-endian this time, and it's a little redundant.
return BufPtr != BufEnd &&
BufPtr[0] == 'B' &&
BufPtr[1] == 'C' &&
BufPtr[2] == 0xc0 &&
BufPtr[3] == 0xde;
}
/// isBitcode - Return true if the given bytes are the magic bytes for
/// LLVM IR bitcode, either with or without a wrapper.
///
inline bool isBitcode(const unsigned char *BufPtr,
const unsigned char *BufEnd) {
return isBitcodeWrapper(BufPtr, BufEnd) ||
isRawBitcode(BufPtr, BufEnd);
}
/// SkipBitcodeWrapperHeader - Some systems wrap bc files with a special
/// header for padding or other reasons. The format of this header is:
///
/// struct bc_header {
/// uint32_t Magic; // 0x0B17C0DE
/// uint32_t Version; // Version, currently always 0.
/// uint32_t BitcodeOffset; // Offset to traditional bitcode file.
/// uint32_t BitcodeSize; // Size of traditional bitcode file.
/// ... potentially other gunk ...
/// };
///
/// This function is called when we find a file with a matching magic number.
/// In this case, skip down to the subsection of the file that is actually a
/// BC file.
/// If 'VerifyBufferSize' is true, check that the buffer is large enough to
/// contain the whole bitcode file.
inline bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr,
const unsigned char *&BufEnd,
bool VerifyBufferSize) {
enum {
KnownHeaderSize = 4*4, // Size of header we read.
OffsetField = 2*4, // Offset in bytes to Offset field.
SizeField = 3*4 // Offset in bytes to Size field.
};
// Must contain the header!
if (BufEnd-BufPtr < KnownHeaderSize) return true;
unsigned Offset = ( BufPtr[OffsetField ] |
(BufPtr[OffsetField+1] << 8) |
(BufPtr[OffsetField+2] << 16) |
(BufPtr[OffsetField+3] << 24));
unsigned Size = ( BufPtr[SizeField ] |
(BufPtr[SizeField +1] << 8) |
(BufPtr[SizeField +2] << 16) |
(BufPtr[SizeField +3] << 24));
// Verify that Offset+Size fits in the file.
if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr))
return true;
BufPtr += Offset;
BufEnd = BufPtr+Size;
return false;
}
} // End llvm namespace
#endif