summaryrefslogtreecommitdiffstats
path: root/include/llvm/Bitcode
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-06-02 17:52:33 +0000
committered <ed@FreeBSD.org>2009-06-02 17:52:33 +0000
commit3277b69d734b9c90b44ebde4ede005717e2c3b2e (patch)
tree64ba909838c23261cace781ece27d106134ea451 /include/llvm/Bitcode
downloadFreeBSD-src-3277b69d734b9c90b44ebde4ede005717e2c3b2e.zip
FreeBSD-src-3277b69d734b9c90b44ebde4ede005717e2c3b2e.tar.gz
Import LLVM, at r72732.
Diffstat (limited to 'include/llvm/Bitcode')
-rw-r--r--include/llvm/Bitcode/Archive.h545
-rw-r--r--include/llvm/Bitcode/BitCodes.h185
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h638
-rw-r--r--include/llvm/Bitcode/BitstreamWriter.h517
-rw-r--r--include/llvm/Bitcode/Deserialize.h517
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h221
-rw-r--r--include/llvm/Bitcode/ReaderWriter.h113
-rw-r--r--include/llvm/Bitcode/Serialization.h68
-rw-r--r--include/llvm/Bitcode/SerializationFwd.h27
-rw-r--r--include/llvm/Bitcode/Serialize.h211
10 files changed, 3042 insertions, 0 deletions
diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h
new file mode 100644
index 0000000..a3631ac
--- /dev/null
+++ b/include/llvm/Bitcode/Archive.h
@@ -0,0 +1,545 @@
+//===-- 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/System/Path.h"
+#include <map>
+#include <set>
+#include <fstream>
+
+namespace llvm {
+ class MemoryBuffer;
+
+// Forward declare classes
+class ModuleProvider; // From VMCore
+class Module; // From VMCore
+class Archive; // Declared below
+class ArchiveMemberHeader; // Internal implementation class
+
+/// 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 {
+ CompressedFlag = 1, ///< Member is a normal compressed file
+ SVR4SymbolTableFlag = 2, ///< Member is a SVR4 symbol table
+ BSD4SymbolTableFlag = 4, ///< Member is a BSD4 symbol table
+ LLVMSymbolTableFlag = 8, ///< Member is an LLVM symbol table
+ BitcodeFlag = 16, ///< Member is bitcode
+ HasPathFlag = 64, ///< Member has a full or partial path
+ HasLongFilenameFlag = 128, ///< Member uses the long filename syntax
+ StringTableFlag = 256 ///< 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 applicabiity 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 void* getData() const { return data; }
+
+ /// This method determines if the member is a regular compressed file.
+ /// @returns true iff the archive member is a compressed regular file.
+ /// @brief Determine if the member is a compressed regular file.
+ bool isCompressed() const { return flags&CompressedFlag; }
+
+ /// @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 Determin 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 void* 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.
+ );
+
+ /// 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
+ 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 exception will be thrown. 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.
+ /// @throws std::string if an error occurs opening the file
+ /// @returns an Archive* that represents the archive file.
+ /// @brief Open an existing archive and load its symbols.
+ static Archive* OpenAndLoadSymbols(
+ const sys::Path& Filename, ///< Name of the archive file to open
+ 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.
+ /// @throws std::string if an error occurs
+ /// @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
+ /// ModuleProvider 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 ModuleProvider
+ /// instance because the associated module defines multiple symbols.
+ /// @returns The ModuleProvider* found or null if the archive does not
+ /// contain a module that defines the \p symbol.
+ /// @brief Look up a module by symbol name.
+ ModuleProvider* 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
+ std::set<ModuleProvider*>& 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 successfull.
+ /// @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
+ bool Compress=false, ///< Compress files
+ 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 occured, 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);
+
+ /// @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 Writing member succeeded
+ /// @returns true 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?
+ bool ShouldCompress, ///< Should the member be compressed?
+ 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 ModuleProvider.
+ /// @brief Module mapping type
+ typedef std::map<unsigned,std::pair<ModuleProvider*,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.
+ /// @}
+ /// @name Hidden
+ /// @{
+ private:
+ Archive(); ///< Do not implement
+ Archive(const Archive&); ///< Do not implement
+ Archive& operator=(const Archive&); ///< Do not implement
+ /// @}
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h
new file mode 100644
index 0000000..449dc35
--- /dev/null
+++ b/include/llvm/Bitcode/BitCodes.h
@@ -0,0 +1,185 @@
+//===- 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 <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) {
+ default: assert(0 && "Unknown encoding");
+ case Fixed:
+ case VBR:
+ return true;
+ case Array:
+ case Char6:
+ case Blob:
+ return false;
+ }
+ }
+
+ /// 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;
+ assert(0 && "Not a value Char6 character!");
+ return 0;
+ }
+
+ 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 '_';
+ assert(0 && "Not a value Char6 character!");
+ return ' ';
+ }
+
+};
+
+/// 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, 8> 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
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h
new file mode 100644
index 0000000..b7ae47d
--- /dev/null
+++ b/include/llvm/Bitcode/BitstreamReader.h
@@ -0,0 +1,638 @@
+//===- 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 BITSTREAM_READER_H
+#define BITSTREAM_READER_H
+
+#include "llvm/Bitcode/BitCodes.h"
+#include <climits>
+#include <vector>
+
+namespace llvm {
+
+ class Deserializer;
+
+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:
+ /// FirstChar/LastChar - This remembers the first and last bytes of the
+ /// stream.
+ const unsigned char *FirstChar, *LastChar;
+
+ 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&); // NOT IMPLEMENTED
+ void operator=(const BitstreamReader&); // NOT IMPLEMENTED
+public:
+ BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) {
+ }
+
+ BitstreamReader(const unsigned char *Start, const unsigned char *End) {
+ IgnoreBlockInfoNames = true;
+ init(Start, End);
+ }
+
+ void init(const unsigned char *Start, const unsigned char *End) {
+ FirstChar = Start;
+ LastChar = End;
+ assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
+ }
+
+ ~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();
+ }
+ }
+
+ const unsigned char *getFirstChar() const { return FirstChar; }
+ const unsigned char *getLastChar() const { return LastChar; }
+
+ /// 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();
+ }
+
+};
+
+class BitstreamCursor {
+ friend class Deserializer;
+ BitstreamReader *BitStream;
+ const unsigned char *NextChar;
+
+ /// CurWord - This is the current data we have pulled from the stream but have
+ /// not returned to the client.
+ uint32_t CurWord;
+
+ /// BitsInCurWord - This is the number of bits in CurWord that are valid. This
+ /// is always from [0...31] inclusive.
+ 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 = R.getFirstChar();
+ assert(NextChar && "Bitstream not initialized yet");
+ CurWord = 0;
+ BitsInCurWord = 0;
+ CurCodeSize = 2;
+ }
+
+ void init(BitstreamReader &R) {
+ freeState();
+
+ BitStream = &R;
+ NextChar = R.getFirstChar();
+ assert(NextChar && "Bitstream not initialized yet");
+ CurWord = 0;
+ BitsInCurWord = 0;
+ CurCodeSize = 2;
+ }
+
+ ~BitstreamCursor() {
+ freeState();
+ }
+
+ void operator=(const BitstreamCursor &RHS) {
+ freeState();
+
+ BitStream = RHS.BitStream;
+ NextChar = RHS.NextChar;
+ CurWord = RHS.CurWord;
+ BitsInCurWord = RHS.BitsInCurWord;
+ CurCodeSize = RHS.CurCodeSize;
+
+ // Copy abbreviations, and bump ref counts.
+ CurAbbrevs = RHS.CurAbbrevs;
+ for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
+ i != e; ++i)
+ CurAbbrevs[i]->addRef();
+
+ // Copy block scope and bump ref counts.
+ for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size());
+ S != e; ++S) {
+ std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs;
+ for (unsigned i = 0, e = static_cast<unsigned>(Abbrevs.size());
+ i != e; ++i)
+ Abbrevs[i]->addRef();
+ }
+ }
+
+ void freeState() {
+ // Free all the Abbrevs.
+ for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
+ i != e; ++i)
+ CurAbbrevs[i]->dropRef();
+ CurAbbrevs.clear();
+
+ // Free all the Abbrevs in the block scope.
+ for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size());
+ S != e; ++S) {
+ std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs;
+ for (unsigned i = 0, e = static_cast<unsigned>(Abbrevs.size());
+ i != e; ++i)
+ Abbrevs[i]->dropRef();
+ }
+ BlockScope.clear();
+ }
+
+ /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
+ unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
+
+ bool AtEndOfStream() const {
+ return NextChar == BitStream->getLastChar() && BitsInCurWord == 0;
+ }
+
+ /// GetCurrentBitNo - Return the bit # of the bit we are reading.
+ uint64_t GetCurrentBitNo() const {
+ return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord;
+ }
+
+ BitstreamReader *getBitStreamReader() {
+ return BitStream;
+ }
+ const BitstreamReader *getBitStreamReader() const {
+ return BitStream;
+ }
+
+
+ /// JumpToBit - Reset the stream to the specified bit number.
+ void JumpToBit(uint64_t BitNo) {
+ uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3;
+ uintptr_t WordBitNo = uintptr_t(BitNo) & 31;
+ assert(ByteNo <= (uintptr_t)(BitStream->getLastChar()-
+ BitStream->getFirstChar()) &&
+ "Invalid location");
+
+ // Move the cursor to the right word.
+ NextChar = BitStream->getFirstChar()+ByteNo;
+ BitsInCurWord = 0;
+ CurWord = 0;
+
+ // Skip over any bits that are already consumed.
+ if (WordBitNo)
+ Read(static_cast<unsigned>(WordBitNo));
+ }
+
+
+ uint32_t Read(unsigned NumBits) {
+ // If the field is fully contained by CurWord, return it quickly.
+ if (BitsInCurWord >= NumBits) {
+ uint32_t R = CurWord & ((1U << NumBits)-1);
+ CurWord >>= NumBits;
+ BitsInCurWord -= NumBits;
+ return R;
+ }
+
+ // If we run out of data, stop at the end of the stream.
+ if (NextChar == BitStream->getLastChar()) {
+ CurWord = 0;
+ BitsInCurWord = 0;
+ return 0;
+ }
+
+ unsigned R = CurWord;
+
+ // Read the next word from the stream.
+ CurWord = (NextChar[0] << 0) | (NextChar[1] << 8) |
+ (NextChar[2] << 16) | (NextChar[3] << 24);
+ NextChar += 4;
+
+ // Extract NumBits-BitsInCurWord from what we just read.
+ unsigned BitsLeft = NumBits-BitsInCurWord;
+
+ // Be careful here, BitsLeft is in the range [1..32] inclusive.
+ R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord;
+
+ // BitsLeft bits have just been used up from CurWord.
+ if (BitsLeft != 32)
+ CurWord >>= BitsLeft;
+ else
+ CurWord = 0;
+ BitsInCurWord = 32-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);
+ }
+ }
+
+ uint64_t ReadVBR64(unsigned NumBits) {
+ uint64_t Piece = Read(NumBits);
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Piece;
+
+ uint64_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);
+ }
+ }
+
+ void SkipToWord() {
+ BitsInCurWord = 0;
+ CurWord = 0;
+ }
+
+ 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);
+ SkipToWord();
+ unsigned NumWords = Read(bitc::BlockSizeWidth);
+
+ // Check that the block wasn't partially defined, and that the offset isn't
+ // bogus.
+ if (AtEndOfStream() || NextChar+NumWords*4 > BitStream->getLastChar())
+ return true;
+
+ NextChar += NumWords*4;
+ return false;
+ }
+
+ /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
+ /// the block, and return true if the block is valid.
+ bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) {
+ // Save the current block's state on BlockScope.
+ BlockScope.push_back(Block(CurCodeSize));
+ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
+
+ // Add the abbrevs specific to this block to the CurAbbrevs list.
+ if (const BitstreamReader::BlockInfo *Info =
+ BitStream->getBlockInfo(BlockID)) {
+ for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size());
+ i != e; ++i) {
+ CurAbbrevs.push_back(Info->Abbrevs[i]);
+ CurAbbrevs.back()->addRef();
+ }
+ }
+
+ // Get the codesize of this block.
+ CurCodeSize = ReadVBR(bitc::CodeLenWidth);
+ SkipToWord();
+ unsigned NumWords = Read(bitc::BlockSizeWidth);
+ if (NumWordsP) *NumWordsP = NumWords;
+
+ // Validate that this block is sane.
+ if (CurCodeSize == 0 || AtEndOfStream() ||
+ NextChar+NumWords*4 > BitStream->getLastChar())
+ return true;
+
+ return false;
+ }
+
+ bool ReadBlockEnd() {
+ if (BlockScope.empty()) return true;
+
+ // Block tail:
+ // [END_BLOCK, <align4bytes>]
+ SkipToWord();
+
+ 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) {
+ assert(Op.isLiteral() && "Not a literal");
+ // If the abbrev specifies the literal value to use, use it.
+ Vals.push_back(Op.getLiteralValue());
+ }
+
+ void ReadAbbreviatedField(const BitCodeAbbrevOp &Op,
+ SmallVectorImpl<uint64_t> &Vals) {
+ assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!");
+
+ // Decode the value as we are commanded.
+ switch (Op.getEncoding()) {
+ default: assert(0 && "Unknown encoding!");
+ case BitCodeAbbrevOp::Fixed:
+ Vals.push_back(Read((unsigned)Op.getEncodingData()));
+ break;
+ case BitCodeAbbrevOp::VBR:
+ Vals.push_back(ReadVBR64((unsigned)Op.getEncodingData()));
+ break;
+ case BitCodeAbbrevOp::Char6:
+ Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6)));
+ break;
+ }
+ }
+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];
+ }
+
+ unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
+ const char **BlobStart = 0, unsigned *BlobLen = 0) {
+ if (AbbrevID == bitc::UNABBREV_RECORD) {
+ unsigned Code = ReadVBR(6);
+ unsigned NumElts = ReadVBR(6);
+ for (unsigned i = 0; i != NumElts; ++i)
+ Vals.push_back(ReadVBR64(6));
+ return Code;
+ }
+
+ const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
+
+ for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) {
+ const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
+ if (Op.isLiteral()) {
+ ReadAbbreviatedLiteral(Op, Vals);
+ } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
+ // Array case. Read the number of elements as a vbr6.
+ unsigned NumElts = ReadVBR(6);
+
+ // Get the element encoding.
+ assert(i+2 == e && "array op not second to last?");
+ const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
+
+ // Read all the elements.
+ for (; NumElts; --NumElts)
+ ReadAbbreviatedField(EltEnc, Vals);
+ } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) {
+ // Blob case. Read the number of bytes as a vbr6.
+ unsigned NumElts = ReadVBR(6);
+ SkipToWord(); // 32-bit alignment
+
+ // Figure out where the end of this blob will be including tail padding.
+ const unsigned char *NewEnd = NextChar+((NumElts+3)&~3);
+
+ // If this would read off the end of the bitcode file, just set the
+ // record to empty and return.
+ if (NewEnd > BitStream->getLastChar()) {
+ Vals.append(NumElts, 0);
+ NextChar = BitStream->getLastChar();
+ break;
+ }
+
+ // Otherwise, read the number of bytes. If we can return a reference to
+ // the data, do so to avoid copying it.
+ if (BlobStart) {
+ *BlobStart = (const char*)NextChar;
+ *BlobLen = NumElts;
+ } else {
+ for (; NumElts; ++NextChar, --NumElts)
+ Vals.push_back(*NextChar);
+ }
+ // Skip over tail padding.
+ NextChar = NewEnd;
+ } else {
+ ReadAbbreviatedField(Op, Vals);
+ }
+ }
+
+ unsigned Code = (unsigned)Vals[0];
+ Vals.erase(Vals.begin());
+ return Code;
+ }
+
+ unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
+ const char *&BlobStart, unsigned &BlobLen) {
+ return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen);
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Abbrev Processing
+ //===--------------------------------------------------------------------===//
+
+ void ReadAbbrevRecord() {
+ BitCodeAbbrev *Abbv = new BitCodeAbbrev();
+ unsigned NumOpInfo = ReadVBR(5);
+ for (unsigned i = 0; i != NumOpInfo; ++i) {
+ bool IsLiteral = Read(1) ? true : false;
+ if (IsLiteral) {
+ Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8)));
+ continue;
+ }
+
+ BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3);
+ if (BitCodeAbbrevOp::hasEncodingData(E))
+ Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5)));
+ else
+ Abbv->Add(BitCodeAbbrevOp(E));
+ }
+ CurAbbrevs.push_back(Abbv);
+ }
+
+public:
+
+ bool ReadBlockInfoBlock() {
+ // If this is the second stream to get to the block info block, skip it.
+ if (BitStream->hasBlockInfoRecords())
+ return SkipBlock();
+
+ if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true;
+
+ SmallVector<uint64_t, 64> Record;
+ BitstreamReader::BlockInfo *CurBlockInfo = 0;
+
+ // Read all the records for this module.
+ while (1) {
+ unsigned Code = ReadCode();
+ if (Code == bitc::END_BLOCK)
+ return ReadBlockEnd();
+ if (Code == bitc::ENTER_SUBBLOCK) {
+ ReadSubBlockID();
+ if (SkipBlock()) return true;
+ continue;
+ }
+
+ // Read abbrev records, associate them with CurBID.
+ if (Code == bitc::DEFINE_ABBREV) {
+ if (!CurBlockInfo) return true;
+ ReadAbbrevRecord();
+
+ // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the
+ // appropriate BlockInfo.
+ BitCodeAbbrev *Abbv = CurAbbrevs.back();
+ CurAbbrevs.pop_back();
+ CurBlockInfo->Abbrevs.push_back(Abbv);
+ continue;
+ }
+
+ // Read a record.
+ Record.clear();
+ switch (ReadRecord(Code, Record)) {
+ default: break; // Default behavior, ignore unknown content.
+ case bitc::BLOCKINFO_CODE_SETBID:
+ if (Record.size() < 1) return true;
+ CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]);
+ break;
+ case bitc::BLOCKINFO_CODE_BLOCKNAME: {
+ if (!CurBlockInfo) return true;
+ if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name.
+ std::string Name;
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ Name += (char)Record[i];
+ CurBlockInfo->Name = Name;
+ break;
+ }
+ case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
+ if (!CurBlockInfo) return true;
+ if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name.
+ std::string Name;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i)
+ Name += (char)Record[i];
+ CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0],
+ Name));
+ break;
+ }
+ }
+ }
+ }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h
new file mode 100644
index 0000000..55dd4dd
--- /dev/null
+++ b/include/llvm/Bitcode/BitstreamWriter.h
@@ -0,0 +1,517 @@
+//===- 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 BITSTREAM_WRITER_H
+#define BITSTREAM_WRITER_H
+
+#include "llvm/Bitcode/BitCodes.h"
+#include <vector>
+
+namespace llvm {
+
+class BitstreamWriter {
+ std::vector<unsigned 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;
+
+public:
+ explicit BitstreamWriter(std::vector<unsigned 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();
+ }
+ }
+
+ std::vector<unsigned char> &getBuffer() { return Out; }
+
+ /// \brief Retrieve the current position in the stream, in bits.
+ uint64_t GetCurrentBitNo() const { return Out.size() * 8 + CurBit; }
+
+ //===--------------------------------------------------------------------===//
+ // Basic Primitives for emitting bits to the stream.
+ //===--------------------------------------------------------------------===//
+
+ void Emit(uint32_t Val, unsigned NumBits) {
+ assert(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.
+ unsigned V = CurValue;
+ Out.push_back((unsigned char)(V >> 0));
+ Out.push_back((unsigned char)(V >> 8));
+ Out.push_back((unsigned char)(V >> 16));
+ Out.push_back((unsigned char)(V >> 24));
+
+ 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) {
+ unsigned V = CurValue;
+ Out.push_back((unsigned char)(V >> 0));
+ Out.push_back((unsigned char)(V >> 8));
+ Out.push_back((unsigned char)(V >> 16));
+ Out.push_back((unsigned char)(V >> 24));
+ CurBit = 0;
+ CurValue = 0;
+ }
+ }
+
+ void EmitVBR(uint32_t Val, unsigned NumBits) {
+ 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) {
+ if ((uint32_t)Val == Val)
+ return EmitVBR((uint32_t)Val, NumBits);
+
+ uint64_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);
+ }
+
+ // 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);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // 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 BlockSizeWordLoc = static_cast<unsigned>(Out.size());
+ 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, BlockSizeWordLoc/4));
+ 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= static_cast<unsigned>(Out.size())/4-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: assert(0 && "Unknown encoding!");
+ case BitCodeAbbrevOp::Fixed:
+ Emit((unsigned)V, (unsigned)Op.getEncodingData());
+ break;
+ case BitCodeAbbrevOp::VBR:
+ 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 the record.
+ template<typename uintty>
+ void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
+ const char *BlobData, unsigned BlobLen) {
+ 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();
+ assert((Out.size() & 3) == 0 && "Not 32-bit aligned");
+
+ // Emit each field as a literal byte.
+ if (BlobData) {
+ for (unsigned i = 0; i != BlobLen; ++i)
+ Out.push_back((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");
+ Out.push_back((unsigned char)Vals[RecordIdx]);
+ }
+ }
+ // Align end to 32-bits.
+ while (Out.size() & 3)
+ Out.push_back(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, 0, 0);
+ }
+
+ /// 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,
+ const char *BlobData, unsigned BlobLen) {
+ EmitRecordWithAbbrevImpl(Abbrev, Vals, BlobData, BlobLen);
+ }
+
+ /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records
+ /// that end with an array.
+ template<typename uintty>
+ void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals,
+ const char *ArrayData, unsigned ArrayLen) {
+ EmitRecordWithAbbrevImpl(Abbrev, Vals, 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 = -1U;
+ }
+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
diff --git a/include/llvm/Bitcode/Deserialize.h b/include/llvm/Bitcode/Deserialize.h
new file mode 100644
index 0000000..3e90227
--- /dev/null
+++ b/include/llvm/Bitcode/Deserialize.h
@@ -0,0 +1,517 @@
+//=- Deserialize.h - Generic Object Deserialization from Bitcode --*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for generic object deserialization from
+// LLVM bitcode.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITCODE_SERIALIZE_INPUT
+#define LLVM_BITCODE_SERIALIZE_INPUT
+
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/Serialization.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+#include <vector>
+
+namespace llvm {
+
+class Deserializer {
+
+ //===----------------------------------------------------------===//
+ // Internal type definitions.
+ //===----------------------------------------------------------===//
+
+ struct BPNode {
+ BPNode* Next;
+ uintptr_t& PtrRef;
+
+ BPNode(BPNode* n, uintptr_t& pref)
+ : Next(n), PtrRef(pref) {
+ PtrRef = 0;
+ }
+ };
+
+ struct BPEntry {
+ union { BPNode* Head; void* Ptr; };
+
+ BPEntry() : Head(NULL) {}
+
+ static inline bool isPod() { return true; }
+
+ void SetPtr(BPNode*& FreeList, void* P);
+ };
+
+ class BPKey {
+ unsigned Raw;
+
+ public:
+ BPKey(SerializedPtrID PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); }
+ BPKey(unsigned code, unsigned) : Raw(code) {}
+
+ void MarkFinal() { Raw |= 0x1; }
+ bool hasFinalPtr() const { return Raw & 0x1 ? true : false; }
+ SerializedPtrID getID() const { return Raw >> 1; }
+
+ static inline BPKey getEmptyKey() { return BPKey(0,0); }
+ static inline BPKey getTombstoneKey() { return BPKey(1,0); }
+ static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; }
+
+ static bool isEqual(const BPKey& K1, const BPKey& K2) {
+ return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true;
+ }
+
+ static bool isPod() { return true; }
+ };
+
+ typedef llvm::DenseMap<BPKey,BPEntry,BPKey,BPEntry> MapTy;
+
+ //===----------------------------------------------------------===//
+ // Publicly visible types.
+ //===----------------------------------------------------------===//
+
+public:
+ struct Location {
+ uint64_t BitNo;
+ unsigned BlockID;
+ unsigned NumWords;
+
+ Location(uint64_t bit, unsigned bid, unsigned words)
+ : BitNo(bit), BlockID(bid), NumWords(words) {}
+
+ Location() : BitNo(0), BlockID(0), NumWords(0) {}
+
+ Location& operator=(Location& RHS) {
+ BitNo = RHS.BitNo;
+ BlockID = RHS.BlockID;
+ NumWords = RHS.NumWords;
+ return *this;
+ }
+
+ bool operator==(const Location& RHS) const { return BitNo == RHS.BitNo; }
+ bool operator!=(const Location& RHS) const { return BitNo != RHS.BitNo; }
+
+ bool contains(const Location& RHS) const {
+ if (RHS.BitNo < BitNo)
+ return false;
+
+ if ((RHS.BitNo - BitNo) >> 5 < NumWords)
+ return true;
+
+ return false;
+ }
+ };
+
+ //===----------------------------------------------------------===//
+ // Internal data members.
+ //===----------------------------------------------------------===//
+
+private:
+ BitstreamCursor Stream;
+ SmallVector<uint64_t,20> Record;
+ unsigned RecIdx;
+ BumpPtrAllocator Allocator;
+ BPNode* FreeList;
+ MapTy BPatchMap;
+ llvm::SmallVector<Location,8> BlockStack;
+ unsigned AbbrevNo;
+ unsigned RecordCode;
+ uint64_t StreamStart;
+
+ //===----------------------------------------------------------===//
+ // Public Interface.
+ //===----------------------------------------------------------===//
+
+public:
+ Deserializer(BitstreamReader& stream);
+ ~Deserializer();
+
+ uint64_t ReadInt();
+ int64_t ReadSInt();
+ SerializedPtrID ReadPtrID() { return (SerializedPtrID) ReadInt(); }
+
+
+ bool ReadBool() {
+ return ReadInt() ? true : false;
+ }
+
+ template <typename T>
+ inline T& Read(T& X) {
+ SerializeTrait<T>::Read(*this,X);
+ return X;
+ }
+
+ template <typename T>
+ inline T* Create() {
+ return SerializeTrait<T>::Create(*this);
+ }
+
+ char* ReadCStr(char* cstr = NULL, unsigned MaxLen=0, bool isNullTerm=true);
+ void ReadCStr(std::vector<char>& buff, bool isNullTerm=false, unsigned Idx=0);
+
+ template <typename T>
+ inline T* ReadOwnedPtr(bool AutoRegister = true) {
+ SerializedPtrID PtrID = ReadPtrID();
+
+ if (!PtrID)
+ return NULL;
+
+ T* x = SerializeTrait<T>::Create(*this);
+
+ if (AutoRegister)
+ RegisterPtr(PtrID,x);
+
+ return x;
+ }
+
+ template <typename T, typename Arg1>
+ inline T* ReadOwnedPtr(Arg1& arg1, bool AutoRegister = true) {
+ SerializedPtrID PtrID = ReadPtrID();
+
+ if (!PtrID)
+ return NULL;
+
+ T* x = SerializeTrait<T>::Create(*this, arg1);
+
+ if (AutoRegister)
+ RegisterPtr(PtrID,x);
+
+ return x;
+ }
+
+ template <typename T>
+ inline void ReadOwnedPtr(T*& Ptr, bool AutoRegister = true) {
+ Ptr = ReadOwnedPtr<T>(AutoRegister);
+ }
+
+ template <typename T1, typename T2>
+ void BatchReadOwnedPtrs(T1*& P1, T2*& P2,
+ bool A1=true, bool A2=true) {
+
+ SerializedPtrID ID1 = ReadPtrID();
+ SerializedPtrID ID2 = ReadPtrID();
+
+ P1 = (ID1) ? SerializeTrait<T1>::Create(*this) : NULL;
+ if (ID1 && A1) RegisterPtr(ID1,P1);
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+ }
+
+ template <typename T1, typename T2, typename Arg1>
+ void BatchReadOwnedPtrs(T1*& P1, T2*& P2, Arg1& arg1,
+ bool A1=true, bool A2=true) {
+
+ SerializedPtrID ID1 = ReadPtrID();
+ SerializedPtrID ID2 = ReadPtrID();
+
+ P1 = (ID1) ? SerializeTrait<T1>::Create(*this, arg1) : NULL;
+ if (ID1 && A1) RegisterPtr(ID1,P1);
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this, arg1) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+ }
+
+ template <typename T1, typename T2, typename T3>
+ void BatchReadOwnedPtrs(T1*& P1, T2*& P2, T3*& P3,
+ bool A1=true, bool A2=true, bool A3=true) {
+
+ SerializedPtrID ID1 = ReadPtrID();
+ SerializedPtrID ID2 = ReadPtrID();
+ SerializedPtrID ID3 = ReadPtrID();
+
+ P1 = (ID1) ? SerializeTrait<T1>::Create(*this) : NULL;
+ if (ID1 && A1) RegisterPtr(ID1,P1);
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+
+ P3 = (ID3) ? SerializeTrait<T3>::Create(*this) : NULL;
+ if (ID3 && A3) RegisterPtr(ID3,P3);
+ }
+
+ template <typename T1, typename T2, typename T3, typename Arg1>
+ void BatchReadOwnedPtrs(T1*& P1, T2*& P2, T3*& P3, Arg1& arg1,
+ bool A1=true, bool A2=true, bool A3=true) {
+
+ SerializedPtrID ID1 = ReadPtrID();
+ SerializedPtrID ID2 = ReadPtrID();
+ SerializedPtrID ID3 = ReadPtrID();
+
+ P1 = (ID1) ? SerializeTrait<T1>::Create(*this, arg1) : NULL;
+ if (ID1 && A1) RegisterPtr(ID1,P1);
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this, arg1) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+
+ P3 = (ID3) ? SerializeTrait<T3>::Create(*this, arg1) : NULL;
+ if (ID3 && A3) RegisterPtr(ID3,P3);
+ }
+
+ template <typename T>
+ void BatchReadOwnedPtrs(unsigned NumPtrs, T** Ptrs, bool AutoRegister=true) {
+ llvm::SmallVector<SerializedPtrID,10> BatchIDVec;
+
+ for (unsigned i = 0; i < NumPtrs; ++i)
+ BatchIDVec.push_back(ReadPtrID());
+
+ for (unsigned i = 0; i < NumPtrs; ++i) {
+ SerializedPtrID& PtrID = BatchIDVec[i];
+
+ T* p = PtrID ? SerializeTrait<T>::Create(*this) : NULL;
+
+ if (PtrID && AutoRegister)
+ RegisterPtr(PtrID,p);
+
+ Ptrs[i] = p;
+ }
+ }
+
+ template <typename T, typename Arg1>
+ void BatchReadOwnedPtrs(unsigned NumPtrs, T** Ptrs, Arg1& arg1,
+ bool AutoRegister=true) {
+
+ llvm::SmallVector<SerializedPtrID,10> BatchIDVec;
+
+ for (unsigned i = 0; i < NumPtrs; ++i)
+ BatchIDVec.push_back(ReadPtrID());
+
+ for (unsigned i = 0; i < NumPtrs; ++i) {
+ SerializedPtrID& PtrID = BatchIDVec[i];
+
+ T* p = PtrID ? SerializeTrait<T>::Create(*this, arg1) : NULL;
+
+ if (PtrID && AutoRegister)
+ RegisterPtr(PtrID,p);
+
+ Ptrs[i] = p;
+ }
+ }
+
+ template <typename T1, typename T2>
+ void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs, T2*& P2,
+ bool A1=true, bool A2=true) {
+
+ llvm::SmallVector<SerializedPtrID,10> BatchIDVec;
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ BatchIDVec.push_back(ReadPtrID());
+
+ SerializedPtrID ID2 = ReadPtrID();
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i) {
+ SerializedPtrID& PtrID = BatchIDVec[i];
+
+ T1* p = PtrID ? SerializeTrait<T1>::Create(*this) : NULL;
+
+ if (PtrID && A1)
+ RegisterPtr(PtrID,p);
+
+ Ptrs[i] = p;
+ }
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+ }
+
+ template <typename T1, typename T2, typename Arg1>
+ void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs, T2*& P2, Arg1& arg1,
+ bool A1=true, bool A2=true) {
+
+ llvm::SmallVector<SerializedPtrID,10> BatchIDVec;
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ BatchIDVec.push_back(ReadPtrID());
+
+ SerializedPtrID ID2 = ReadPtrID();
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i) {
+ SerializedPtrID& PtrID = BatchIDVec[i];
+
+ T1* p = PtrID ? SerializeTrait<T1>::Create(*this, arg1) : NULL;
+
+ if (PtrID && A1)
+ RegisterPtr(PtrID,p);
+
+ Ptrs[i] = p;
+ }
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this, arg1) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+ }
+
+ template <typename T1, typename T2, typename T3>
+ void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs,
+ T2*& P2, T3*& P3,
+ bool A1=true, bool A2=true, bool A3=true) {
+
+ llvm::SmallVector<SerializedPtrID,10> BatchIDVec;
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ BatchIDVec.push_back(ReadPtrID());
+
+ SerializedPtrID ID2 = ReadPtrID();
+ SerializedPtrID ID3 = ReadPtrID();
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i) {
+ SerializedPtrID& PtrID = BatchIDVec[i];
+
+ T1* p = PtrID ? SerializeTrait<T1>::Create(*this) : NULL;
+
+ if (PtrID && A1)
+ RegisterPtr(PtrID,p);
+
+ Ptrs[i] = p;
+ }
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+
+ P3 = (ID3) ? SerializeTrait<T3>::Create(*this) : NULL;
+ if (ID3 && A3) RegisterPtr(ID3,P3);
+ }
+
+ template <typename T1, typename T2, typename T3, typename Arg1>
+ void BatchReadOwnedPtrs(unsigned NumT1Ptrs, T1** Ptrs,
+ T2*& P2, T3*& P3, Arg1& arg1,
+ bool A1=true, bool A2=true, bool A3=true) {
+
+ llvm::SmallVector<SerializedPtrID,10> BatchIDVec;
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ BatchIDVec.push_back(ReadPtrID());
+
+ SerializedPtrID ID2 = ReadPtrID();
+ SerializedPtrID ID3 = ReadPtrID();
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i) {
+ SerializedPtrID& PtrID = BatchIDVec[i];
+
+ T1* p = PtrID ? SerializeTrait<T1>::Create(*this, arg1) : NULL;
+
+ if (PtrID && A1)
+ RegisterPtr(PtrID,p);
+
+ Ptrs[i] = p;
+ }
+
+ P2 = (ID2) ? SerializeTrait<T2>::Create(*this, arg1) : NULL;
+ if (ID2 && A2) RegisterPtr(ID2,P2);
+
+ P3 = (ID3) ? SerializeTrait<T3>::Create(*this, arg1) : NULL;
+ if (ID3 && A3) RegisterPtr(ID3,P3);
+ }
+
+ template <typename T>
+ void ReadPtr(T*& PtrRef, bool AllowBackpatch = true) {
+ ReadUIntPtr(reinterpret_cast<uintptr_t&>(PtrRef), AllowBackpatch);
+ }
+
+ template <typename T>
+ void ReadPtr(const T*& PtrRef, bool AllowBackpatch = true) {
+ ReadPtr(const_cast<T*&>(PtrRef), AllowBackpatch);
+ }
+
+
+ template <typename T>
+ void ReadPtr(T*& PtrRef, const SerializedPtrID& PtrID,
+ bool AllowBackpatch = true) {
+ ReadUIntPtr(reinterpret_cast<uintptr_t&>(PtrRef), PtrID, AllowBackpatch);
+ }
+
+ template <typename T>
+ void ReadPtr(const T*& PtrRef, const SerializedPtrID& PtrID,
+ bool AllowBackpatch = true) {
+
+ ReadPtr(const_cast<T*&>(PtrRef), PtrID, AllowBackpatch);
+ }
+
+ template <typename T>
+ T* ReadPtr() { T* x = 0; ReadPtr<T>(x,false); return x; }
+
+ void ReadUIntPtr(uintptr_t& PtrRef, const SerializedPtrID& PtrID,
+ bool AllowBackpatch = true);
+
+ void ReadUIntPtr(uintptr_t& PtrRef, bool AllowBackpatch = true) {
+ ReadUIntPtr(PtrRef,ReadPtrID(),AllowBackpatch);
+ }
+
+ template <typename T>
+ T& ReadRef() {
+ T* p = reinterpret_cast<T*>(ReadInternalRefPtr());
+ return *p;
+ }
+
+ void RegisterPtr(const SerializedPtrID& PtrID, const void* Ptr);
+
+ void RegisterPtr(const void* Ptr) {
+ RegisterPtr(ReadPtrID(),Ptr);
+ }
+
+ template<typename T>
+ void RegisterRef(const T& x) {
+ RegisterPtr(&x);
+ }
+
+ template<typename T>
+ void RegisterRef(const SerializedPtrID& PtrID, const T& x) {
+ RegisterPtr(PtrID,&x);
+ }
+
+ Location getCurrentBlockLocation();
+ unsigned getCurrentBlockID();
+ unsigned getAbbrevNo();
+
+ bool FinishedBlock(Location BlockLoc);
+ bool JumpTo(const Location& BlockLoc);
+ void Rewind();
+
+ bool AtEnd();
+ bool inRecord();
+ void SkipBlock();
+ bool SkipToBlock(unsigned BlockID);
+
+ unsigned getRecordCode();
+
+ BitstreamCursor &getStream() { return Stream; }
+
+private:
+ bool AdvanceStream();
+ void ReadRecord();
+
+ uintptr_t ReadInternalRefPtr();
+
+ static inline bool HasFinalPtr(MapTy::value_type& V) {
+ return V.first.hasFinalPtr();
+ }
+
+ static inline uintptr_t GetFinalPtr(MapTy::value_type& V) {
+ return reinterpret_cast<uintptr_t>(V.second.Ptr);
+ }
+
+ static inline BPNode* GetBPNode(MapTy::value_type& V) {
+ return V.second.Head;
+ }
+
+ static inline void SetBPNode(MapTy::value_type& V, BPNode* N) {
+ V.second.Head = N;
+ }
+
+ void SetPtr(MapTy::value_type& V, const void* P) {
+ V.first.MarkFinal();
+ V.second.SetPtr(FreeList,const_cast<void*>(P));
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
new file mode 100644
index 0000000..1ede69d
--- /dev/null
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -0,0 +1,221 @@
+//===- 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,
+ TYPE_BLOCK_ID,
+ CONSTANTS_BLOCK_ID,
+ FUNCTION_BLOCK_ID,
+ TYPE_SYMTAB_BLOCK_ID,
+ VALUE_SYMTAB_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]
+ 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]
+ MODULE_CODE_FUNCTION = 8,
+
+ // ALIAS: [alias type, aliasee val#, linkage]
+ 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 {
+ PARAMATTR_CODE_ENTRY = 1 // ENTRY: [paramidx0, attr0, paramidx1, attr1...]
+ };
+
+ /// 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 = 9, // FUNCTION: [vararg, retty, paramty x N]
+ TYPE_CODE_STRUCT = 10, // STRUCT: [ispacked, eltty x N]
+ 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
+ };
+
+ // 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]
+ };
+
+ // 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 = 18, // INLINEASM: [sideeffect,asmstr,conststr]
+ CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval]
+ CST_CODE_MDSTRING = 20, // MDSTRING: [values]
+ CST_CODE_MDNODE = 21 // MDNODE: [n x (type num, value num)]
+ };
+
+ /// 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
+ };
+
+
+ // 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, opval, n, n x ops]
+ FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
+ FUNC_CODE_INST_UNWIND = 14, // UNWIND
+ FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
+
+ FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...]
+ FUNC_CODE_INST_MALLOC = 17, // MALLOC: [instty, op, align]
+ FUNC_CODE_INST_FREE = 18, // FREE: [opty, op]
+ FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align]
+ FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol]
+ // FIXME: Remove STORE in favor of STORE2 in LLVM 3.0
+ FUNC_CODE_INST_STORE = 21, // STORE: [valty,val,ptr, align, vol]
+ FUNC_CODE_INST_CALL = 22, // CALL: [attr, fnty, fnid, args...]
+ 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_STORE2 = 24, // STORE: [ptrty,ptr,val, align, vol]
+ // FIXME: Remove GETRESULT in favor of EXTRACTVAL in LLVM 3.0
+ FUNC_CODE_INST_GETRESULT = 25, // GETRESULT: [ty, opval, n]
+ 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, NOT for vicmp/vfcmp
+ 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]
+ };
+} // End bitc namespace
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h
new file mode 100644
index 0000000..abdd5d3
--- /dev/null
+++ b/include/llvm/Bitcode/ReaderWriter.h
@@ -0,0 +1,113 @@
+//===-- 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_H
+#define LLVM_BITCODE_H
+
+#include <iosfwd>
+#include <string>
+
+namespace llvm {
+ class Module;
+ class ModuleProvider;
+ class MemoryBuffer;
+ class ModulePass;
+ class BitstreamWriter;
+ class raw_ostream;
+
+ /// getBitcodeModuleProvider - 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.
+ ModuleProvider *getBitcodeModuleProvider(MemoryBuffer *Buffer,
+ 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, std::string *ErrMsg = 0);
+
+ /// WriteBitcodeToFile - Write the specified module to the specified output
+ /// stream.
+ void WriteBitcodeToFile(const Module *M, std::ostream &Out);
+
+ /// WriteBitcodeToFile - Write the specified module to the specified
+ /// raw output stream.
+ void WriteBitcodeToFile(const Module *M, raw_ostream &Out);
+
+ /// WriteBitcodeToStream - Write the specified module to the specified
+ /// raw output stream.
+ void WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream);
+
+ /// CreateBitcodeWriterPass - Create and return a pass that writes the module
+ /// to the specified ostream.
+ ModulePass *CreateBitcodeWriterPass(std::ostream &Str);
+
+ /// createBitcodeWriterPass - Create and return a pass that writes the module
+ /// to the specified ostream.
+ ModulePass *createBitcodeWriterPass(raw_ostream &Str);
+
+
+ /// isBitcodeWrapper - Return true fi this is a wrapper for LLVM IR bitcode
+ /// files.
+ static bool inline isBitcodeWrapper(unsigned char *BufPtr,
+ unsigned char *BufEnd) {
+ return (BufPtr != BufEnd && BufPtr[0] == 0xDE && BufPtr[1] == 0xC0 &&
+ BufPtr[2] == 0x17 && BufPtr[3] == 0x0B);
+ }
+
+ /// 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.
+ static inline bool SkipBitcodeWrapperHeader(unsigned char *&BufPtr,
+ unsigned char *&BufEnd) {
+ 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 (Offset+Size > unsigned(BufEnd-BufPtr))
+ return true;
+ BufPtr += Offset;
+ BufEnd = BufPtr+Size;
+ return false;
+ }
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Bitcode/Serialization.h b/include/llvm/Bitcode/Serialization.h
new file mode 100644
index 0000000..2f0d350
--- /dev/null
+++ b/include/llvm/Bitcode/Serialization.h
@@ -0,0 +1,68 @@
+//==- Serialization.h - Generic Object Serialization to Bitcode ---*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines traits for primitive types used for both object
+// serialization and deserialization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITCODE_SERIALIZE
+#define LLVM_BITCODE_SERIALIZE
+
+#include "llvm/Bitcode/SerializationFwd.h"
+
+namespace llvm {
+
+/// SerializeTrait - SerializeTrait bridges between the Serializer/Deserializer
+/// and the functions that serialize objects of specific types. The default
+/// behavior is to call static methods of the class for the object being
+/// serialized, but this behavior can be changed by specializing this
+/// template. Classes only need to implement the methods corresponding
+/// to the serialization scheme they want to support. For example, "Read"
+/// and "ReadVal" correspond to different deserialization schemes which make
+/// sense for different types; a class need only implement one of them.
+/// Serialization and deserialization of pointers are specially handled
+/// by the Serializer and Deserializer using the EmitOwnedPtr, etc. methods.
+/// To serialize the actual object referred to by a pointer, the class
+/// of the object either must implement the methods called by the default
+/// behavior of SerializeTrait, or specialize SerializeTrait. This latter
+/// is useful when one cannot add methods to an existing class (for example).
+template <typename T>
+struct SerializeTrait {
+ static inline void Emit(Serializer& S, const T& X) { X.Emit(S); }
+ static inline void Read(Deserializer& D, T& X) { X.Read(D); }
+ static inline T* Create(Deserializer& D) { return T::Create(D); }
+
+ template <typename Arg1>
+ static inline T* Create(Deserializer& D, Arg1& arg1) {
+ return T::Create(D, arg1);
+ }
+};
+
+#define SERIALIZE_INT_TRAIT(TYPE)\
+template <> struct SerializeTrait<TYPE> {\
+ static void Emit(Serializer& S, TYPE X);\
+ static void Read(Deserializer& S, TYPE& X); };
+
+SERIALIZE_INT_TRAIT(bool)
+SERIALIZE_INT_TRAIT(unsigned char)
+SERIALIZE_INT_TRAIT(unsigned short)
+SERIALIZE_INT_TRAIT(unsigned int)
+SERIALIZE_INT_TRAIT(unsigned long)
+
+SERIALIZE_INT_TRAIT(signed char)
+SERIALIZE_INT_TRAIT(signed short)
+SERIALIZE_INT_TRAIT(signed int)
+SERIALIZE_INT_TRAIT(signed long)
+
+#undef SERIALIZE_INT_TRAIT
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Bitcode/SerializationFwd.h b/include/llvm/Bitcode/SerializationFwd.h
new file mode 100644
index 0000000..7224190
--- /dev/null
+++ b/include/llvm/Bitcode/SerializationFwd.h
@@ -0,0 +1,27 @@
+//==- SerializationFwd.h - Forward references for Serialization ---*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides forward references for bitcode object serialization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITCODE_SERIALIZE_FWD
+#define LLVM_BITCODE_SERIALIZE_FWD
+
+namespace llvm {
+
+class Serializer;
+class Deserializer;
+template <typename T> struct SerializeTrait;
+
+typedef unsigned SerializedPtrID;
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Bitcode/Serialize.h b/include/llvm/Bitcode/Serialize.h
new file mode 100644
index 0000000..6fe4f02
--- /dev/null
+++ b/include/llvm/Bitcode/Serialize.h
@@ -0,0 +1,211 @@
+//==- Serialize.h - Generic Object Serialization to Bitcode -------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for generic object serialization to
+// LLVM bitcode.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITCODE_SERIALIZE_OUTPUT
+#define LLVM_BITCODE_SERIALIZE_OUTPUT
+
+#include "llvm/Bitcode/Serialization.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+class Serializer {
+ BitstreamWriter& Stream;
+ SmallVector<uint64_t,10> Record;
+ unsigned BlockLevel;
+
+ typedef DenseMap<const void*,unsigned> MapTy;
+ MapTy PtrMap;
+
+public:
+ explicit Serializer(BitstreamWriter& stream);
+ ~Serializer();
+
+ //==------------------------------------------------==//
+ // Template-based dispatch to emit arbitrary types.
+ //==------------------------------------------------==//
+
+ template <typename T>
+ inline void Emit(const T& X) { SerializeTrait<T>::Emit(*this,X); }
+
+ //==------------------------------------------------==//
+ // Methods to emit primitive types.
+ //==------------------------------------------------==//
+
+ void EmitInt(uint64_t X);
+ void EmitSInt(int64_t X);
+
+ inline void EmitBool(bool X) { EmitInt(X); }
+ void EmitCStr(const char* beg, const char* end);
+ void EmitCStr(const char* cstr);
+
+ void EmitPtr(const void* ptr) { EmitInt(getPtrId(ptr)); }
+
+ template <typename T>
+ inline void EmitRef(const T& ref) { EmitPtr(&ref); }
+
+ // Emit a pointer and the object pointed to. (This has no relation to the
+ // OwningPtr<> class.)
+ template <typename T>
+ inline void EmitOwnedPtr(T* ptr) {
+ EmitPtr(ptr);
+ if (ptr) SerializeTrait<T>::Emit(*this,*ptr);
+ }
+
+
+ //==------------------------------------------------==//
+ // Batch emission of pointers.
+ //==------------------------------------------------==//
+
+ template <typename T1, typename T2>
+ void BatchEmitOwnedPtrs(T1* p1, T2* p2) {
+ EmitPtr(p1);
+ EmitPtr(p2);
+ if (p1) SerializeTrait<T1>::Emit(*this,*p1);
+ if (p2) SerializeTrait<T2>::Emit(*this,*p2);
+ }
+
+ template <typename T1, typename T2, typename T3>
+ void BatchEmitOwnedPtrs(T1* p1, T2* p2, T3* p3) {
+ EmitPtr(p1);
+ EmitPtr(p2);
+ EmitPtr(p3);
+ if (p1) SerializeTrait<T1>::Emit(*this,*p1);
+ if (p2) SerializeTrait<T2>::Emit(*this,*p2);
+ if (p3) SerializeTrait<T3>::Emit(*this,*p3);
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ void BatchEmitOwnedPtrs(T1* p1, T2* p2, T3* p3, T4& p4) {
+ EmitPtr(p1);
+ EmitPtr(p2);
+ EmitPtr(p3);
+ EmitPtr(p4);
+ if (p1) SerializeTrait<T1>::Emit(*this,*p1);
+ if (p2) SerializeTrait<T2>::Emit(*this,*p2);
+ if (p3) SerializeTrait<T3>::Emit(*this,*p3);
+ if (p4) SerializeTrait<T4>::Emit(*this,*p4);
+ }
+
+ template <typename T>
+ void BatchEmitOwnedPtrs(unsigned NumPtrs, T* const * Ptrs) {
+ for (unsigned i = 0; i < NumPtrs; ++i)
+ EmitPtr(Ptrs[i]);
+
+ for (unsigned i = 0; i < NumPtrs; ++i)
+ if (Ptrs[i]) SerializeTrait<T>::Emit(*this,*Ptrs[i]);
+ }
+
+ template <typename T1, typename T2>
+ void BatchEmitOwnedPtrs(unsigned NumT1Ptrs, T1* const * Ptrs, T2* p2) {
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ EmitPtr(Ptrs[i]);
+
+ EmitPtr(p2);
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ if (Ptrs[i]) SerializeTrait<T1>::Emit(*this,*Ptrs[i]);
+
+ if (p2) SerializeTrait<T2>::Emit(*this,*p2);
+ }
+
+ template <typename T1, typename T2, typename T3>
+ void BatchEmitOwnedPtrs(unsigned NumT1Ptrs, T1* const * Ptrs,
+ T2* p2, T3* p3) {
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ EmitPtr(Ptrs[i]);
+
+ EmitPtr(p2);
+ EmitPtr(p3);
+
+ for (unsigned i = 0; i < NumT1Ptrs; ++i)
+ if (Ptrs[i]) SerializeTrait<T1>::Emit(*this,*Ptrs[i]);
+
+ if (p2) SerializeTrait<T2>::Emit(*this,*p2);
+ if (p3) SerializeTrait<T3>::Emit(*this,*p3);
+ }
+
+ //==------------------------------------------------==//
+ // Emitter Functors
+ //==------------------------------------------------==//
+
+ template <typename T>
+ struct Emitter0 {
+ Serializer& S;
+ Emitter0(Serializer& s) : S(s) {}
+ void operator()(const T& x) const {
+ SerializeTrait<T>::Emit(S,x);
+ }
+ };
+
+ template <typename T, typename Arg1>
+ struct Emitter1 {
+ Serializer& S;
+ Arg1 A1;
+
+ Emitter1(Serializer& s, Arg1 a1) : S(s), A1(a1) {}
+ void operator()(const T& x) const {
+ SerializeTrait<T>::Emit(S,x,A1);
+ }
+ };
+
+ template <typename T, typename Arg1, typename Arg2>
+ struct Emitter2 {
+ Serializer& S;
+ Arg1 A1;
+ Arg2 A2;
+
+ Emitter2(Serializer& s, Arg1 a1, Arg2 a2) : S(s), A1(a1), A2(a2) {}
+ void operator()(const T& x) const {
+ SerializeTrait<T>::Emit(S,x,A1,A2);
+ }
+ };
+
+ template <typename T>
+ Emitter0<T> MakeEmitter() {
+ return Emitter0<T>(*this);
+ }
+
+ template <typename T, typename Arg1>
+ Emitter1<T,Arg1> MakeEmitter(Arg1 a1) {
+ return Emitter1<T,Arg1>(*this,a1);
+ }
+
+ template <typename T, typename Arg1, typename Arg2>
+ Emitter2<T,Arg1,Arg2> MakeEmitter(Arg1 a1, Arg2 a2) {
+ return Emitter2<T,Arg1,Arg2>(*this,a1,a2);
+ }
+
+ //==------------------------------------------------==//
+ // Misc. query and block/record manipulation methods.
+ //==------------------------------------------------==//
+
+ bool isRegistered(const void* p) const;
+
+ void FlushRecord() { if (inRecord()) EmitRecord(); }
+ void EnterBlock(unsigned BlockID = 8, unsigned CodeLen = 3);
+ void ExitBlock();
+
+private:
+ void EmitRecord();
+ inline bool inRecord() { return Record.size() > 0; }
+ SerializedPtrID getPtrId(const void* ptr);
+};
+
+} // end namespace llvm
+#endif
OpenPOWER on IntegriCloud