aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Schimpf <kschimpf@google.com>2013-05-01 10:42:30 -0700
committerKarl Schimpf <kschimpf@google.com>2013-05-01 10:42:30 -0700
commitf42b26d0d46034cb2b91df810477fc0df2e67b27 (patch)
treebc8749b8fa6e36670df3171a27d9db2bfab608a7
parent595239b2b7297b62d9f804770f5f43d8bf637a0f (diff)
Copy LLVM bitcode reader to generate a PNaCl wire format reader.
Copy classes for LLVM BitcodeReader into a NaCl subdirectory, to create a wire format version. Renames classes/functions to include NaCl prefix, so that they don't conflict with the LLVM Bitcode reader. Also implements pnacl-thaw, showing that we can read the PNaCl wire format files. BUG= https://code.google.com/p/nativeclient/issues/detail?id=3405 R=jvoung@chromium.org Review URL: https://codereview.chromium.org/14314016
-rw-r--r--include/llvm/Bitcode/NaCl/NaClBitstreamReader.h560
-rw-r--r--include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h339
-rw-r--r--include/llvm/Bitcode/NaCl/NaClReaderWriter.h122
-rw-r--r--lib/Bitcode/NaCl/CMakeLists.txt1
-rw-r--r--lib/Bitcode/NaCl/LLVMBuild.txt2
-rw-r--r--lib/Bitcode/NaCl/Makefile2
-rw-r--r--lib/Bitcode/NaCl/Reader/CMakeLists.txt6
-rw-r--r--lib/Bitcode/NaCl/Reader/LLVMBuild.txt22
-rw-r--r--lib/Bitcode/NaCl/Reader/Makefile15
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp3124
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h350
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp373
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp402
-rw-r--r--tools/CMakeLists.txt1
-rw-r--r--tools/Makefile2
-rw-r--r--tools/pnacl-thaw/CMakeLists.txt5
-rw-r--r--tools/pnacl-thaw/LLVMBuild.txt16
-rw-r--r--tools/pnacl-thaw/Makefile17
-rw-r--r--tools/pnacl-thaw/pnacl-thaw.cpp94
19 files changed, 5248 insertions, 205 deletions
diff --git a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h
new file mode 100644
index 0000000000..238ce5275a
--- /dev/null
+++ b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h
@@ -0,0 +1,560 @@
+//===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===//
+// Low-level bitstream reader interface
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitstreamReader class. This class can be used to
+// read an arbitrary bitstream, regardless of its contents.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H
+#define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/StreamableMemoryObject.h"
+#include <climits>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+ class Deserializer;
+
+/// NaClBitstreamReader - This class is used to read from a NaCl
+/// bitcode wire format stream, maintaining information that is global
+/// to decoding the entire file. While a file is being read, multiple
+/// cursors can be independently advanced or skipped around within the
+/// file. These are represented by the NaClBitstreamCursor class.
+class NaClBitstreamReader {
+public:
+ /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
+ /// These describe abbreviations that all blocks of the specified ID inherit.
+ struct BlockInfo {
+ unsigned BlockID;
+ std::vector<BitCodeAbbrev*> Abbrevs;
+ std::string Name;
+
+ std::vector<std::pair<unsigned, std::string> > RecordNames;
+ };
+private:
+ OwningPtr<StreamableMemoryObject> BitcodeBytes;
+
+ std::vector<BlockInfo> BlockInfoRecords;
+
+ /// IgnoreBlockInfoNames - This is set to true if we don't care about the
+ /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer
+ /// uses this.
+ bool IgnoreBlockInfoNames;
+
+ NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION;
+ void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION;
+public:
+ NaClBitstreamReader() : IgnoreBlockInfoNames(true) {
+ }
+
+ NaClBitstreamReader(const unsigned char *Start, const unsigned char *End) {
+ IgnoreBlockInfoNames = true;
+ init(Start, End);
+ }
+
+ NaClBitstreamReader(StreamableMemoryObject *bytes) {
+ BitcodeBytes.reset(bytes);
+ }
+
+ void init(const unsigned char *Start, const unsigned char *End) {
+ assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
+ BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
+ }
+
+ StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
+
+ ~NaClBitstreamReader() {
+ // Free the BlockInfoRecords.
+ while (!BlockInfoRecords.empty()) {
+ BlockInfo &Info = BlockInfoRecords.back();
+ // Free blockinfo abbrev info.
+ for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
+ i != e; ++i)
+ Info.Abbrevs[i]->dropRef();
+ BlockInfoRecords.pop_back();
+ }
+ }
+
+ /// CollectBlockInfoNames - This is called by clients that want block/record
+ /// name information.
+ void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
+ bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
+
+ //===--------------------------------------------------------------------===//
+ // Block Manipulation
+ //===--------------------------------------------------------------------===//
+
+ /// hasBlockInfoRecords - Return true if we've already read and processed the
+ /// block info block for this Bitstream. We only process it for the first
+ /// cursor that walks over it.
+ bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
+
+ /// getBlockInfo - If there is block info for the specified ID, return it,
+ /// otherwise return null.
+ const BlockInfo *getBlockInfo(unsigned BlockID) const {
+ // Common case, the most recent entry matches BlockID.
+ if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
+ return &BlockInfoRecords.back();
+
+ for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
+ i != e; ++i)
+ if (BlockInfoRecords[i].BlockID == BlockID)
+ return &BlockInfoRecords[i];
+ return 0;
+ }
+
+ BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
+ if (const BlockInfo *BI = getBlockInfo(BlockID))
+ return *const_cast<BlockInfo*>(BI);
+
+ // Otherwise, add a new record.
+ BlockInfoRecords.push_back(BlockInfo());
+ BlockInfoRecords.back().BlockID = BlockID;
+ return BlockInfoRecords.back();
+ }
+};
+
+
+/// NaClBitstreamEntry - When advancing through a bitstream cursor,
+/// each advance can discover a few different kinds of entries:
+/// Error - Malformed bitcode was found.
+/// EndBlock - We've reached the end of the current block, (or the end of the
+/// file, which is treated like a series of EndBlock records.
+/// SubBlock - This is the start of a new subblock of a specific ID.
+/// Record - This is a record with a specific AbbrevID.
+///
+struct NaClBitstreamEntry {
+ enum {
+ Error,
+ EndBlock,
+ SubBlock,
+ Record
+ } Kind;
+
+ unsigned ID;
+
+ static NaClBitstreamEntry getError() {
+ NaClBitstreamEntry E; E.Kind = Error; return E;
+ }
+ static NaClBitstreamEntry getEndBlock() {
+ NaClBitstreamEntry E; E.Kind = EndBlock; return E;
+ }
+ static NaClBitstreamEntry getSubBlock(unsigned ID) {
+ NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
+ }
+ static NaClBitstreamEntry getRecord(unsigned AbbrevID) {
+ NaClBitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
+ }
+};
+
+/// NaClBitstreamCursor - This represents a position within a bitcode
+/// file. There may be multiple independent cursors reading within
+/// one bitstream, each maintaining their own local state.
+///
+/// Unlike iterators, NaClBitstreamCursors are heavy-weight objects
+/// that should not be passed by value.
+class NaClBitstreamCursor {
+ friend class Deserializer;
+ NaClBitstreamReader *BitStream;
+ size_t NextChar;
+
+
+ /// CurWord/word_t - This is the current data we have pulled from the stream
+ /// but have not returned to the client. This is specifically and
+ /// intentionally defined to follow the word size of the host machine for
+ /// efficiency. We use word_t in places that are aware of this to make it
+ /// perfectly explicit what is going on.
+ typedef uint32_t word_t;
+ word_t CurWord;
+
+ /// BitsInCurWord - This is the number of bits in CurWord that are valid. This
+ /// is always from [0...31/63] inclusive (depending on word size).
+ unsigned BitsInCurWord;
+
+ // CurCodeSize - This is the declared size of code values used for the current
+ // block, in bits.
+ unsigned CurCodeSize;
+
+ /// CurAbbrevs - Abbrevs installed at in this block.
+ std::vector<BitCodeAbbrev*> CurAbbrevs;
+
+ struct Block {
+ unsigned PrevCodeSize;
+ std::vector<BitCodeAbbrev*> PrevAbbrevs;
+ explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
+ };
+
+ /// BlockScope - This tracks the codesize of parent blocks.
+ SmallVector<Block, 8> BlockScope;
+
+
+public:
+ NaClBitstreamCursor() : BitStream(0), NextChar(0) {
+ }
+ NaClBitstreamCursor(const NaClBitstreamCursor &RHS)
+ : BitStream(0), NextChar(0) {
+ operator=(RHS);
+ }
+
+ explicit NaClBitstreamCursor(NaClBitstreamReader &R) : BitStream(&R) {
+ NextChar = 0;
+ CurWord = 0;
+ BitsInCurWord = 0;
+ CurCodeSize = 2;
+ }
+
+ void init(NaClBitstreamReader &R) {
+ freeState();
+
+ BitStream = &R;
+ NextChar = 0;
+ CurWord = 0;
+ BitsInCurWord = 0;
+ CurCodeSize = 2;
+ }
+
+ ~NaClBitstreamCursor() {
+ freeState();
+ }
+
+ void operator=(const NaClBitstreamCursor &RHS);
+
+ void freeState();
+
+ bool isEndPos(size_t pos) {
+ return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
+ }
+
+ bool canSkipToPos(size_t pos) const {
+ // pos can be skipped to if it is a valid address or one byte past the end.
+ return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
+ static_cast<uint64_t>(pos - 1));
+ }
+
+ uint32_t getWord(size_t pos) {
+ uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
+ BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL);
+ return *reinterpret_cast<support::ulittle32_t *>(buf);
+ }
+
+ bool AtEndOfStream() {
+ return BitsInCurWord == 0 && isEndPos(NextChar);
+ }
+
+ /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
+ unsigned getAbbrevIDWidth() const { return CurCodeSize; }
+
+ /// GetCurrentBitNo - Return the bit # of the bit we are reading.
+ uint64_t GetCurrentBitNo() const {
+ return NextChar*CHAR_BIT - BitsInCurWord;
+ }
+
+ NaClBitstreamReader *getBitStreamReader() {
+ return BitStream;
+ }
+ const NaClBitstreamReader *getBitStreamReader() const {
+ return BitStream;
+ }
+
+ /// Flags that modify the behavior of advance().
+ enum {
+ /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does
+ /// not automatically pop the block scope when the end of a block is
+ /// reached.
+ AF_DontPopBlockAtEnd = 1,
+
+ /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are
+ /// returned just like normal records.
+ AF_DontAutoprocessAbbrevs = 2
+ };
+
+ /// advance - Advance the current bitstream, returning the next entry in the
+ /// stream.
+ NaClBitstreamEntry advance(unsigned Flags = 0) {
+ while (1) {
+ unsigned Code = ReadCode();
+ if (Code == bitc::END_BLOCK) {
+ // Pop the end of the block unless Flags tells us not to.
+ if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
+ return NaClBitstreamEntry::getError();
+ return NaClBitstreamEntry::getEndBlock();
+ }
+
+ if (Code == bitc::ENTER_SUBBLOCK)
+ return NaClBitstreamEntry::getSubBlock(ReadSubBlockID());
+
+ if (Code == bitc::DEFINE_ABBREV &&
+ !(Flags & AF_DontAutoprocessAbbrevs)) {
+ // We read and accumulate abbrev's, the client can't do anything with
+ // them anyway.
+ ReadAbbrevRecord();
+ continue;
+ }
+
+ return NaClBitstreamEntry::getRecord(Code);
+ }
+ }
+
+ /// advanceSkippingSubblocks - This is a convenience function for clients that
+ /// don't expect any subblocks. This just skips over them automatically.
+ NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
+ while (1) {
+ // If we found a normal entry, return it.
+ NaClBitstreamEntry Entry = advance(Flags);
+ if (Entry.Kind != NaClBitstreamEntry::SubBlock)
+ return Entry;
+
+ // If we found a sub-block, just skip over it and check the next entry.
+ if (SkipBlock())
+ return NaClBitstreamEntry::getError();
+ }
+ }
+
+ /// JumpToBit - Reset the stream to the specified bit number.
+ void JumpToBit(uint64_t BitNo) {
+ uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
+ unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
+ assert(canSkipToPos(ByteNo) && "Invalid location");
+
+ // Move the cursor to the right word.
+ NextChar = ByteNo;
+ BitsInCurWord = 0;
+ CurWord = 0;
+
+ // Skip over any bits that are already consumed.
+ if (WordBitNo) {
+ if (sizeof(word_t) > 4)
+ Read64(WordBitNo);
+ else
+ Read(WordBitNo);
+ }
+ }
+
+
+ uint32_t Read(unsigned NumBits) {
+ assert(NumBits && NumBits <= 32 &&
+ "Cannot return zero or more than 32 bits!");
+
+ // If the field is fully contained by CurWord, return it quickly.
+ if (BitsInCurWord >= NumBits) {
+ uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits));
+ CurWord >>= NumBits;
+ BitsInCurWord -= NumBits;
+ return R;
+ }
+
+ // If we run out of data, stop at the end of the stream.
+ if (isEndPos(NextChar)) {
+ CurWord = 0;
+ BitsInCurWord = 0;
+ return 0;
+ }
+
+ uint32_t R = uint32_t(CurWord);
+
+ // Read the next word from the stream.
+ uint8_t Array[sizeof(word_t)] = {0};
+
+ BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array),
+ Array, NULL);
+
+ // Handle big-endian byte-swapping if necessary.
+ support::detail::packed_endian_specific_integral
+ <word_t, support::little, support::unaligned> EndianValue;
+ memcpy(&EndianValue, Array, sizeof(Array));
+
+ CurWord = EndianValue;
+
+ NextChar += sizeof(word_t);
+
+ // Extract NumBits-BitsInCurWord from what we just read.
+ unsigned BitsLeft = NumBits-BitsInCurWord;
+
+ // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive.
+ R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft)))
+ << BitsInCurWord);
+
+ // BitsLeft bits have just been used up from CurWord. BitsLeft is in the
+ // range [1..32]/[1..64] so be careful how we shift.
+ if (BitsLeft != sizeof(word_t)*8)
+ CurWord >>= BitsLeft;
+ else
+ CurWord = 0;
+ BitsInCurWord = sizeof(word_t)*8-BitsLeft;
+ return R;
+ }
+
+ uint64_t Read64(unsigned NumBits) {
+ if (NumBits <= 32) return Read(NumBits);
+
+ uint64_t V = Read(32);
+ return V | (uint64_t)Read(NumBits-32) << 32;
+ }
+
+ uint32_t ReadVBR(unsigned NumBits) {
+ uint32_t Piece = Read(NumBits);
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Piece;
+
+ uint32_t Result = 0;
+ unsigned NextBit = 0;
+ while (1) {
+ Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;
+
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Result;
+
+ NextBit += NumBits-1;
+ Piece = Read(NumBits);
+ }
+ }
+
+ // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The
+ // chunk size of the VBR must still be <= 32 bits though.
+ uint64_t ReadVBR64(unsigned NumBits) {
+ uint32_t Piece = Read(NumBits);
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return uint64_t(Piece);
+
+ uint64_t Result = 0;
+ unsigned NextBit = 0;
+ while (1) {
+ Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;
+
+ if ((Piece & (1U << (NumBits-1))) == 0)
+ return Result;
+
+ NextBit += NumBits-1;
+ Piece = Read(NumBits);
+ }
+ }
+
+private:
+ void SkipToFourByteBoundary() {
+ // If word_t is 64-bits and if we've read less than 32 bits, just dump
+ // the bits we have up to the next 32-bit boundary.
+ if (sizeof(word_t) > 4 &&
+ BitsInCurWord >= 32) {
+ CurWord >>= BitsInCurWord-32;
+ BitsInCurWord = 32;
+ return;
+ }
+
+ BitsInCurWord = 0;
+ CurWord = 0;
+ }
+public:
+
+ unsigned ReadCode() {
+ return Read(CurCodeSize);
+ }
+
+
+ // Block header:
+ // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
+
+ /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for
+ /// the block.
+ unsigned ReadSubBlockID() {
+ return ReadVBR(bitc::BlockIDWidth);
+ }
+
+ /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip
+ /// over the body of this block. If the block record is malformed, return
+ /// true.
+ bool SkipBlock() {
+ // Read and ignore the codelen value. Since we are skipping this block, we
+ // don't care what code widths are used inside of it.
+ ReadVBR(bitc::CodeLenWidth);
+ SkipToFourByteBoundary();
+ unsigned NumFourBytes = Read(bitc::BlockSizeWidth);
+
+ // Check that the block wasn't partially defined, and that the offset isn't
+ // bogus.
+ size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8;
+ if (AtEndOfStream() || !canSkipToPos(SkipTo/8))
+ return true;
+
+ JumpToBit(SkipTo);
+ return false;
+ }
+
+ /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
+ /// the block, and return true if the block has an error.
+ bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0);
+
+ bool ReadBlockEnd() {
+ if (BlockScope.empty()) return true;
+
+ // Block tail:
+ // [END_BLOCK, <align4bytes>]
+ SkipToFourByteBoundary();
+
+ popBlockScope();
+ return false;
+ }
+
+private:
+
+ void popBlockScope() {
+ CurCodeSize = BlockScope.back().PrevCodeSize;
+
+ // Delete abbrevs from popped scope.
+ for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
+ i != e; ++i)
+ CurAbbrevs[i]->dropRef();
+
+ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
+ BlockScope.pop_back();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Record Processing
+ //===--------------------------------------------------------------------===//
+
+private:
+ void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op,
+ SmallVectorImpl<uint64_t> &Vals);
+ void readAbbreviatedField(const BitCodeAbbrevOp &Op,
+ SmallVectorImpl<uint64_t> &Vals);
+ void skipAbbreviatedField(const BitCodeAbbrevOp &Op);
+
+public:
+
+ /// getAbbrev - Return the abbreviation for the specified AbbrevId.
+ const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
+ unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
+ assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
+ return CurAbbrevs[AbbrevNo];
+ }
+
+ /// skipRecord - Read the current record and discard it.
+ void skipRecord(unsigned AbbrevID);
+
+ unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
+ StringRef *Blob = 0);
+
+ //===--------------------------------------------------------------------===//
+ // Abbrev Processing
+ //===--------------------------------------------------------------------===//
+ void ReadAbbrevRecord();
+
+ bool ReadBlockInfoBlock();
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h b/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h
new file mode 100644
index 0000000000..a211a61edc
--- /dev/null
+++ b/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h
@@ -0,0 +1,339 @@
+//===- NaClLLVMBitCodes.h ---------------------------------------*- C++ -*-===//
+// Enum values for the NaCl bitcode wire format
+//
+// 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 NaCl bitcode wire format.
+//
+// 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_NACL_NACLBITCODES_H
+#define LLVM_BITCODE_NACL_NACLBITCODES_H
+
+// TODO(kschimpf) Make a NaCl version of BitCodes.h, so that block id's
+// and abbreviations can be modified.
+#include "llvm/Bitcode/BitCodes.h"
+
+namespace llvm {
+namespace naclbitc {
+ // The only top-level block type defined is for a module.
+ enum NaClBlockIDs {
+ // Blocks
+ MODULE_BLOCK_ID = bitc::FIRST_APPLICATION_BLOCKID,
+
+ // Module sub-block id's.
+ PARAMATTR_BLOCK_ID,
+ PARAMATTR_GROUP_BLOCK_ID,
+
+ CONSTANTS_BLOCK_ID,
+ FUNCTION_BLOCK_ID,
+
+ UNUSED_ID1,
+
+ VALUE_SYMTAB_BLOCK_ID,
+ METADATA_BLOCK_ID,
+ METADATA_ATTACHMENT_ID,
+
+ TYPE_BLOCK_ID_NEW,
+
+ USELIST_BLOCK_ID
+ };
+
+
+ /// MODULE blocks have a number of optional fields and subblocks.
+ enum NaClModuleCodes {
+ MODULE_CODE_VERSION = 1, // VERSION: [version#]
+ MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N]
+ MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N]
+ MODULE_CODE_ASM = 4, // ASM: [strchr x N]
+ MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N]
+
+ // FIXME: Remove DEPLIB in 4.0.
+ MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N]
+
+ // GLOBALVAR: [pointer type, isconst, initid,
+ // linkage, alignment, section, visibility, threadlocal]
+ MODULE_CODE_GLOBALVAR = 7,
+
+ // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
+ // section, visibility, gc, unnamed_addr]
+ MODULE_CODE_FUNCTION = 8,
+
+ // ALIAS: [alias type, aliasee val#, linkage, visibility]
+ MODULE_CODE_ALIAS = 9,
+
+ // MODULE_CODE_PURGEVALS: [numvals]
+ MODULE_CODE_PURGEVALS = 10,
+
+ MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N]
+ };
+
+ /// PARAMATTR blocks have code for defining a parameter attribute set.
+ enum NaClAttributeCodes {
+ // FIXME: Remove `PARAMATTR_CODE_ENTRY_OLD' in 4.0
+ PARAMATTR_CODE_ENTRY_OLD = 1, // ENTRY: [paramidx0, attr0,
+ // paramidx1, attr1...]
+ PARAMATTR_CODE_ENTRY = 2, // ENTRY: [paramidx0, attrgrp0,
+ // paramidx1, attrgrp1, ...]
+ PARAMATTR_GRP_CODE_ENTRY = 3 // ENTRY: [id, attr0, att1, ...]
+ };
+
+ /// TYPE blocks have codes for each type primitive they use.
+ enum NaClTypeCodes {
+ TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries]
+
+ // Type Codes
+ TYPE_CODE_VOID = 2, // VOID
+ TYPE_CODE_FLOAT = 3, // FLOAT
+ TYPE_CODE_DOUBLE = 4, // DOUBLE
+ TYPE_CODE_LABEL = 5, // LABEL
+ TYPE_CODE_OPAQUE = 6, // OPAQUE
+ TYPE_CODE_INTEGER = 7, // INTEGER: [width]
+ TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
+
+ TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty,
+ // paramty x N]
+
+ TYPE_CODE_HALF = 10, // HALF
+
+ TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
+ TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
+
+ // These are not with the other floating point types because they're
+ // a late addition, and putting them in the right place breaks
+ // binary compatibility.
+ TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE
+ TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
+ TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
+
+ TYPE_CODE_METADATA = 16, // METADATA
+
+ TYPE_CODE_X86_MMX = 17, // X86 MMX
+
+ TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N]
+ TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N]
+ TYPE_CODE_STRUCT_NAMED = 20,// STRUCT_NAMED: [ispacked, eltty x N]
+
+ TYPE_CODE_FUNCTION = 21 // FUNCTION: [vararg, retty, paramty x N]
+ };
+
+ // The type symbol table only has one code (TST_ENTRY_CODE).
+ enum NaClTypeSymtabCodes {
+ TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N]
+ };
+
+ // The value symbol table only has one code (VST_ENTRY_CODE).
+ enum NaClValueSymtabCodes {
+ VST_CODE_ENTRY = 1, // VST_ENTRY: [valid, namechar x N]
+ VST_CODE_BBENTRY = 2 // VST_BBENTRY: [bbid, namechar x N]
+ };
+
+ enum NaClMetadataCodes {
+ METADATA_STRING = 1, // MDSTRING: [values]
+ // 2 is unused.
+ // 3 is unused.
+ METADATA_NAME = 4, // STRING: [values]
+ // 5 is unused.
+ METADATA_KIND = 6, // [n x [id, name]]
+ // 7 is unused.
+ METADATA_NODE = 8, // NODE: [n x (type num, value num)]
+ METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)]
+ METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
+ METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]]
+ };
+
+ // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
+ // constant and maintains an implicit current type value.
+ enum NaClConstantsCodes {
+ CST_CODE_SETTYPE = 1, // SETTYPE: [typeid]
+ CST_CODE_NULL = 2, // NULL
+ CST_CODE_UNDEF = 3, // UNDEF
+ CST_CODE_INTEGER = 4, // INTEGER: [intval]
+ CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval]
+ CST_CODE_FLOAT = 6, // FLOAT: [fpval]
+ CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number]
+ CST_CODE_STRING = 8, // STRING: [values]
+ CST_CODE_CSTRING = 9, // CSTRING: [values]
+ CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval]
+ CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval]
+ CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands]
+ CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval]
+ CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval]
+ CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval]
+ CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval]
+ CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred]
+ CST_CODE_INLINEASM_OLD = 18, // INLINEASM: [sideeffect|alignstack,
+ // asmstr,conststr]
+ CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval]
+ CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands]
+ CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
+ CST_CODE_DATA = 22, // DATA: [n x elements]
+ CST_CODE_INLINEASM = 23 // INLINEASM: [sideeffect|alignstack|
+ // asmdialect,asmstr,conststr]
+ };
+
+ /// CastOpcodes - These are values used in the bitcode files to encode which
+ /// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums
+ /// have no fixed relation to the LLVM IR enum values. Changing these will
+ /// break compatibility with old files.
+ enum NaClCastOpcodes {
+ 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 NaClBinaryOpcodes {
+ BINOP_ADD = 0,
+ BINOP_SUB = 1,
+ BINOP_MUL = 2,
+ BINOP_UDIV = 3,
+ BINOP_SDIV = 4, // overloaded for FP
+ BINOP_UREM = 5,
+ BINOP_SREM = 6, // overloaded for FP
+ BINOP_SHL = 7,
+ BINOP_LSHR = 8,
+ BINOP_ASHR = 9,
+ BINOP_AND = 10,
+ BINOP_OR = 11,
+ BINOP_XOR = 12
+ };
+
+ /// These are values used in the bitcode files to encode AtomicRMW operations.
+ /// The values of these enums have no fixed relation to the LLVM IR enum
+ /// values. Changing these will break compatibility with old files.
+ enum NaClRMWOperations {
+ RMW_XCHG = 0,
+ RMW_ADD = 1,
+ RMW_SUB = 2,
+ RMW_AND = 3,
+ RMW_NAND = 4,
+ RMW_OR = 5,
+ RMW_XOR = 6,
+ RMW_MAX = 7,
+ RMW_MIN = 8,
+ RMW_UMAX = 9,
+ RMW_UMIN = 10
+ };
+
+ /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
+ /// OverflowingBinaryOperator's SubclassOptionalData contents.
+ enum NaClOverflowingBinaryOperatorOptionalFlags {
+ OBO_NO_UNSIGNED_WRAP = 0,
+ OBO_NO_SIGNED_WRAP = 1
+ };
+
+ /// PossiblyExactOperatorOptionalFlags - Flags for serializing
+ /// PossiblyExactOperator's SubclassOptionalData contents.
+ enum NaClPossiblyExactOperatorOptionalFlags {
+ PEO_EXACT = 0
+ };
+
+ /// Encoded AtomicOrdering values.
+ enum NaClAtomicOrderingCodes {
+ ORDERING_NOTATOMIC = 0,
+ ORDERING_UNORDERED = 1,
+ ORDERING_MONOTONIC = 2,
+ ORDERING_ACQUIRE = 3,
+ ORDERING_RELEASE = 4,
+ ORDERING_ACQREL = 5,
+ ORDERING_SEQCST = 6
+ };
+
+ /// Encoded SynchronizationScope values.
+ enum NaClAtomicSynchScopeCodes {
+ SYNCHSCOPE_SINGLETHREAD = 0,
+ SYNCHSCOPE_CROSSTHREAD = 1
+ };
+
+ // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
+ // can contain a constant block (CONSTANTS_BLOCK_ID).
+ enum NaClFunctionCodes {
+ FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n]
+
+ FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval]
+ FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval]
+ FUNC_CODE_INST_GEP = 4, // GEP: [n x operands]
+ FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval]
+ FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval]
+ FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval]
+ FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval]
+ FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred]
+
+ FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
+ FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
+ FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...]
+ FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
+ // 14 is unused.
+ FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
+
+ FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...]
+ // 17 is unused.
+ // 18 is unused.
+ FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align]
+ FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol]
+ // 21 is unused.
+ // 22 is unused.
+ FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty]
+ // This store code encodes the pointer type, rather than the value type
+ // this is so information only available in the pointer type (e.g. address
+ // spaces) is retained.
+ FUNC_CODE_INST_STORE = 24, // STORE: [ptrty,ptr,val, align, vol]
+ // 25 is unused.
+ FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
+ FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
+ // fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to
+ // support legacy vicmp/vfcmp instructions.
+ FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
+ // new select on i1 or [N x i1]
+ FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
+ FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands]
+ FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...]
+ // 32 is unused.
+ FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN
+
+ FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...]
+
+ FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal]
+ FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope]
+ FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
+ // ordering, synchscope]
+ FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
+ // align, vol,
+ // ordering, synchscope]
+ FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
+ FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
+ FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
+ // ordering, synchscope]
+ FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
+ // ordering, synchscope]
+ };
+
+ enum NaClUseListCodes {
+ USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD.
+ };
+} // End naclbitc namespace
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
index 2b905b97e8..d505af0a1f 100644
--- a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
+++ b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
@@ -8,22 +8,142 @@
//
//===----------------------------------------------------------------------===//
//
-// This header defines interfaces to read and write LLVM bitcode files/streams.
+// This header defines interfaces to read and write NaCl bitcode wire format
+// files.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_NACL_NACLREADERWRITER_H
#define LLVM_BITCODE_NACL_NACLREADERWRITER_H
+#include <string>
+
namespace llvm {
+ class MemoryBuffer;
+ class DataStreamer;
+ class LLVMContext;
class Module;
class raw_ostream;
+ /// getNaClLazyBitcodeModule - Read the header of the specified bitcode buffer
+ /// and prepare for lazy deserialization of function bodies. If successful,
+ /// this takes ownership of 'buffer' and returns a non-null pointer. On
+ /// error, this returns null, *does not* take ownership of Buffer, and fills
+ /// in *ErrMsg with an error description if ErrMsg is non-null.
+ Module *getNaClLazyBitcodeModule(MemoryBuffer *Buffer,
+ LLVMContext &Context,
+ std::string *ErrMsg = 0);
+
+ /// getNaClStreamedBitcodeModule - Read the header of the specified stream
+ /// and prepare for lazy deserialization and streaming of function bodies.
+ /// On error, this returns null, and fills in *ErrMsg with an error
+ /// description if ErrMsg is non-null.
+ Module *getNaClStreamedBitcodeModule(const std::string &name,
+ DataStreamer *streamer,
+ LLVMContext &Context,
+ std::string *ErrMsg = 0);
+
+ /// NaClParseBitcodeFile - 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 *NaClParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context,
+ std::string *ErrMsg = 0);
+
/// NaClWriteBitcodeToFile - Write the specified module to the
/// specified raw output stream, using PNaCl wire format. For
/// streams where it matters, the given stream should be in "binary"
/// mode.
void NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out);
+ /// isNaClBitcodeWrapper - Return true if the given bytes are the
+ /// magic bytes for an LLVM IR bitcode wrapper.
+ ///
+ inline bool isNaClBitcodeWrapper(const unsigned char *BufPtr,
+ const unsigned char *BufEnd) {
+ // See if you can find the hidden message in the magic bytes :-).
+ // (Hint: it's a little-endian encoding.)
+ return BufPtr != BufEnd &&
+ BufPtr[0] == 0xDE &&
+ BufPtr[1] == 0xC0 &&
+ BufPtr[2] == 0x17 &&
+ BufPtr[3] == 0x0B;
+ }
+
+ /// isNaClRawBitcode - Return true if the given bytes are the magic
+ /// bytes for raw LLVM IR bitcode (without a wrapper).
+ ///
+ inline bool isNaClRawBitcode(const unsigned char *BufPtr,
+ const unsigned char *BufEnd) {
+ // These bytes sort of have a hidden message, but it's not in
+ // little-endian this time, and it's a little redundant.
+ return BufPtr != BufEnd &&
+ BufPtr[0] == 'B' &&
+ BufPtr[1] == 'C' &&
+ BufPtr[2] == 0xc0 &&
+ BufPtr[3] == 0xde;
+ }
+
+ /// isNaClBitcode - Return true if the given bytes are the magic bytes for
+ /// LLVM IR bitcode, either with or without a wrapper.
+ ///
+ inline bool isNaClBitcode(const unsigned char *BufPtr,
+ const unsigned char *BufEnd) {
+ return isNaClBitcodeWrapper(BufPtr, BufEnd) ||
+ isNaClRawBitcode(BufPtr, BufEnd);
+ }
+
+ /// SkipNaClBitcodeWrapperHeader - 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 ...
+ /// };
+ ///
+ /// TODO(kschimpf): Consider changing Magic and/or gunk to communicate
+ /// file is PNaCl wire format file (rather than LLVM bitcode).
+ ///
+ /// TODO(kschimpf): Add code to read gunk in, and store it so it is
+ /// accessable.
+ ///
+ /// This function is called when we find a file with a matching magic number.
+ /// In this case, skip down to the subsection of the file that is actually a
+ /// BC file.
+ /// If 'VerifyBufferSize' is true, check that the buffer is large enough to
+ /// contain the whole bitcode file.
+ inline bool SkipNaClBitcodeWrapperHeader(const unsigned char *&BufPtr,
+ const unsigned char *&BufEnd,
+ bool VerifyBufferSize) {
+ enum {
+ KnownHeaderSize = 4*4, // Size of header we read.
+ OffsetField = 2*4, // Offset in bytes to Offset field.
+ SizeField = 3*4 // Offset in bytes to Size field.
+ };
+
+ // Must contain the header!
+ if (BufEnd-BufPtr < KnownHeaderSize) return true;
+
+ unsigned Offset = ( BufPtr[OffsetField ] |
+ (BufPtr[OffsetField+1] << 8) |
+ (BufPtr[OffsetField+2] << 16) |
+ (BufPtr[OffsetField+3] << 24));
+ unsigned Size = ( BufPtr[SizeField ] |
+ (BufPtr[SizeField +1] << 8) |
+ (BufPtr[SizeField +2] << 16) |
+ (BufPtr[SizeField +3] << 24));
+
+ // Verify that Offset+Size fits in the file.
+ if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr))
+ return true;
+ BufPtr += Offset;
+ BufEnd = BufPtr+Size;
+ return false;
+ }
+
} // end llvm namespace
#endif
diff --git a/lib/Bitcode/NaCl/CMakeLists.txt b/lib/Bitcode/NaCl/CMakeLists.txt
index 2854f037d3..5a8b272bef 100644
--- a/lib/Bitcode/NaCl/CMakeLists.txt
+++ b/lib/Bitcode/NaCl/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(Writer)
+add_subdirectory(Reader)
diff --git a/lib/Bitcode/NaCl/LLVMBuild.txt b/lib/Bitcode/NaCl/LLVMBuild.txt
index 154bb0c589..a29928d2a0 100644
--- a/lib/Bitcode/NaCl/LLVMBuild.txt
+++ b/lib/Bitcode/NaCl/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = Writer
+subdirectories = Writer Reader
[component_0]
type = Group
diff --git a/lib/Bitcode/NaCl/Makefile b/lib/Bitcode/NaCl/Makefile
index a1e85e919b..5bbbc351a1 100644
--- a/lib/Bitcode/NaCl/Makefile
+++ b/lib/Bitcode/NaCl/Makefile
@@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../..
-PARALLEL_DIRS = Writer
+PARALLEL_DIRS = Writer Reader
include $(LEVEL)/Makefile.common
diff --git a/lib/Bitcode/NaCl/Reader/CMakeLists.txt b/lib/Bitcode/NaCl/Reader/CMakeLists.txt
new file mode 100644
index 0000000000..1013174307
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_llvm_library(LLVMNaClBitReader
+ NaClBitcodeReader.cpp
+ NaClBitstreamReader.cpp
+ )
+
+add_dependencies(LLVMNaClBitReader intrinsics_gen)
diff --git a/lib/Bitcode/NaCl/Reader/LLVMBuild.txt b/lib/Bitcode/NaCl/Reader/LLVMBuild.txt
new file mode 100644
index 0000000000..acf354f5b5
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/Bitcode/NaClReader/LLVMBuild.txt -------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = NaClBitReader
+parent = NaClBitcode
+required_libraries = Core Support
diff --git a/lib/Bitcode/NaCl/Reader/Makefile b/lib/Bitcode/NaCl/Reader/Makefile
new file mode 100644
index 0000000000..92c75c29a4
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Bitcode/NaCl/Reader/Makefile --------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME = LLVMNaClBitReader
+BUILD_ARCHIVE = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
new file mode 100644
index 0000000000..79b6ea6cca
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
@@ -0,0 +1,3124 @@
+//===- NaClBitcodeReader.cpp ----------------------------------------------===//
+// Internal NaClBitcodeReader implementation
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "NaClBitcodeReader.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/AutoUpgrade.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+using namespace llvm;
+
+enum {
+ SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
+};
+
+void NaClBitcodeReader::materializeForwardReferencedFunctions() {
+ while (!BlockAddrFwdRefs.empty()) {
+ Function *F = BlockAddrFwdRefs.begin()->first;
+ F->Materialize();
+ }
+}
+
+void NaClBitcodeReader::FreeState() {
+ if (BufferOwned)
+ delete Buffer;
+ Buffer = 0;
+ std::vector<Type*>().swap(TypeList);
+ ValueList.clear();
+ MDValueList.clear();
+
+ std::vector<AttributeSet>().swap(MAttributes);
+ std::vector<BasicBlock*>().swap(FunctionBBs);
+ std::vector<Function*>().swap(FunctionsWithBodies);
+ DeferredFunctionInfo.clear();
+ MDKindMap.clear();
+
+ assert(BlockAddrFwdRefs.empty() && "Unresolved blockaddress fwd references");
+}
+
+//===----------------------------------------------------------------------===//
+// Helper functions to implement forward reference resolution, etc.
+//===----------------------------------------------------------------------===//
+
+/// ConvertToString - Convert a string from a record into an std::string, return
+/// true on failure.
+template<typename StrTy>
+static bool ConvertToString(ArrayRef<uint64_t> Record, unsigned Idx,
+ StrTy &Result) {
+ if (Idx > Record.size())
+ return true;
+
+ for (unsigned i = Idx, e = Record.size(); i != e; ++i)
+ Result += (char)Record[i];
+ return false;
+}
+
+static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) {
+ switch (Val) {
+ default: // Map unknown/new linkages to external
+ case 0: return GlobalValue::ExternalLinkage;
+ case 1: return GlobalValue::WeakAnyLinkage;
+ case 2: return GlobalValue::AppendingLinkage;
+ case 3: return GlobalValue::InternalLinkage;
+ case 4: return GlobalValue::LinkOnceAnyLinkage;
+ case 5: return GlobalValue::DLLImportLinkage;
+ case 6: return GlobalValue::DLLExportLinkage;
+ case 7: return GlobalValue::ExternalWeakLinkage;
+ case 8: return GlobalValue::CommonLinkage;
+ case 9: return GlobalValue::PrivateLinkage;
+ case 10: return GlobalValue::WeakODRLinkage;
+ case 11: return GlobalValue::LinkOnceODRLinkage;
+ case 12: return GlobalValue::AvailableExternallyLinkage;
+ case 13: return GlobalValue::LinkerPrivateLinkage;
+ case 14: return GlobalValue::LinkerPrivateWeakLinkage;
+ case 15: return GlobalValue::LinkOnceODRAutoHideLinkage;
+ }
+}
+
+static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
+ switch (Val) {
+ default: // Map unknown visibilities to default.
+ case 0: return GlobalValue::DefaultVisibility;
+ case 1: return GlobalValue::HiddenVisibility;
+ case 2: return GlobalValue::ProtectedVisibility;
+ }
+}
+
+static GlobalVariable::ThreadLocalMode GetDecodedThreadLocalMode(unsigned Val) {
+ switch (Val) {
+ case 0: return GlobalVariable::NotThreadLocal;
+ default: // Map unknown non-zero value to general dynamic.
+ case 1: return GlobalVariable::GeneralDynamicTLSModel;
+ case 2: return GlobalVariable::LocalDynamicTLSModel;
+ case 3: return GlobalVariable::InitialExecTLSModel;
+ case 4: return GlobalVariable::LocalExecTLSModel;
+ }
+}
+
+static int GetDecodedCastOpcode(unsigned Val) {
+ switch (Val) {
+ default: return -1;
+ case naclbitc::CAST_TRUNC : return Instruction::Trunc;
+ case naclbitc::CAST_ZEXT : return Instruction::ZExt;
+ case naclbitc::CAST_SEXT : return Instruction::SExt;
+ case naclbitc::CAST_FPTOUI : return Instruction::FPToUI;
+ case naclbitc::CAST_FPTOSI : return Instruction::FPToSI;
+ case naclbitc::CAST_UITOFP : return Instruction::UIToFP;
+ case naclbitc::CAST_SITOFP : return Instruction::SIToFP;
+ case naclbitc::CAST_FPTRUNC : return Instruction::FPTrunc;
+ case naclbitc::CAST_FPEXT : return Instruction::FPExt;
+ case naclbitc::CAST_PTRTOINT: return Instruction::PtrToInt;
+ case naclbitc::CAST_INTTOPTR: return Instruction::IntToPtr;
+ case naclbitc::CAST_BITCAST : return Instruction::BitCast;
+ }
+}
+static int GetDecodedBinaryOpcode(unsigned Val, Type *Ty) {
+ switch (Val) {
+ default: return -1;
+ case naclbitc::BINOP_ADD:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add;
+ case naclbitc::BINOP_SUB:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub;
+ case naclbitc::BINOP_MUL:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul;
+ case naclbitc::BINOP_UDIV: return Instruction::UDiv;
+ case naclbitc::BINOP_SDIV:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv;
+ case naclbitc::BINOP_UREM: return Instruction::URem;
+ case naclbitc::BINOP_SREM:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem;
+ case naclbitc::BINOP_SHL: return Instruction::Shl;
+ case naclbitc::BINOP_LSHR: return Instruction::LShr;
+ case naclbitc::BINOP_ASHR: return Instruction::AShr;
+ case naclbitc::BINOP_AND: return Instruction::And;
+ case naclbitc::BINOP_OR: return Instruction::Or;
+ case naclbitc::BINOP_XOR: return Instruction::Xor;
+ }
+}
+
+static AtomicRMWInst::BinOp GetDecodedRMWOperation(unsigned Val) {
+ switch (Val) {
+ default: return AtomicRMWInst::BAD_BINOP;
+ case naclbitc::RMW_XCHG: return AtomicRMWInst::Xchg;
+ case naclbitc::RMW_ADD: return AtomicRMWInst::Add;
+ case naclbitc::RMW_SUB: return AtomicRMWInst::Sub;
+ case naclbitc::RMW_AND: return AtomicRMWInst::And;
+ case naclbitc::RMW_NAND: return AtomicRMWInst::Nand;
+ case naclbitc::RMW_OR: return AtomicRMWInst::Or;
+ case naclbitc::RMW_XOR: return AtomicRMWInst::Xor;
+ case naclbitc::RMW_MAX: return AtomicRMWInst::Max;
+ case naclbitc::RMW_MIN: return AtomicRMWInst::Min;
+ case naclbitc::RMW_UMAX: return AtomicRMWInst::UMax;
+ case naclbitc::RMW_UMIN: return AtomicRMWInst::UMin;
+ }
+}
+
+static AtomicOrdering GetDecodedOrdering(unsigned Val) {
+ switch (Val) {
+ case naclbitc::ORDERING_NOTATOMIC: return NotAtomic;
+ case naclbitc::ORDERING_UNORDERED: return Unordered;
+ case naclbitc::ORDERING_MONOTONIC: return Monotonic;
+ case naclbitc::ORDERING_ACQUIRE: return Acquire;
+ case naclbitc::ORDERING_RELEASE: return Release;
+ case naclbitc::ORDERING_ACQREL: return AcquireRelease;
+ default: // Map unknown orderings to sequentially-consistent.
+ case naclbitc::ORDERING_SEQCST: return SequentiallyConsistent;
+ }
+}
+
+static SynchronizationScope GetDecodedSynchScope(unsigned Val) {
+ switch (Val) {
+ case naclbitc::SYNCHSCOPE_SINGLETHREAD: return SingleThread;
+ default: // Map unknown scopes to cross-thread.
+ case naclbitc::SYNCHSCOPE_CROSSTHREAD: return CrossThread;
+ }
+}
+
+namespace llvm {
+namespace {
+ /// @brief A class for maintaining the slot number definition
+ /// as a placeholder for the actual definition for forward constants defs.
+ class ConstantPlaceHolder : public ConstantExpr {
+ void operator=(const ConstantPlaceHolder &) LLVM_DELETED_FUNCTION;
+ public:
+ // allocate space for exactly one operand
+ void *operator new(size_t s) {
+ return User::operator new(s, 1);
+ }
+ explicit ConstantPlaceHolder(Type *Ty, LLVMContext& Context)
+ : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
+ Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
+ }
+
+ /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Value *V) {
+ return isa<ConstantExpr>(V) &&
+ cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
+ }
+
+
+ /// Provide fast operand accessors
+ //DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ };
+}
+
+// FIXME: can we inherit this from ConstantExpr?
+template <>
+struct OperandTraits<ConstantPlaceHolder> :
+ public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
+};
+}
+
+
+void NaClBitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) {
+ if (Idx == size()) {
+ push_back(V);
+ return;
+ }
+
+ if (Idx >= size())
+ resize(Idx+1);
+
+ WeakVH &OldV = ValuePtrs[Idx];
+ if (OldV == 0) {
+ OldV = V;
+ return;
+ }
+
+ // Handle constants and non-constants (e.g. instrs) differently for
+ // efficiency.
+ if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
+ ResolveConstants.push_back(std::make_pair(PHC, Idx));
+ OldV = V;
+ } else {
+ // If there was a forward reference to this value, replace it.
+ Value *PrevVal = OldV;
+ OldV->replaceAllUsesWith(V);
+ delete PrevVal;
+ }
+}
+
+
+Constant *NaClBitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
+ Type *Ty) {
+ if (Idx >= size())
+ resize(Idx + 1);
+
+ if (Value *V = ValuePtrs[Idx]) {
+ assert(Ty == V->getType() && "Type mismatch in constant table!");
+ return cast<Constant>(V);
+ }
+
+ // Create and return a placeholder, which will later be RAUW'd.
+ Constant *C = new ConstantPlaceHolder(Ty, Context);
+ ValuePtrs[Idx] = C;
+ return C;
+}
+
+Value *NaClBitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
+ if (Idx >= size())
+ resize(Idx + 1);
+
+ if (Value *V = ValuePtrs[Idx]) {
+ assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
+ return V;
+ }
+
+ // No type specified, must be invalid reference.
+ if (Ty == 0) return 0;
+
+ // Create and return a placeholder, which will later be RAUW'd.
+ Value *V = new Argument(Ty);
+ ValuePtrs[Idx] = V;
+ return V;
+}
+
+/// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+/// resolves any forward references. The idea behind this is that we sometimes
+/// get constants (such as large arrays) which reference *many* forward ref
+/// constants. Replacing each of these causes a lot of thrashing when
+/// building/reuniquing the constant. Instead of doing this, we look at all the
+/// uses and rewrite all the place holders at once for any constant that uses
+/// a placeholder.
+void NaClBitcodeReaderValueList::ResolveConstantForwardRefs() {
+ // Sort the values by-pointer so that they are efficient to look up with a
+ // binary search.
+ std::sort(ResolveConstants.begin(), ResolveConstants.end());
+
+ SmallVector<Constant*, 64> NewOps;
+
+ while (!ResolveConstants.empty()) {
+ Value *RealVal = operator[](ResolveConstants.back().second);
+ Constant *Placeholder = ResolveConstants.back().first;
+ ResolveConstants.pop_back();
+
+ // Loop over all users of the placeholder, updating them to reference the
+ // new value. If they reference more than one placeholder, update them all
+ // at once.
+ while (!Placeholder->use_empty()) {
+ Value::use_iterator UI = Placeholder->use_begin();
+ User *U = *UI;
+
+ // If the using object isn't uniqued, just update the operands. This
+ // handles instructions and initializers for global variables.
+ if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
+ UI.getUse().set(RealVal);
+ continue;
+ }
+
+ // Otherwise, we have a constant that uses the placeholder. Replace that
+ // constant with a new constant that has *all* placeholder uses updated.
+ Constant *UserC = cast<Constant>(U);
+ for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
+ I != E; ++I) {
+ Value *NewOp;
+ if (!isa<ConstantPlaceHolder>(*I)) {
+ // Not a placeholder reference.
+ NewOp = *I;
+ } else if (*I == Placeholder) {
+ // Common case is that it just references this one placeholder.
+ NewOp = RealVal;
+ } else {
+ // Otherwise, look up the placeholder in ResolveConstants.
+ ResolveConstantsTy::iterator It =
+ std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(),
+ std::pair<Constant*, unsigned>(cast<Constant>(*I),
+ 0));
+ assert(It != ResolveConstants.end() && It->first == *I);
+ NewOp = operator[](It->second);
+ }
+
+ NewOps.push_back(cast<Constant>(NewOp));
+ }
+
+ // Make the new constant.
+ Constant *NewC;
+ if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
+ NewC = ConstantArray::get(UserCA->getType(), NewOps);
+ } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
+ NewC = ConstantStruct::get(UserCS->getType(), NewOps);
+ } else if (isa<ConstantVector>(UserC)) {
+ NewC = ConstantVector::get(NewOps);
+ } else {
+ assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
+ NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
+ }
+
+ UserC->replaceAllUsesWith(NewC);
+ UserC->destroyConstant();
+ NewOps.clear();
+ }
+
+ // Update all ValueHandles, they should be the only users at this point.
+ Placeholder->replaceAllUsesWith(RealVal);
+ delete Placeholder;
+ }
+}
+
+void NaClBitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) {
+ if (Idx == size()) {
+ push_back(V);
+ return;
+ }
+
+ if (Idx >= size())
+ resize(Idx+1);
+
+ WeakVH &OldV = MDValuePtrs[Idx];
+ if (OldV == 0) {
+ OldV = V;
+ return;
+ }
+
+ // If there was a forward reference to this value, replace it.
+ MDNode *PrevVal = cast<MDNode>(OldV);
+ OldV->replaceAllUsesWith(V);
+ MDNode::deleteTemporary(PrevVal);
+ // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new
+ // value for Idx.
+ MDValuePtrs[Idx] = V;
+}
+
+Value *NaClBitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+ if (Idx >= size())
+ resize(Idx + 1);
+
+ if (Value *V = MDValuePtrs[Idx]) {
+ assert(V->getType()->isMetadataTy() && "Type mismatch in value table!");
+ return V;
+ }
+
+ // Create and return a placeholder, which will later be RAUW'd.
+ Value *V = MDNode::getTemporary(Context, ArrayRef<Value*>());
+ MDValuePtrs[Idx] = V;
+ return V;
+}
+
+Type *NaClBitcodeReader::getTypeByID(unsigned ID) {
+ // The type table size is always specified correctly.
+ if (ID >= TypeList.size())
+ return 0;
+
+ if (Type *Ty = TypeList[ID])
+ return Ty;
+
+ // If we have a forward reference, the only possible case is when it is to a
+ // named struct. Just create a placeholder for now.
+ return TypeList[ID] = StructType::create(Context);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Functions for parsing blocks from the bitcode file
+//===----------------------------------------------------------------------===//
+
+
+/// \brief This fills an AttrBuilder object with the LLVM attributes that have
+/// been decoded from the given integer. This function must stay in sync with
+/// 'encodeLLVMAttributesForBitcode'.
+static void decodeLLVMAttributesForBitcode(AttrBuilder &B,
+ uint64_t EncodedAttrs) {
+ // FIXME: Remove in 4.0.
+
+ // The alignment is stored as a 16-bit raw value from bits 31--16. We shift
+ // the bits above 31 down by 11 bits.
+ unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
+ assert((!Alignment || isPowerOf2_32(Alignment)) &&
+ "Alignment must be a power of two.");
+
+ if (Alignment)
+ B.addAlignmentAttr(Alignment);
+ B.addRawValue(((EncodedAttrs & (0xfffffULL << 32)) >> 11) |
+ (EncodedAttrs & 0xffff));
+}
+
+bool NaClBitcodeReader::ParseAttributeBlock() {
+ if (Stream.EnterSubBlock(naclbitc::PARAMATTR_BLOCK_ID))
+ return Error("Malformed block record");
+
+ if (!MAttributes.empty())
+ return Error("Multiple PARAMATTR blocks found!");
+
+ SmallVector<uint64_t, 64> Record;
+
+ SmallVector<AttributeSet, 8> Attrs;
+
+ // Read all the records.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("Error at end of PARAMATTR block");
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: // Default behavior: ignore.
+ break;
+ case naclbitc::PARAMATTR_CODE_ENTRY_OLD: { // ENTRY: [paramidx0, attr0, ...]
+ // FIXME: Remove in 4.0.
+ if (Record.size() & 1)
+ return Error("Invalid ENTRY record");
+
+ for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+ AttrBuilder B;
+ decodeLLVMAttributesForBitcode(B, Record[i+1]);
+ Attrs.push_back(AttributeSet::get(Context, Record[i], B));
+ }
+
+ MAttributes.push_back(AttributeSet::get(Context, Attrs));
+ Attrs.clear();
+ break;
+ }
+ case naclbitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [attrgrp0, attrgrp1, ...]
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ Attrs.push_back(MAttributeGroups[Record[i]]);
+
+ MAttributes.push_back(AttributeSet::get(Context, Attrs));
+ Attrs.clear();
+ break;
+ }
+ }
+ }
+}
+
+bool NaClBitcodeReader::ParseAttributeGroupBlock() {
+ if (Stream.EnterSubBlock(naclbitc::PARAMATTR_GROUP_BLOCK_ID))
+ return Error("Malformed block record");
+
+ if (!MAttributeGroups.empty())
+ return Error("Multiple PARAMATTR_GROUP blocks found!");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("Error at end of PARAMATTR_GROUP block");
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: // Default behavior: ignore.
+ break;
+ case naclbitc::PARAMATTR_GRP_CODE_ENTRY: {
+ // ENTRY: [grpid, idx, a0, a1, ...]
+ if (Record.size() < 3)
+ return Error("Invalid ENTRY record");
+
+ uint64_t GrpID = Record[0];
+ uint64_t Idx = Record[1]; // Index of the object this attribute refers to.
+
+ AttrBuilder B;
+ for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+ if (Record[i] == 0) { // Enum attribute
+ B.addAttribute(Attribute::AttrKind(Record[++i]));
+ } else if (Record[i] == 1) { // Align attribute
+ if (Attribute::AttrKind(Record[++i]) == Attribute::Alignment)
+ B.addAlignmentAttr(Record[++i]);
+ else
+ B.addStackAlignmentAttr(Record[++i]);
+ } else { // String attribute
+ assert((Record[i] == 3 || Record[i] == 4) &&
+ "Invalid attribute group entry");
+ bool HasValue = (Record[i++] == 4);
+ SmallString<64> KindStr;
+ SmallString<64> ValStr;
+
+ while (Record[i] != 0 && i != e)
+ KindStr += Record[i++];
+ assert(Record[i] == 0 && "Kind string not null terminated");
+
+ if (HasValue) {
+ // Has a value associated with it.
+ ++i; // Skip the '0' that terminates the "kind" string.
+ while (Record[i] != 0 && i != e)
+ ValStr += Record[i++];
+ assert(Record[i] == 0 && "Value string not null terminated");
+ }
+
+ B.addAttribute(KindStr.str(), ValStr.str());
+ }
+ }
+
+ MAttributeGroups[GrpID] = AttributeSet::get(Context, Idx, B);
+ break;
+ }
+ }
+ }
+}
+
+bool NaClBitcodeReader::ParseTypeTable() {
+ if (Stream.EnterSubBlock(naclbitc::TYPE_BLOCK_ID_NEW))
+ return Error("Malformed block record");
+
+ return ParseTypeTableBody();
+}
+
+bool NaClBitcodeReader::ParseTypeTableBody() {
+ if (!TypeList.empty())
+ return Error("Multiple TYPE_BLOCKs found!");
+
+ SmallVector<uint64_t, 64> Record;
+ unsigned NumRecords = 0;
+
+ SmallString<64> TypeName;
+
+ // Read all the records for this type table.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ Error("Error in the type table block");
+ return true;
+ case NaClBitstreamEntry::EndBlock:
+ if (NumRecords != TypeList.size())
+ return Error("Invalid type forward reference in TYPE_BLOCK");
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ Type *ResultTy = 0;
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: return Error("unknown type in type table");
+ case naclbitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+ // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+ // type list. This allows us to reserve space.
+ if (Record.size() < 1)
+ return Error("Invalid TYPE_CODE_NUMENTRY record");
+ TypeList.resize(Record[0]);
+ continue;
+ case naclbitc::TYPE_CODE_VOID: // VOID
+ ResultTy = Type::getVoidTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_HALF: // HALF
+ ResultTy = Type::getHalfTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_FLOAT: // FLOAT
+ ResultTy = Type::getFloatTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_DOUBLE: // DOUBLE
+ ResultTy = Type::getDoubleTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_X86_FP80: // X86_FP80
+ ResultTy = Type::getX86_FP80Ty(Context);
+ break;
+ case naclbitc::TYPE_CODE_FP128: // FP128
+ ResultTy = Type::getFP128Ty(Context);
+ break;
+ case naclbitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+ ResultTy = Type::getPPC_FP128Ty(Context);
+ break;
+ case naclbitc::TYPE_CODE_LABEL: // LABEL
+ ResultTy = Type::getLabelTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_METADATA: // METADATA
+ ResultTy = Type::getMetadataTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_X86_MMX: // X86_MMX
+ ResultTy = Type::getX86_MMXTy(Context);
+ break;
+ case naclbitc::TYPE_CODE_INTEGER: // INTEGER: [width]
+ if (Record.size() < 1)
+ return Error("Invalid Integer type record");
+
+ ResultTy = IntegerType::get(Context, Record[0]);
+ break;
+ case naclbitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+ // [pointee type, address space]
+ if (Record.size() < 1)
+ return Error("Invalid POINTER type record");
+ unsigned AddressSpace = 0;
+ if (Record.size() == 2)
+ AddressSpace = Record[1];
+ ResultTy = getTypeByID(Record[0]);
+ if (ResultTy == 0) return Error("invalid element type in pointer type");
+ ResultTy = PointerType::get(ResultTy, AddressSpace);
+ break;
+ }
+ case naclbitc::TYPE_CODE_FUNCTION_OLD: {
+ // FIXME: attrid is dead, remove it in LLVM 4.0
+ // FUNCTION: [vararg, attrid, retty, paramty x N]
+ if (Record.size() < 3)
+ return Error("Invalid FUNCTION type record");
+ SmallVector<Type*, 8> ArgTys;
+ for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ ArgTys.push_back(T);
+ else
+ break;
+ }
+
+ ResultTy = getTypeByID(Record[2]);
+ if (ResultTy == 0 || ArgTys.size() < Record.size()-3)
+ return Error("invalid type in function type");
+
+ ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+ break;
+ }
+ case naclbitc::TYPE_CODE_FUNCTION: {
+ // FUNCTION: [vararg, retty, paramty x N]
+ if (Record.size() < 2)
+ return Error("Invalid FUNCTION type record");
+ SmallVector<Type*, 8> ArgTys;
+ for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ ArgTys.push_back(T);
+ else
+ break;
+ }
+
+ ResultTy = getTypeByID(Record[1]);
+ if (ResultTy == 0 || ArgTys.size() < Record.size()-2)
+ return Error("invalid type in function type");
+
+ ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+ break;
+ }
+ case naclbitc::TYPE_CODE_STRUCT_ANON: { // STRUCT: [ispacked, eltty x N]
+ if (Record.size() < 1)
+ return Error("Invalid STRUCT type record");
+ SmallVector<Type*, 8> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ EltTys.push_back(T);
+ else
+ break;
+ }
+ if (EltTys.size() != Record.size()-1)
+ return Error("invalid type in struct type");
+ ResultTy = StructType::get(Context, EltTys, Record[0]);
+ break;
+ }
+ case naclbitc::TYPE_CODE_STRUCT_NAME: // STRUCT_NAME: [strchr x N]
+ if (ConvertToString(Record, 0, TypeName))
+ return Error("Invalid STRUCT_NAME record");
+ continue;
+
+ case naclbitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
+ if (Record.size() < 1)
+ return Error("Invalid STRUCT type record");
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ // Check to see if this was forward referenced, if so fill in the temp.
+ StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+ if (Res) {
+ Res->setName(TypeName);
+ TypeList[NumRecords] = 0;
+ } else // Otherwise, create a new struct.
+ Res = StructType::create(Context, TypeName);
+ TypeName.clear();
+
+ SmallVector<Type*, 8> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ EltTys.push_back(T);
+ else
+ break;
+ }
+ if (EltTys.size() != Record.size()-1)
+ return Error("invalid STRUCT type record");
+ Res->setBody(EltTys, Record[0]);
+ ResultTy = Res;
+ break;
+ }
+ case naclbitc::TYPE_CODE_OPAQUE: { // OPAQUE: []
+ if (Record.size() != 1)
+ return Error("Invalid OPAQUE type record");
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ // Check to see if this was forward referenced, if so fill in the temp.
+ StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+ if (Res) {
+ Res->setName(TypeName);
+ TypeList[NumRecords] = 0;
+ } else // Otherwise, create a new struct with no body.
+ Res = StructType::create(Context, TypeName);
+ TypeName.clear();
+ ResultTy = Res;
+ break;
+ }
+ case naclbitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
+ if (Record.size() < 2)
+ return Error("Invalid ARRAY type record");
+ if ((ResultTy = getTypeByID(Record[1])))
+ ResultTy = ArrayType::get(ResultTy, Record[0]);
+ else
+ return Error("Invalid ARRAY type element");
+ break;
+ case naclbitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
+ if (Record.size() < 2)
+ return Error("Invalid VECTOR type record");
+ if ((ResultTy = getTypeByID(Record[1])))
+ ResultTy = VectorType::get(ResultTy, Record[0]);
+ else
+ return Error("Invalid ARRAY type element");
+ break;
+ }
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+ assert(ResultTy && "Didn't read a type?");
+ assert(TypeList[NumRecords] == 0 && "Already read type?");
+ TypeList[NumRecords++] = ResultTy;
+ }
+}
+
+bool NaClBitcodeReader::ParseValueSymbolTable() {
+ if (Stream.EnterSubBlock(naclbitc::VALUE_SYMTAB_BLOCK_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records for this value table.
+ SmallString<128> ValueName;
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("malformed value symbol table block");
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: // Default behavior: unknown type.
+ break;
+ case naclbitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N]
+ if (ConvertToString(Record, 1, ValueName))
+ return Error("Invalid VST_ENTRY record");
+ unsigned ValueID = Record[0];
+ if (ValueID >= ValueList.size())
+ return Error("Invalid Value ID in VST_ENTRY record");
+ Value *V = ValueList[ValueID];
+
+ V->setName(StringRef(ValueName.data(), ValueName.size()));
+ ValueName.clear();
+ break;
+ }
+ case naclbitc::VST_CODE_BBENTRY: {
+ if (ConvertToString(Record, 1, ValueName))
+ return Error("Invalid VST_BBENTRY record");
+ BasicBlock *BB = getBasicBlock(Record[0]);
+ if (BB == 0)
+ return Error("Invalid BB ID in VST_BBENTRY record");
+
+ BB->setName(StringRef(ValueName.data(), ValueName.size()));
+ ValueName.clear();
+ break;
+ }
+ }
+ }
+}
+
+bool NaClBitcodeReader::ParseMetadata() {
+ unsigned NextMDValueNo = MDValueList.size();
+
+ if (Stream.EnterSubBlock(naclbitc::METADATA_BLOCK_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ Error("malformed metadata block");
+ return true;
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ bool IsFunctionLocal = false;
+ // Read a record.
+ Record.clear();
+ unsigned Code = Stream.readRecord(Entry.ID, Record);
+ switch (Code) {
+ default: // Default behavior: ignore.
+ break;
+ case naclbitc::METADATA_NAME: {
+ // Read name of the named metadata.
+ SmallString<8> Name(Record.begin(), Record.end());
+ Record.clear();
+ Code = Stream.ReadCode();
+
+ // METADATA_NAME is always followed by METADATA_NAMED_NODE.
+ unsigned NextBitCode = Stream.readRecord(Code, Record);
+ assert(NextBitCode == naclbitc::METADATA_NAMED_NODE); (void)NextBitCode;
+
+ // Read named metadata elements.
+ unsigned Size = Record.size();
+ NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata(Name);
+ for (unsigned i = 0; i != Size; ++i) {
+ MDNode *MD = dyn_cast<MDNode>(MDValueList.getValueFwdRef(Record[i]));
+ if (MD == 0)
+ return Error("Malformed metadata record");
+ NMD->addOperand(MD);
+ }
+ break;
+ }
+ case naclbitc::METADATA_FN_NODE:
+ IsFunctionLocal = true;
+ // fall-through
+ case naclbitc::METADATA_NODE: {
+ if (Record.size() % 2 == 1)
+ return Error("Invalid METADATA_NODE record");
+
+ unsigned Size = Record.size();
+ SmallVector<Value*, 8> Elts;
+ for (unsigned i = 0; i != Size; i += 2) {
+ Type *Ty = getTypeByID(Record[i]);
+ if (!Ty) return Error("Invalid METADATA_NODE record");
+ if (Ty->isMetadataTy())
+ Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
+ else if (!Ty->isVoidTy())
+ Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty));
+ else
+ Elts.push_back(NULL);
+ }
+ Value *V = MDNode::getWhenValsUnresolved(Context, Elts, IsFunctionLocal);
+ IsFunctionLocal = false;
+ MDValueList.AssignValue(V, NextMDValueNo++);
+ break;
+ }
+ case naclbitc::METADATA_STRING: {
+ SmallString<8> String(Record.begin(), Record.end());
+ Value *V = MDString::get(Context, String);
+ MDValueList.AssignValue(V, NextMDValueNo++);
+ break;
+ }
+ case naclbitc::METADATA_KIND: {
+ if (Record.size() < 2)
+ return Error("Invalid METADATA_KIND record");
+
+ unsigned Kind = Record[0];
+ SmallString<8> Name(Record.begin()+1, Record.end());
+
+ unsigned NewKind = TheModule->getMDKindID(Name.str());
+ if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
+ return Error("Conflicting METADATA_KIND records");
+ break;
+ }
+ }
+ }
+}
+
+/// decodeSignRotatedValue - Decode a signed value stored with the sign bit in
+/// the LSB for dense VBR encoding.
+uint64_t NaClBitcodeReader::decodeSignRotatedValue(uint64_t V) {
+ if ((V & 1) == 0)
+ return V >> 1;
+ if (V != 1)
+ return -(V >> 1);
+ // There is no such thing as -0 with integers. "-0" really means MININT.
+ return 1ULL << 63;
+}
+
+/// ResolveGlobalAndAliasInits - Resolve all of the initializers for global
+/// values and aliases that we can.
+bool NaClBitcodeReader::ResolveGlobalAndAliasInits() {
+ std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
+ std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
+
+ GlobalInitWorklist.swap(GlobalInits);
+ AliasInitWorklist.swap(AliasInits);
+
+ while (!GlobalInitWorklist.empty()) {
+ unsigned ValID = GlobalInitWorklist.back().second;
+ if (ValID >= ValueList.size()) {
+ // Not ready to resolve this yet, it requires something later in the file.
+ GlobalInits.push_back(GlobalInitWorklist.back());
+ } else {
+ if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
+ GlobalInitWorklist.back().first->setInitializer(C);
+ else
+ return Error("Global variable initializer is not a constant!");
+ }
+ GlobalInitWorklist.pop_back();
+ }
+
+ while (!AliasInitWorklist.empty()) {
+ unsigned ValID = AliasInitWorklist.back().second;
+ if (ValID >= ValueList.size()) {
+ AliasInits.push_back(AliasInitWorklist.back());
+ } else {
+ if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
+ AliasInitWorklist.back().first->setAliasee(C);
+ else
+ return Error("Alias initializer is not a constant!");
+ }
+ AliasInitWorklist.pop_back();
+ }
+ return false;
+}
+
+static APInt ReadWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
+ SmallVector<uint64_t, 8> Words(Vals.size());
+ std::transform(Vals.begin(), Vals.end(), Words.begin(),
+ NaClBitcodeReader::decodeSignRotatedValue);
+
+ return APInt(TypeBits, Words);
+}
+
+bool NaClBitcodeReader::ParseConstants() {
+ if (Stream.EnterSubBlock(naclbitc::CONSTANTS_BLOCK_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records for this value table.
+ Type *CurTy = Type::getInt32Ty(Context);
+ unsigned NextCstNo = ValueList.size();
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("malformed block record in AST file");
+ case NaClBitstreamEntry::EndBlock:
+ if (NextCstNo != ValueList.size())
+ return Error("Invalid constant reference!");
+
+ // Once all the constants have been read, go through and resolve forward
+ // references.
+ ValueList.ResolveConstantForwardRefs();
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ Value *V = 0;
+ unsigned BitCode = Stream.readRecord(Entry.ID, Record);
+ switch (BitCode) {
+ default: // Default behavior: unknown constant
+ case naclbitc::CST_CODE_UNDEF: // UNDEF
+ V = UndefValue::get(CurTy);
+ break;
+ case naclbitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
+ if (Record.empty())
+ return Error("Malformed CST_SETTYPE record");
+ if (Record[0] >= TypeList.size())
+ return Error("Invalid Type ID in CST_SETTYPE record");
+ CurTy = TypeList[Record[0]];
+ continue; // Skip the ValueList manipulation.
+ case naclbitc::CST_CODE_NULL: // NULL
+ V = Constant::getNullValue(CurTy);
+ break;
+ case naclbitc::CST_CODE_INTEGER: // INTEGER: [intval]
+ if (!CurTy->isIntegerTy() || Record.empty())
+ return Error("Invalid CST_INTEGER record");
+ V = ConstantInt::get(CurTy, decodeSignRotatedValue(Record[0]));
+ break;
+ case naclbitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
+ if (!CurTy->isIntegerTy() || Record.empty())
+ return Error("Invalid WIDE_INTEGER record");
+
+ APInt VInt = ReadWideAPInt(Record,
+ cast<IntegerType>(CurTy)->getBitWidth());
+ V = ConstantInt::get(Context, VInt);
+
+ break;
+ }
+ case naclbitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
+ if (Record.empty())
+ return Error("Invalid FLOAT record");
+ if (CurTy->isHalfTy())
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEhalf,
+ APInt(16, (uint16_t)Record[0])));
+ else if (CurTy->isFloatTy())
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle,
+ APInt(32, (uint32_t)Record[0])));
+ else if (CurTy->isDoubleTy())
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble,
+ APInt(64, Record[0])));
+ else if (CurTy->isX86_FP80Ty()) {
+ // Bits are not stored the same way as a normal i80 APInt, compensate.
+ uint64_t Rearrange[2];
+ Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
+ Rearrange[1] = Record[0] >> 48;
+ V = ConstantFP::get(Context, APFloat(APFloat::x87DoubleExtended,
+ APInt(80, Rearrange)));
+ } else if (CurTy->isFP128Ty())
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEquad,
+ APInt(128, Record)));
+ else if (CurTy->isPPC_FP128Ty())
+ V = ConstantFP::get(Context, APFloat(APFloat::PPCDoubleDouble,
+ APInt(128, Record)));
+ else
+ V = UndefValue::get(CurTy);
+ break;
+ }
+
+ case naclbitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number]
+ if (Record.empty())
+ return Error("Invalid CST_AGGREGATE record");
+
+ unsigned Size = Record.size();
+ SmallVector<Constant*, 16> Elts;
+
+ if (StructType *STy = dyn_cast<StructType>(CurTy)) {
+ for (unsigned i = 0; i != Size; ++i)
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i],
+ STy->getElementType(i)));
+ V = ConstantStruct::get(STy, Elts);
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
+ Type *EltTy = ATy->getElementType();
+ for (unsigned i = 0; i != Size; ++i)
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+ V = ConstantArray::get(ATy, Elts);
+ } else if (VectorType *VTy = dyn_cast<VectorType>(CurTy)) {
+ Type *EltTy = VTy->getElementType();
+ for (unsigned i = 0; i != Size; ++i)
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+ V = ConstantVector::get(Elts);
+ } else {
+ V = UndefValue::get(CurTy);
+ }
+ break;
+ }
+ case naclbitc::CST_CODE_STRING: // STRING: [values]
+ case naclbitc::CST_CODE_CSTRING: { // CSTRING: [values]
+ if (Record.empty())
+ return Error("Invalid CST_STRING record");
+
+ SmallString<16> Elts(Record.begin(), Record.end());
+ V = ConstantDataArray::getString(Context, Elts,
+ BitCode == naclbitc::CST_CODE_CSTRING);
+ break;
+ }
+ case naclbitc::CST_CODE_DATA: {// DATA: [n x value]
+ if (Record.empty())
+ return Error("Invalid CST_DATA record");
+
+ Type *EltTy = cast<SequentialType>(CurTy)->getElementType();
+ unsigned Size = Record.size();
+
+ if (EltTy->isIntegerTy(8)) {
+ SmallVector<uint8_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::get(Context, Elts);
+ else
+ V = ConstantDataArray::get(Context, Elts);
+ } else if (EltTy->isIntegerTy(16)) {
+ SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::get(Context, Elts);
+ else
+ V = ConstantDataArray::get(Context, Elts);
+ } else if (EltTy->isIntegerTy(32)) {
+ SmallVector<uint32_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::get(Context, Elts);
+ else
+ V = ConstantDataArray::get(Context, Elts);
+ } else if (EltTy->isIntegerTy(64)) {
+ SmallVector<uint64_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::get(Context, Elts);
+ else
+ V = ConstantDataArray::get(Context, Elts);
+ } else if (EltTy->isFloatTy()) {
+ SmallVector<float, 16> Elts(Size);
+ std::transform(Record.begin(), Record.end(), Elts.begin(), BitsToFloat);
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::get(Context, Elts);
+ else
+ V = ConstantDataArray::get(Context, Elts);
+ } else if (EltTy->isDoubleTy()) {
+ SmallVector<double, 16> Elts(Size);
+ std::transform(Record.begin(), Record.end(), Elts.begin(),
+ BitsToDouble);
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::get(Context, Elts);
+ else
+ V = ConstantDataArray::get(Context, Elts);
+ } else {
+ return Error("Unknown element type in CE_DATA");
+ }
+ break;
+ }
+
+ case naclbitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval]
+ if (Record.size() < 3) return Error("Invalid CE_BINOP record");
+ int Opc = GetDecodedBinaryOpcode(Record[0], CurTy);
+ if (Opc < 0) {
+ V = UndefValue::get(CurTy); // Unknown binop.
+ } else {
+ Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
+ Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
+ unsigned Flags = 0;
+ if (Record.size() >= 4) {
+ if (Opc == Instruction::Add ||
+ Opc == Instruction::Sub ||
+ Opc == Instruction::Mul ||
+ Opc == Instruction::Shl) {
+ if (Record[3] & (1 << naclbitc::OBO_NO_SIGNED_WRAP))
+ Flags |= OverflowingBinaryOperator::NoSignedWrap;
+ if (Record[3] & (1 << naclbitc::OBO_NO_UNSIGNED_WRAP))
+ Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
+ } else if (Opc == Instruction::SDiv ||
+ Opc == Instruction::UDiv ||
+ Opc == Instruction::LShr ||
+ Opc == Instruction::AShr) {
+ if (Record[3] & (1 << naclbitc::PEO_EXACT))
+ Flags |= SDivOperator::IsExact;
+ }
+ }
+ V = ConstantExpr::get(Opc, LHS, RHS, Flags);
+ }
+ break;
+ }
+ case naclbitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval]
+ if (Record.size() < 3) return Error("Invalid CE_CAST record");
+ int Opc = GetDecodedCastOpcode(Record[0]);
+ if (Opc < 0) {
+ V = UndefValue::get(CurTy); // Unknown cast.
+ } else {
+ Type *OpTy = getTypeByID(Record[1]);
+ if (!OpTy) return Error("Invalid CE_CAST record");
+ Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy);
+ V = ConstantExpr::getCast(Opc, Op, CurTy);
+ }
+ break;
+ }
+ case naclbitc::CST_CODE_CE_INBOUNDS_GEP:
+ case naclbitc::CST_CODE_CE_GEP: { // CE_GEP: [n x operands]
+ if (Record.size() & 1) return Error("Invalid CE_GEP record");
+ SmallVector<Constant*, 16> Elts;
+ for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+ Type *ElTy = getTypeByID(Record[i]);
+ if (!ElTy) return Error("Invalid CE_GEP record");
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
+ }
+ ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
+ V = ConstantExpr::getGetElementPtr(Elts[0], Indices,
+ BitCode ==
+ naclbitc::CST_CODE_CE_INBOUNDS_GEP);
+ break;
+ }
+ case naclbitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
+ if (Record.size() < 3) return Error("Invalid CE_SELECT record");
+ V = ConstantExpr::getSelect(
+ ValueList.getConstantFwdRef(Record[0],
+ Type::getInt1Ty(Context)),
+ ValueList.getConstantFwdRef(Record[1],CurTy),
+ ValueList.getConstantFwdRef(Record[2],CurTy));
+ break;
+ case naclbitc::CST_CODE_CE_EXTRACTELT: {
+ // CE_EXTRACTELT: [opty, opval, opval]
+ if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record");
+ VectorType *OpTy =
+ dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+ if (OpTy == 0) return Error("Invalid CE_EXTRACTELT record");
+ Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+ Constant *Op1 = ValueList.getConstantFwdRef(Record[2],
+ Type::getInt32Ty(Context));
+ V = ConstantExpr::getExtractElement(Op0, Op1);
+ break;
+ }
+ case naclbitc::CST_CODE_CE_INSERTELT: {// CE_INSERTELT: [opval, opval, opval]
+ VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+ if (Record.size() < 3 || OpTy == 0)
+ return Error("Invalid CE_INSERTELT record");
+ Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+ Constant *Op1 = ValueList.getConstantFwdRef(Record[1],
+ OpTy->getElementType());
+ Constant *Op2 = ValueList.getConstantFwdRef(Record[2],
+ Type::getInt32Ty(Context));
+ V = ConstantExpr::getInsertElement(Op0, Op1, Op2);
+ break;
+ }
+ case naclbitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval]
+ VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+ if (Record.size() < 3 || OpTy == 0)
+ return Error("Invalid CE_SHUFFLEVEC record");
+ Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+ Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy);
+ Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+ OpTy->getNumElements());
+ Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy);
+ V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+ break;
+ }
+ case naclbitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval]
+ VectorType *RTy = dyn_cast<VectorType>(CurTy);
+ VectorType *OpTy =
+ dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+ if (Record.size() < 4 || RTy == 0 || OpTy == 0)
+ return Error("Invalid CE_SHUFVEC_EX record");
+ Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+ Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+ Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+ RTy->getNumElements());
+ Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy);
+ V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+ break;
+ }
+ case naclbitc::CST_CODE_CE_CMP: { // CE_CMP: [opty, opval, opval, pred]
+ if (Record.size() < 4) return Error("Invalid CE_CMP record");
+ Type *OpTy = getTypeByID(Record[0]);
+ if (OpTy == 0) return Error("Invalid CE_CMP record");
+ Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+ Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+
+ if (OpTy->isFPOrFPVectorTy())
+ V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
+ else
+ V = ConstantExpr::getICmp(Record[3], Op0, Op1);
+ break;
+ }
+ // This maintains backward compatibility, pre-asm dialect keywords.
+ // FIXME: Remove with the 4.0 release.
+ case naclbitc::CST_CODE_INLINEASM_OLD: {
+ if (Record.size() < 2) return Error("Invalid INLINEASM record");
+ std::string AsmStr, ConstrStr;
+ bool HasSideEffects = Record[0] & 1;
+ bool IsAlignStack = Record[0] >> 1;
+ unsigned AsmStrSize = Record[1];
+ if (2+AsmStrSize >= Record.size())
+ return Error("Invalid INLINEASM record");
+ unsigned ConstStrSize = Record[2+AsmStrSize];
+ if (3+AsmStrSize+ConstStrSize > Record.size())
+ return Error("Invalid INLINEASM record");
+
+ for (unsigned i = 0; i != AsmStrSize; ++i)
+ AsmStr += (char)Record[2+i];
+ for (unsigned i = 0; i != ConstStrSize; ++i)
+ ConstrStr += (char)Record[3+AsmStrSize+i];
+ PointerType *PTy = cast<PointerType>(CurTy);
+ V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
+ AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
+ break;
+ }
+ // This version adds support for the asm dialect keywords (e.g.,
+ // inteldialect).
+ case naclbitc::CST_CODE_INLINEASM: {
+ if (Record.size() < 2) return Error("Invalid INLINEASM record");
+ std::string AsmStr, ConstrStr;
+ bool HasSideEffects = Record[0] & 1;
+ bool IsAlignStack = (Record[0] >> 1) & 1;
+ unsigned AsmDialect = Record[0] >> 2;
+ unsigned AsmStrSize = Record[1];
+ if (2+AsmStrSize >= Record.size())
+ return Error("Invalid INLINEASM record");
+ unsigned ConstStrSize = Record[2+AsmStrSize];
+ if (3+AsmStrSize+ConstStrSize > Record.size())
+ return Error("Invalid INLINEASM record");
+
+ for (unsigned i = 0; i != AsmStrSize; ++i)
+ AsmStr += (char)Record[2+i];
+ for (unsigned i = 0; i != ConstStrSize; ++i)
+ ConstrStr += (char)Record[3+AsmStrSize+i];
+ PointerType *PTy = cast<PointerType>(CurTy);
+ V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
+ AsmStr, ConstrStr, HasSideEffects, IsAlignStack,
+ InlineAsm::AsmDialect(AsmDialect));
+ break;
+ }
+ case naclbitc::CST_CODE_BLOCKADDRESS:{
+ if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record");
+ Type *FnTy = getTypeByID(Record[0]);
+ if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record");
+ Function *Fn =
+ dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy));
+ if (Fn == 0) return Error("Invalid CE_BLOCKADDRESS record");
+
+ // If the function is already parsed we can insert the block address right
+ // away.
+ if (!Fn->empty()) {
+ Function::iterator BBI = Fn->begin(), BBE = Fn->end();
+ for (size_t I = 0, E = Record[2]; I != E; ++I) {
+ if (BBI == BBE)
+ return Error("Invalid blockaddress block #");
+ ++BBI;
+ }
+ V = BlockAddress::get(Fn, BBI);
+ } else {
+ // Otherwise insert a placeholder and remember it so it can be inserted
+ // when the function is parsed.
+ GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(),
+ Type::getInt8Ty(Context),
+ false, GlobalValue::InternalLinkage,
+ 0, "");
+ BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef));
+ V = FwdRef;
+ }
+ break;
+ }
+ }
+
+ ValueList.AssignValue(V, NextCstNo);
+ ++NextCstNo;
+ }
+}
+
+bool NaClBitcodeReader::ParseUseLists() {
+ if (Stream.EnterSubBlock(naclbitc::USELIST_BLOCK_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("malformed use list block");
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a use list record.
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: // Default behavior: unknown type.
+ break;
+ case naclbitc::USELIST_CODE_ENTRY: { // USELIST_CODE_ENTRY: TBD.
+ unsigned RecordLength = Record.size();
+ if (RecordLength < 1)
+ return Error ("Invalid UseList reader!");
+ UseListRecords.push_back(Record);
+ break;
+ }
+ }
+ }
+}
+
+/// RememberAndSkipFunctionBody - When we see the block for a function body,
+/// remember where it is and then skip it. This lets us lazily deserialize the
+/// functions.
+bool NaClBitcodeReader::RememberAndSkipFunctionBody() {
+ // Get the function we are talking about.
+ if (FunctionsWithBodies.empty())
+ return Error("Insufficient function protos");
+
+ Function *Fn = FunctionsWithBodies.back();
+ FunctionsWithBodies.pop_back();
+
+ // Save the current stream state.
+ uint64_t CurBit = Stream.GetCurrentBitNo();
+ DeferredFunctionInfo[Fn] = CurBit;
+
+ // Skip over the function block for now.
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ return false;
+}
+
+bool NaClBitcodeReader::GlobalCleanup() {
+ // Patch the initializers for globals and aliases up.
+ ResolveGlobalAndAliasInits();
+ if (!GlobalInits.empty() || !AliasInits.empty())
+ return Error("Malformed global initializer set");
+
+ // Look for intrinsic functions which need to be upgraded at some point
+ for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
+ FI != FE; ++FI) {
+ Function *NewFn;
+ if (UpgradeIntrinsicFunction(FI, NewFn))
+ UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn));
+ }
+
+ // Look for global variables which need to be renamed.
+ for (Module::global_iterator
+ GI = TheModule->global_begin(), GE = TheModule->global_end();
+ GI != GE; ++GI)
+ UpgradeGlobalVariable(GI);
+ // Force deallocation of memory for these vectors to favor the client that
+ // want lazy deserialization.
+ std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
+ std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
+ return false;
+}
+
+bool NaClBitcodeReader::ParseModule(bool Resume) {
+ if (Resume)
+ Stream.JumpToBit(NextUnreadBit);
+ else if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+ std::vector<std::string> SectionTable;
+ std::vector<std::string> GCTable;
+
+ // Read all the records for this module.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::Error:
+ Error("malformed module block");
+ return true;
+ case NaClBitstreamEntry::EndBlock:
+ return GlobalCleanup();
+
+ case NaClBitstreamEntry::SubBlock:
+ switch (Entry.ID) {
+ default: // Skip unknown content.
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ break;
+ case bitc::BLOCKINFO_BLOCK_ID:
+ if (Stream.ReadBlockInfoBlock())
+ return Error("Malformed BlockInfoBlock");
+ break;
+ case naclbitc::PARAMATTR_BLOCK_ID:
+ if (ParseAttributeBlock())
+ return true;
+ break;
+ case naclbitc::PARAMATTR_GROUP_BLOCK_ID:
+ if (ParseAttributeGroupBlock())
+ return true;
+ break;
+ case naclbitc::TYPE_BLOCK_ID_NEW:
+ if (ParseTypeTable())
+ return true;
+ break;
+ case naclbitc::VALUE_SYMTAB_BLOCK_ID:
+ if (ParseValueSymbolTable())
+ return true;
+ SeenValueSymbolTable = true;
+ break;
+ case naclbitc::CONSTANTS_BLOCK_ID:
+ if (ParseConstants() || ResolveGlobalAndAliasInits())
+ return true;
+ break;
+ case naclbitc::METADATA_BLOCK_ID:
+ if (ParseMetadata())
+ return true;
+ break;
+ case naclbitc::FUNCTION_BLOCK_ID:
+ // If this is the first function body we've seen, reverse the
+ // FunctionsWithBodies list.
+ if (!SeenFirstFunctionBody) {
+ std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
+ if (GlobalCleanup())
+ return true;
+ SeenFirstFunctionBody = true;
+ }
+
+ if (RememberAndSkipFunctionBody())
+ return true;
+ // For streaming bitcode, suspend parsing when we reach the function
+ // bodies. Subsequent materialization calls will resume it when
+ // necessary. For streaming, the function bodies must be at the end of
+ // the bitcode. If the bitcode file is old, the symbol table will be
+ // at the end instead and will not have been seen yet. In this case,
+ // just finish the parse now.
+ if (LazyStreamer && SeenValueSymbolTable) {
+ NextUnreadBit = Stream.GetCurrentBitNo();
+ return false;
+ }
+ break;
+ case naclbitc::USELIST_BLOCK_ID:
+ if (ParseUseLists())
+ return true;
+ break;
+ }
+ continue;
+
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+
+ // Read a record.
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: break; // Default behavior, ignore unknown content.
+ case naclbitc::MODULE_CODE_VERSION: { // VERSION: [version#]
+ if (Record.size() < 1)
+ return Error("Malformed MODULE_CODE_VERSION");
+ // Only version #0 and #1 are supported so far.
+ unsigned module_version = Record[0];
+ switch (module_version) {
+ default: return Error("Unknown bitstream version!");
+ case 0:
+ UseRelativeIDs = false;
+ break;
+ case 1:
+ UseRelativeIDs = true;
+ break;
+ }
+ break;
+ }
+ case naclbitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_TRIPLE record");
+
+ // @LOCALMOD-BEGIN
+ // This hack is needed in order to get Clang compiled binaries
+ // working with the Gold plugin, until PNaCl backend is introduced
+ // in lib/Target/PNaCl.
+ if (S == "le32-unknown-nacl")
+ S = "armv7-none-linux-gnueabi";
+ // @LOCALMOD-END
+ TheModule->setTargetTriple(S);
+ break;
+ }
+ case naclbitc::MODULE_CODE_DATALAYOUT: { // DATALAYOUT: [strchr x N]
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_DATALAYOUT record");
+ TheModule->setDataLayout(S);
+ break;
+ }
+ case naclbitc::MODULE_CODE_ASM: { // ASM: [strchr x N]
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_ASM record");
+ TheModule->setModuleInlineAsm(S);
+ break;
+ }
+ case naclbitc::MODULE_CODE_DEPLIB: { // DEPLIB: [strchr x N]
+ // FIXME: Remove in 4.0.
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_DEPLIB record");
+ // Ignore value.
+ break;
+ }
+ case naclbitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N]
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_SECTIONNAME record");
+ SectionTable.push_back(S);
+ break;
+ }
+ case naclbitc::MODULE_CODE_GCNAME: { // SECTIONNAME: [strchr x N]
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_GCNAME record");
+ GCTable.push_back(S);
+ break;
+ }
+ // GLOBALVAR: [pointer type, isconst, initid,
+ // linkage, alignment, section, visibility, threadlocal,
+ // unnamed_addr]
+ case naclbitc::MODULE_CODE_GLOBALVAR: {
+ if (Record.size() < 6)
+ return Error("Invalid MODULE_CODE_GLOBALVAR record");
+ Type *Ty = getTypeByID(Record[0]);
+ if (!Ty) return Error("Invalid MODULE_CODE_GLOBALVAR record");
+ if (!Ty->isPointerTy())
+ return Error("Global not a pointer type!");
+ unsigned AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
+ Ty = cast<PointerType>(Ty)->getElementType();
+
+ bool isConstant = Record[1];
+ GlobalValue::LinkageTypes Linkage = GetDecodedLinkage(Record[3]);
+ unsigned Alignment = (1 << Record[4]) >> 1;
+ std::string Section;
+ if (Record[5]) {
+ if (Record[5]-1 >= SectionTable.size())
+ return Error("Invalid section ID");
+ Section = SectionTable[Record[5]-1];
+ }
+ GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
+ if (Record.size() > 6)
+ Visibility = GetDecodedVisibility(Record[6]);
+
+ GlobalVariable::ThreadLocalMode TLM = GlobalVariable::NotThreadLocal;
+ if (Record.size() > 7)
+ TLM = GetDecodedThreadLocalMode(Record[7]);
+
+ bool UnnamedAddr = false;
+ if (Record.size() > 8)
+ UnnamedAddr = Record[8];
+
+ bool ExternallyInitialized = false;
+ if (Record.size() > 9)
+ ExternallyInitialized = Record[9];
+
+ GlobalVariable *NewGV =
+ new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0,
+ TLM, AddressSpace, ExternallyInitialized);
+ NewGV->setAlignment(Alignment);
+ if (!Section.empty())
+ NewGV->setSection(Section);
+ NewGV->setVisibility(Visibility);
+ NewGV->setUnnamedAddr(UnnamedAddr);
+
+ ValueList.push_back(NewGV);
+
+ // Remember which value to use for the global initializer.
+ if (unsigned InitID = Record[2])
+ GlobalInits.push_back(std::make_pair(NewGV, InitID-1));
+ break;
+ }
+ // FUNCTION: [type, callingconv, isproto, linkage, paramattr,
+ // alignment, section, visibility, gc, unnamed_addr]
+ case naclbitc::MODULE_CODE_FUNCTION: {
+ if (Record.size() < 8)
+ return Error("Invalid MODULE_CODE_FUNCTION record");
+ Type *Ty = getTypeByID(Record[0]);
+ if (!Ty) return Error("Invalid MODULE_CODE_FUNCTION record");
+ if (!Ty->isPointerTy())
+ return Error("Function not a pointer type!");
+ FunctionType *FTy =
+ dyn_cast<FunctionType>(cast<PointerType>(Ty)->getElementType());
+ if (!FTy)
+ return Error("Function not a pointer to function type!");
+
+ Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
+ "", TheModule);
+
+ Func->setCallingConv(static_cast<CallingConv::ID>(Record[1]));
+ bool isProto = Record[2];
+ Func->setLinkage(GetDecodedLinkage(Record[3]));
+ Func->setAttributes(getAttributes(Record[4]));
+
+ Func->setAlignment((1 << Record[5]) >> 1);
+ if (Record[6]) {
+ if (Record[6]-1 >= SectionTable.size())
+ return Error("Invalid section ID");
+ Func->setSection(SectionTable[Record[6]-1]);
+ }
+ Func->setVisibility(GetDecodedVisibility(Record[7]));
+ if (Record.size() > 8 && Record[8]) {
+ if (Record[8]-1 > GCTable.size())
+ return Error("Invalid GC ID");
+ Func->setGC(GCTable[Record[8]-1].c_str());
+ }
+ bool UnnamedAddr = false;
+ if (Record.size() > 9)
+ UnnamedAddr = Record[9];
+ Func->setUnnamedAddr(UnnamedAddr);
+ ValueList.push_back(Func);
+
+ // If this is a function with a body, remember the prototype we are
+ // creating now, so that we can match up the body with them later.
+ if (!isProto) {
+ FunctionsWithBodies.push_back(Func);
+ if (LazyStreamer) DeferredFunctionInfo[Func] = 0;
+ }
+ break;
+ }
+ // ALIAS: [alias type, aliasee val#, linkage]
+ // ALIAS: [alias type, aliasee val#, linkage, visibility]
+ case naclbitc::MODULE_CODE_ALIAS: {
+ if (Record.size() < 3)
+ return Error("Invalid MODULE_ALIAS record");
+ Type *Ty = getTypeByID(Record[0]);
+ if (!Ty) return Error("Invalid MODULE_ALIAS record");
+ if (!Ty->isPointerTy())
+ return Error("Function not a pointer type!");
+
+ GlobalAlias *NewGA = new GlobalAlias(Ty, GetDecodedLinkage(Record[2]),
+ "", 0, TheModule);
+ // Old bitcode files didn't have visibility field.
+ if (Record.size() > 3)
+ NewGA->setVisibility(GetDecodedVisibility(Record[3]));
+ ValueList.push_back(NewGA);
+ AliasInits.push_back(std::make_pair(NewGA, Record[1]));
+ break;
+ }
+ /// MODULE_CODE_PURGEVALS: [numvals]
+ case naclbitc::MODULE_CODE_PURGEVALS:
+ // Trim down the value list to the specified size.
+ if (Record.size() < 1 || Record[0] > ValueList.size())
+ return Error("Invalid MODULE_PURGEVALS record");
+ ValueList.shrinkTo(Record[0]);
+ break;
+ }
+ Record.clear();
+ }
+}
+
+bool NaClBitcodeReader::ParseBitcodeInto(Module *M) {
+ TheModule = 0;
+
+ if (InitStream()) return true;
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'B' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(4) != 0x0 ||
+ Stream.Read(4) != 0xC ||
+ Stream.Read(4) != 0xE ||
+ Stream.Read(4) != 0xD)
+ return Error("Invalid bitcode signature");
+
+ // We expect a number of well-defined blocks, though we don't necessarily
+ // need to understand them all.
+ while (1) {
+ if (Stream.AtEndOfStream())
+ return false;
+
+ NaClBitstreamEntry Entry =
+ Stream.advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs);
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::Error:
+ Error("malformed module file");
+ return true;
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+
+ case NaClBitstreamEntry::SubBlock:
+ switch (Entry.ID) {
+ case bitc::BLOCKINFO_BLOCK_ID:
+ if (Stream.ReadBlockInfoBlock())
+ return Error("Malformed BlockInfoBlock");
+ break;
+ case naclbitc::MODULE_BLOCK_ID:
+ // Reject multiple MODULE_BLOCK's in a single bitstream.
+ if (TheModule)
+ return Error("Multiple MODULE_BLOCKs in same stream");
+ TheModule = M;
+ if (ParseModule(false))
+ return true;
+ if (LazyStreamer) return false;
+ break;
+ default:
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ break;
+ }
+ continue;
+ case NaClBitstreamEntry::Record:
+ // There should be no records in the top-level of blocks.
+
+ // The ranlib in Xcode 4 will align archive members by appending newlines
+ // to the end of them. If this file size is a multiple of 4 but not 8, we
+ // have to read and ignore these final 4 bytes :-(
+ if (Stream.getAbbrevIDWidth() == 2 && Entry.ID == 2 &&
+ Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a &&
+ Stream.AtEndOfStream())
+ return false;
+
+ return Error("Invalid record at top-level");
+ }
+ }
+}
+
+bool NaClBitcodeReader::ParseModuleTriple(std::string &Triple) {
+ if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records for this module.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("malformed module block");
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: break; // Default behavior, ignore unknown content.
+ case naclbitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
+ std::string S;
+ if (ConvertToString(Record, 0, S))
+ return Error("Invalid MODULE_CODE_TRIPLE record");
+ Triple = S;
+ break;
+ }
+ }
+ Record.clear();
+ }
+}
+
+bool NaClBitcodeReader::ParseTriple(std::string &Triple) {
+ if (InitStream()) return true;
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'B' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(4) != 0x0 ||
+ Stream.Read(4) != 0xC ||
+ Stream.Read(4) != 0xE ||
+ Stream.Read(4) != 0xD)
+ return Error("Invalid bitcode signature");
+
+ // We expect a number of well-defined blocks, though we don't necessarily
+ // need to understand them all.
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::Error:
+ Error("malformed module file");
+ return true;
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+
+ case NaClBitstreamEntry::SubBlock:
+ if (Entry.ID == naclbitc::MODULE_BLOCK_ID)
+ return ParseModuleTriple(Triple);
+
+ // Ignore other sub-blocks.
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+ continue;
+
+ case NaClBitstreamEntry::Record:
+ Stream.skipRecord(Entry.ID);
+ continue;
+ }
+ }
+}
+
+/// ParseMetadataAttachment - Parse metadata attachments.
+bool NaClBitcodeReader::ParseMetadataAttachment() {
+ if (Stream.EnterSubBlock(naclbitc::METADATA_ATTACHMENT_ID))
+ return Error("Malformed block record");
+
+ SmallVector<uint64_t, 64> Record;
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case NaClBitstreamEntry::Error:
+ return Error("malformed metadata block");
+ case NaClBitstreamEntry::EndBlock:
+ return false;
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a metadata attachment record.
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ default: // Default behavior: ignore.
+ break;
+ case naclbitc::METADATA_ATTACHMENT: {
+ unsigned RecordLength = Record.size();
+ if (Record.empty() || (RecordLength - 1) % 2 == 1)
+ return Error ("Invalid METADATA_ATTACHMENT reader!");
+ Instruction *Inst = InstructionList[Record[0]];
+ for (unsigned i = 1; i != RecordLength; i = i+2) {
+ unsigned Kind = Record[i];
+ DenseMap<unsigned, unsigned>::iterator I =
+ MDKindMap.find(Kind);
+ if (I == MDKindMap.end())
+ return Error("Invalid metadata kind ID");
+ Value *Node = MDValueList.getValueFwdRef(Record[i+1]);
+ Inst->setMetadata(I->second, cast<MDNode>(Node));
+ }
+ break;
+ }
+ }
+ }
+}
+
+/// ParseFunctionBody - Lazily parse the specified function body block.
+bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
+ if (Stream.EnterSubBlock(naclbitc::FUNCTION_BLOCK_ID))
+ return Error("Malformed block record");
+
+ InstructionList.clear();
+ unsigned ModuleValueListSize = ValueList.size();
+ unsigned ModuleMDValueListSize = MDValueList.size();
+
+ // Add all the function arguments to the value table.
+ for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
+ ValueList.push_back(I);
+
+ unsigned NextValueNo = ValueList.size();
+ BasicBlock *CurBB = 0;
+ unsigned CurBBNo = 0;
+
+ DebugLoc LastLoc;
+
+ // Read all the records.
+ SmallVector<uint64_t, 64> Record;
+ while (1) {
+ NaClBitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ case NaClBitstreamEntry::Error:
+ return Error("Bitcode error in function block");
+ case NaClBitstreamEntry::EndBlock:
+ goto OutOfRecordLoop;
+
+ case NaClBitstreamEntry::SubBlock:
+ switch (Entry.ID) {
+ default: // Skip unknown content.
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ break;
+ case naclbitc::CONSTANTS_BLOCK_ID:
+ if (ParseConstants()) return true;
+ NextValueNo = ValueList.size();
+ break;
+ case naclbitc::VALUE_SYMTAB_BLOCK_ID:
+ if (ParseValueSymbolTable()) return true;
+ break;
+ case naclbitc::METADATA_ATTACHMENT_ID:
+ if (ParseMetadataAttachment()) return true;
+ break;
+ case naclbitc::METADATA_BLOCK_ID:
+ if (ParseMetadata()) return true;
+ break;
+ }
+ continue;
+
+ case NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ Instruction *I = 0;
+ unsigned BitCode = Stream.readRecord(Entry.ID, Record);
+ switch (BitCode) {
+ default: // Default behavior: reject
+ return Error("Unknown instruction");
+ case naclbitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks]
+ if (Record.size() < 1 || Record[0] == 0)
+ return Error("Invalid DECLAREBLOCKS record");
+ // Create all the basic blocks for the function.
+ FunctionBBs.resize(Record[0]);
+ for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
+ FunctionBBs[i] = BasicBlock::Create(Context, "", F);
+ CurBB = FunctionBBs[0];
+ continue;
+
+ case naclbitc::FUNC_CODE_DEBUG_LOC_AGAIN: // DEBUG_LOC_AGAIN
+ // This record indicates that the last instruction is at the same
+ // location as the previous instruction with a location.
+ I = 0;
+
+ // Get the last instruction emitted.
+ if (CurBB && !CurBB->empty())
+ I = &CurBB->back();
+ else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+ !FunctionBBs[CurBBNo-1]->empty())
+ I = &FunctionBBs[CurBBNo-1]->back();
+
+ if (I == 0) return Error("Invalid DEBUG_LOC_AGAIN record");
+ I->setDebugLoc(LastLoc);
+ I = 0;
+ continue;
+
+ case naclbitc::FUNC_CODE_DEBUG_LOC: { // DEBUG_LOC: [line, col, scope, ia]
+ I = 0; // Get the last instruction emitted.
+ if (CurBB && !CurBB->empty())
+ I = &CurBB->back();
+ else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+ !FunctionBBs[CurBBNo-1]->empty())
+ I = &FunctionBBs[CurBBNo-1]->back();
+ if (I == 0 || Record.size() < 4)
+ return Error("Invalid FUNC_CODE_DEBUG_LOC record");
+
+ unsigned Line = Record[0], Col = Record[1];
+ unsigned ScopeID = Record[2], IAID = Record[3];
+
+ MDNode *Scope = 0, *IA = 0;
+ if (ScopeID) Scope = cast<MDNode>(MDValueList.getValueFwdRef(ScopeID-1));
+ if (IAID) IA = cast<MDNode>(MDValueList.getValueFwdRef(IAID-1));
+ LastLoc = DebugLoc::get(Line, Col, Scope, IA);
+ I->setDebugLoc(LastLoc);
+ I = 0;
+ continue;
+ }
+
+ case naclbitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode]
+ unsigned OpNum = 0;
+ Value *LHS, *RHS;
+ if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+ popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS) ||
+ OpNum+1 > Record.size())
+ return Error("Invalid BINOP record");
+
+ int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
+ if (Opc == -1) return Error("Invalid BINOP record");
+ I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
+ InstructionList.push_back(I);
+ if (OpNum < Record.size()) {
+ if (Opc == Instruction::Add ||
+ Opc == Instruction::Sub ||
+ Opc == Instruction::Mul ||
+ Opc == Instruction::Shl) {
+ if (Record[OpNum] & (1 << naclbitc::OBO_NO_SIGNED_WRAP))
+ cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
+ if (Record[OpNum] & (1 << naclbitc::OBO_NO_UNSIGNED_WRAP))
+ cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
+ } else if (Opc == Instruction::SDiv ||
+ Opc == Instruction::UDiv ||
+ Opc == Instruction::LShr ||
+ Opc == Instruction::AShr) {
+ if (Record[OpNum] & (1 << naclbitc::PEO_EXACT))
+ cast<BinaryOperator>(I)->setIsExact(true);
+ } else if (isa<FPMathOperator>(I)) {
+ FastMathFlags FMF;
+ if (0 != (Record[OpNum] & FastMathFlags::UnsafeAlgebra))
+ FMF.setUnsafeAlgebra();
+ if (0 != (Record[OpNum] & FastMathFlags::NoNaNs))
+ FMF.setNoNaNs();
+ if (0 != (Record[OpNum] & FastMathFlags::NoInfs))
+ FMF.setNoInfs();
+ if (0 != (Record[OpNum] & FastMathFlags::NoSignedZeros))
+ FMF.setNoSignedZeros();
+ if (0 != (Record[OpNum] & FastMathFlags::AllowReciprocal))
+ FMF.setAllowReciprocal();
+ if (FMF.any())
+ I->setFastMathFlags(FMF);
+ }
+
+ }
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc]
+ unsigned OpNum = 0;
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+ OpNum+2 != Record.size())
+ return Error("Invalid CAST record");
+
+ Type *ResTy = getTypeByID(Record[OpNum]);
+ int Opc = GetDecodedCastOpcode(Record[OpNum+1]);
+ if (Opc == -1 || ResTy == 0)
+ return Error("Invalid CAST record");
+ I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_INBOUNDS_GEP:
+ case naclbitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands]
+ unsigned OpNum = 0;
+ Value *BasePtr;
+ if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr))
+ return Error("Invalid GEP record");
+
+ SmallVector<Value*, 16> GEPIdx;
+ while (OpNum != Record.size()) {
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ return Error("Invalid GEP record");
+ GEPIdx.push_back(Op);
+ }
+
+ I = GetElementPtrInst::Create(BasePtr, GEPIdx);
+ InstructionList.push_back(I);
+ if (BitCode == naclbitc::FUNC_CODE_INST_INBOUNDS_GEP)
+ cast<GetElementPtrInst>(I)->setIsInBounds(true);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_EXTRACTVAL: {
+ // EXTRACTVAL: [opty, opval, n x indices]
+ unsigned OpNum = 0;
+ Value *Agg;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+ return Error("Invalid EXTRACTVAL record");
+
+ SmallVector<unsigned, 4> EXTRACTVALIdx;
+ for (unsigned RecSize = Record.size();
+ OpNum != RecSize; ++OpNum) {
+ uint64_t Index = Record[OpNum];
+ if ((unsigned)Index != Index)
+ return Error("Invalid EXTRACTVAL index");
+ EXTRACTVALIdx.push_back((unsigned)Index);
+ }
+
+ I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_INSERTVAL: {
+ // INSERTVAL: [opty, opval, opty, opval, n x indices]
+ unsigned OpNum = 0;
+ Value *Agg;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+ return Error("Invalid INSERTVAL record");
+ Value *Val;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Val))
+ return Error("Invalid INSERTVAL record");
+
+ SmallVector<unsigned, 4> INSERTVALIdx;
+ for (unsigned RecSize = Record.size();
+ OpNum != RecSize; ++OpNum) {
+ uint64_t Index = Record[OpNum];
+ if ((unsigned)Index != Index)
+ return Error("Invalid INSERTVAL index");
+ INSERTVALIdx.push_back((unsigned)Index);
+ }
+
+ I = InsertValueInst::Create(Agg, Val, INSERTVALIdx);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval]
+ // obsolete form of select
+ // handles select i1 ... in old bitcode
+ unsigned OpNum = 0;
+ Value *TrueVal, *FalseVal, *Cond;
+ if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+ popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
+ popValue(Record, OpNum, NextValueNo, Type::getInt1Ty(Context), Cond))
+ return Error("Invalid SELECT record");
+
+ I = SelectInst::Create(Cond, TrueVal, FalseVal);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred]
+ // new form of select
+ // handles select i1 or select [N x i1]
+ unsigned OpNum = 0;
+ Value *TrueVal, *FalseVal, *Cond;
+ if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+ popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
+ getValueTypePair(Record, OpNum, NextValueNo, Cond))
+ return Error("Invalid SELECT record");
+
+ // select condition can be either i1 or [N x i1]
+ if (VectorType* vector_type =
+ dyn_cast<VectorType>(Cond->getType())) {
+ // expect <n x i1>
+ if (vector_type->getElementType() != Type::getInt1Ty(Context))
+ return Error("Invalid SELECT condition type");
+ } else {
+ // expect i1
+ if (Cond->getType() != Type::getInt1Ty(Context))
+ return Error("Invalid SELECT condition type");
+ }
+
+ I = SelectInst::Create(Cond, TrueVal, FalseVal);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
+ unsigned OpNum = 0;
+ Value *Vec, *Idx;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+ popValue(Record, OpNum, NextValueNo, Type::getInt32Ty(Context), Idx))
+ return Error("Invalid EXTRACTELT record");
+ I = ExtractElementInst::Create(Vec, Idx);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval]
+ unsigned OpNum = 0;
+ Value *Vec, *Elt, *Idx;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+ popValue(Record, OpNum, NextValueNo,
+ cast<VectorType>(Vec->getType())->getElementType(), Elt) ||
+ popValue(Record, OpNum, NextValueNo, Type::getInt32Ty(Context), Idx))
+ return Error("Invalid INSERTELT record");
+ I = InsertElementInst::Create(Vec, Elt, Idx);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval]
+ unsigned OpNum = 0;
+ Value *Vec1, *Vec2, *Mask;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
+ popValue(Record, OpNum, NextValueNo, Vec1->getType(), Vec2))
+ return Error("Invalid SHUFFLEVEC record");
+
+ if (getValueTypePair(Record, OpNum, NextValueNo, Mask))
+ return Error("Invalid SHUFFLEVEC record");
+ I = new ShuffleVectorInst(Vec1, Vec2, Mask);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_CMP: // CMP: [opty, opval, opval, pred]
+ // Old form of ICmp/FCmp returning bool
+ // Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were
+ // both legal on vectors but had different behaviour.
+ case naclbitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred]
+ // FCmp/ICmp returning bool or vector of bool
+
+ unsigned OpNum = 0;
+ Value *LHS, *RHS;
+ if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+ popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS) ||
+ OpNum+1 != Record.size())
+ return Error("Invalid CMP record");
+
+ if (LHS->getType()->isFPOrFPVectorTy())
+ I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS);
+ else
+ I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_RET: // RET: [opty,opval<optional>]
+ {
+ unsigned Size = Record.size();
+ if (Size == 0) {
+ I = ReturnInst::Create(Context);
+ InstructionList.push_back(I);
+ break;
+ }
+
+ unsigned OpNum = 0;
+ Value *Op = NULL;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ return Error("Invalid RET record");
+ if (OpNum != Record.size())
+ return Error("Invalid RET record");
+
+ I = ReturnInst::Create(Context, Op);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
+ if (Record.size() != 1 && Record.size() != 3)
+ return Error("Invalid BR record");
+ BasicBlock *TrueDest = getBasicBlock(Record[0]);
+ if (TrueDest == 0)
+ return Error("Invalid BR record");
+
+ if (Record.size() == 1) {
+ I = BranchInst::Create(TrueDest);
+ InstructionList.push_back(I);
+ }
+ else {
+ BasicBlock *FalseDest = getBasicBlock(Record[1]);
+ Value *Cond = getValue(Record, 2, NextValueNo,
+ Type::getInt1Ty(Context));
+ if (FalseDest == 0 || Cond == 0)
+ return Error("Invalid BR record");
+ I = BranchInst::Create(TrueDest, FalseDest, Cond);
+ InstructionList.push_back(I);
+ }
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
+ // Check magic
+ if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {
+ // New SwitchInst format with case ranges.
+
+ Type *OpTy = getTypeByID(Record[1]);
+ unsigned ValueBitWidth = cast<IntegerType>(OpTy)->getBitWidth();
+
+ Value *Cond = getValue(Record, 2, NextValueNo, OpTy);
+ BasicBlock *Default = getBasicBlock(Record[3]);
+ if (OpTy == 0 || Cond == 0 || Default == 0)
+ return Error("Invalid SWITCH record");
+
+ unsigned NumCases = Record[4];
+
+ SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
+ InstructionList.push_back(SI);
+
+ unsigned CurIdx = 5;
+ for (unsigned i = 0; i != NumCases; ++i) {
+ IntegersSubsetToBB CaseBuilder;
+ unsigned NumItems = Record[CurIdx++];
+ for (unsigned ci = 0; ci != NumItems; ++ci) {
+ bool isSingleNumber = Record[CurIdx++];
+
+ APInt Low;
+ unsigned ActiveWords = 1;
+ if (ValueBitWidth > 64)
+ ActiveWords = Record[CurIdx++];
+ Low = ReadWideAPInt(makeArrayRef(&Record[CurIdx], ActiveWords),
+ ValueBitWidth);
+ CurIdx += ActiveWords;
+
+ if (!isSingleNumber) {
+ ActiveWords = 1;
+ if (ValueBitWidth > 64)
+ ActiveWords = Record[CurIdx++];
+ APInt High =
+ ReadWideAPInt(makeArrayRef(&Record[CurIdx], ActiveWords),
+ ValueBitWidth);
+
+ CaseBuilder.add(IntItem::fromType(OpTy, Low),
+ IntItem::fromType(OpTy, High));
+ CurIdx += ActiveWords;
+ } else
+ CaseBuilder.add(IntItem::fromType(OpTy, Low));
+ }
+ BasicBlock *DestBB = getBasicBlock(Record[CurIdx++]);
+ IntegersSubset Case = CaseBuilder.getCase();
+ SI->addCase(Case, DestBB);
+ }
+ uint16_t Hash = SI->hash();
+ if (Hash != (Record[0] & 0xFFFF))
+ return Error("Invalid SWITCH record");
+ I = SI;
+ break;
+ }
+
+ // Old SwitchInst format without case ranges.
+
+ if (Record.size() < 3 || (Record.size() & 1) == 0)
+ return Error("Invalid SWITCH record");
+ Type *OpTy = getTypeByID(Record[0]);
+ Value *Cond = getValue(Record, 1, NextValueNo, OpTy);
+ BasicBlock *Default = getBasicBlock(Record[2]);
+ if (OpTy == 0 || Cond == 0 || Default == 0)
+ return Error("Invalid SWITCH record");
+ unsigned NumCases = (Record.size()-3)/2;
+ SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
+ InstructionList.push_back(SI);
+ for (unsigned i = 0, e = NumCases; i != e; ++i) {
+ ConstantInt *CaseVal =
+ dyn_cast_or_null<ConstantInt>(getFnValueByID(Record[3+i*2], OpTy));
+ BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]);
+ if (CaseVal == 0 || DestBB == 0) {
+ delete SI;
+ return Error("Invalid SWITCH record!");
+ }
+ SI->addCase(CaseVal, DestBB);
+ }
+ I = SI;
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...]
+ if (Record.size() < 2)
+ return Error("Invalid INDIRECTBR record");
+ Type *OpTy = getTypeByID(Record[0]);
+ Value *Address = getValue(Record, 1, NextValueNo, OpTy);
+ if (OpTy == 0 || Address == 0)
+ return Error("Invalid INDIRECTBR record");
+ unsigned NumDests = Record.size()-2;
+ IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests);
+ InstructionList.push_back(IBI);
+ for (unsigned i = 0, e = NumDests; i != e; ++i) {
+ if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) {
+ IBI->addDestination(DestBB);
+ } else {
+ delete IBI;
+ return Error("Invalid INDIRECTBR record!");
+ }
+ }
+ I = IBI;
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_INVOKE: {
+ // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
+ if (Record.size() < 4) return Error("Invalid INVOKE record");
+ AttributeSet PAL = getAttributes(Record[0]);
+ unsigned CCInfo = Record[1];
+ BasicBlock *NormalBB = getBasicBlock(Record[2]);
+ BasicBlock *UnwindBB = getBasicBlock(Record[3]);
+
+ unsigned OpNum = 4;
+ Value *Callee;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+ return Error("Invalid INVOKE record");
+
+ PointerType *CalleeTy = dyn_cast<PointerType>(Callee->getType());
+ FunctionType *FTy = !CalleeTy ? 0 :
+ dyn_cast<FunctionType>(CalleeTy->getElementType());
+
+ // Check that the right number of fixed parameters are here.
+ if (FTy == 0 || NormalBB == 0 || UnwindBB == 0 ||
+ Record.size() < OpNum+FTy->getNumParams())
+ return Error("Invalid INVOKE record");
+
+ SmallVector<Value*, 16> Ops;
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+ Ops.push_back(getValue(Record, OpNum, NextValueNo,
+ FTy->getParamType(i)));
+ if (Ops.back() == 0) return Error("Invalid INVOKE record");
+ }
+
+ if (!FTy->isVarArg()) {
+ if (Record.size() != OpNum)
+ return Error("Invalid INVOKE record");
+ } else {
+ // Read type/value pairs for varargs params.
+ while (OpNum != Record.size()) {
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ return Error("Invalid INVOKE record");
+ Ops.push_back(Op);
+ }
+ }
+
+ I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops);
+ InstructionList.push_back(I);
+ cast<InvokeInst>(I)->setCallingConv(
+ static_cast<CallingConv::ID>(CCInfo));
+ cast<InvokeInst>(I)->setAttributes(PAL);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]
+ unsigned Idx = 0;
+ Value *Val = 0;
+ if (getValueTypePair(Record, Idx, NextValueNo, Val))
+ return Error("Invalid RESUME record");
+ I = ResumeInst::Create(Val);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
+ I = new UnreachableInst(Context);
+ InstructionList.push_back(I);
+ break;
+ case naclbitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
+ if (Record.size() < 1 || ((Record.size()-1)&1))
+ return Error("Invalid PHI record");
+ Type *Ty = getTypeByID(Record[0]);
+ if (!Ty) return Error("Invalid PHI record");
+
+ PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2);
+ InstructionList.push_back(PN);
+
+ for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) {
+ Value *V;
+ // With the new function encoding, it is possible that operands have
+ // negative IDs (for forward references). Use a signed VBR
+ // representation to keep the encoding small.
+ if (UseRelativeIDs)
+ V = getValueSigned(Record, 1+i, NextValueNo, Ty);
+ else
+ V = getValue(Record, 1+i, NextValueNo, Ty);
+ BasicBlock *BB = getBasicBlock(Record[2+i]);
+ if (!V || !BB) return Error("Invalid PHI record");
+ PN->addIncoming(V, BB);
+ }
+ I = PN;
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_LANDINGPAD: {
+ // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?]
+ unsigned Idx = 0;
+ if (Record.size() < 4)
+ return Error("Invalid LANDINGPAD record");
+ Type *Ty = getTypeByID(Record[Idx++]);
+ if (!Ty) return Error("Invalid LANDINGPAD record");
+ Value *PersFn = 0;
+ if (getValueTypePair(Record, Idx, NextValueNo, PersFn))
+ return Error("Invalid LANDINGPAD record");
+
+ bool IsCleanup = !!Record[Idx++];
+ unsigned NumClauses = Record[Idx++];
+ LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, NumClauses);
+ LP->setCleanup(IsCleanup);
+ for (unsigned J = 0; J != NumClauses; ++J) {
+ LandingPadInst::ClauseType CT =
+ LandingPadInst::ClauseType(Record[Idx++]); (void)CT;
+ Value *Val;
+
+ if (getValueTypePair(Record, Idx, NextValueNo, Val)) {
+ delete LP;
+ return Error("Invalid LANDINGPAD record");
+ }
+
+ assert((CT != LandingPadInst::Catch ||
+ !isa<ArrayType>(Val->getType())) &&
+ "Catch clause has a invalid type!");
+ assert((CT != LandingPadInst::Filter ||
+ isa<ArrayType>(Val->getType())) &&
+ "Filter clause has invalid type!");
+ LP->addClause(Val);
+ }
+
+ I = LP;
+ InstructionList.push_back(I);
+ break;
+ }
+
+ case naclbitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align]
+ if (Record.size() != 4)
+ return Error("Invalid ALLOCA record");
+ PointerType *Ty =
+ dyn_cast_or_null<PointerType>(getTypeByID(Record[0]));
+ Type *OpTy = getTypeByID(Record[1]);
+ Value *Size = getFnValueByID(Record[2], OpTy);
+ unsigned Align = Record[3];
+ if (!Ty || !Size) return Error("Invalid ALLOCA record");
+ I = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol]
+ unsigned OpNum = 0;
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+ OpNum+2 != Record.size())
+ return Error("Invalid LOAD record");
+
+ I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_LOADATOMIC: {
+ // LOADATOMIC: [opty, op, align, vol, ordering, synchscope]
+ unsigned OpNum = 0;
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+ OpNum+4 != Record.size())
+ return Error("Invalid LOADATOMIC record");
+
+
+ AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+ if (Ordering == NotAtomic || Ordering == Release ||
+ Ordering == AcquireRelease)
+ return Error("Invalid LOADATOMIC record");
+ if (Ordering != NotAtomic && Record[OpNum] == 0)
+ return Error("Invalid LOADATOMIC record");
+ SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+
+ I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1,
+ Ordering, SynchScope);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_STORE: { // STORE2:[ptrty, ptr, val, align, vol]
+ unsigned OpNum = 0;
+ Value *Val, *Ptr;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ popValue(Record, OpNum, NextValueNo,
+ cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+ OpNum+2 != Record.size())
+ return Error("Invalid STORE record");
+
+ I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_STOREATOMIC: {
+ // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, synchscope]
+ unsigned OpNum = 0;
+ Value *Val, *Ptr;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ popValue(Record, OpNum, NextValueNo,
+ cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+ OpNum+4 != Record.size())
+ return Error("Invalid STOREATOMIC record");
+
+ AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+ if (Ordering == NotAtomic || Ordering == Acquire ||
+ Ordering == AcquireRelease)
+ return Error("Invalid STOREATOMIC record");
+ SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+ if (Ordering != NotAtomic && Record[OpNum] == 0)
+ return Error("Invalid STOREATOMIC record");
+
+ I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1,
+ Ordering, SynchScope);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_CMPXCHG: {
+ // CMPXCHG:[ptrty, ptr, cmp, new, vol, ordering, synchscope]
+ unsigned OpNum = 0;
+ Value *Ptr, *Cmp, *New;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ popValue(Record, OpNum, NextValueNo,
+ cast<PointerType>(Ptr->getType())->getElementType(), Cmp) ||
+ popValue(Record, OpNum, NextValueNo,
+ cast<PointerType>(Ptr->getType())->getElementType(), New) ||
+ OpNum+3 != Record.size())
+ return Error("Invalid CMPXCHG record");
+ AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+1]);
+ if (Ordering == NotAtomic || Ordering == Unordered)
+ return Error("Invalid CMPXCHG record");
+ SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]);
+ I = new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope);
+ cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_ATOMICRMW: {
+ // ATOMICRMW:[ptrty, ptr, val, op, vol, ordering, synchscope]
+ unsigned OpNum = 0;
+ Value *Ptr, *Val;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ popValue(Record, OpNum, NextValueNo,
+ cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+ OpNum+4 != Record.size())
+ return Error("Invalid ATOMICRMW record");
+ AtomicRMWInst::BinOp Operation = GetDecodedRMWOperation(Record[OpNum]);
+ if (Operation < AtomicRMWInst::FIRST_BINOP ||
+ Operation > AtomicRMWInst::LAST_BINOP)
+ return Error("Invalid ATOMICRMW record");
+ AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+ if (Ordering == NotAtomic || Ordering == Unordered)
+ return Error("Invalid ATOMICRMW record");
+ SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+ I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope);
+ cast<AtomicRMWInst>(I)->setVolatile(Record[OpNum+1]);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_FENCE: { // FENCE:[ordering, synchscope]
+ if (2 != Record.size())
+ return Error("Invalid FENCE record");
+ AtomicOrdering Ordering = GetDecodedOrdering(Record[0]);
+ if (Ordering == NotAtomic || Ordering == Unordered ||
+ Ordering == Monotonic)
+ return Error("Invalid FENCE record");
+ SynchronizationScope SynchScope = GetDecodedSynchScope(Record[1]);
+ I = new FenceInst(Context, Ordering, SynchScope);
+ InstructionList.push_back(I);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_CALL: {
+ // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...]
+ if (Record.size() < 3)
+ return Error("Invalid CALL record");
+
+ AttributeSet PAL = getAttributes(Record[0]);
+ unsigned CCInfo = Record[1];
+
+ unsigned OpNum = 2;
+ Value *Callee;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+ return Error("Invalid CALL record");
+
+ PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
+ FunctionType *FTy = 0;
+ if (OpTy) FTy = dyn_cast<FunctionType>(OpTy->getElementType());
+ if (!FTy || Record.size() < FTy->getNumParams()+OpNum)
+ return Error("Invalid CALL record");
+
+ SmallVector<Value*, 16> Args;
+ // Read the fixed params.
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+ if (FTy->getParamType(i)->isLabelTy())
+ Args.push_back(getBasicBlock(Record[OpNum]));
+ else
+ Args.push_back(getValue(Record, OpNum, NextValueNo,
+ FTy->getParamType(i)));
+ if (Args.back() == 0) return Error("Invalid CALL record");
+ }
+
+ // Read type/value pairs for varargs params.
+ if (!FTy->isVarArg()) {
+ if (OpNum != Record.size())
+ return Error("Invalid CALL record");
+ } else {
+ while (OpNum != Record.size()) {
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ return Error("Invalid CALL record");
+ Args.push_back(Op);
+ }
+ }
+
+ I = CallInst::Create(Callee, Args);
+ InstructionList.push_back(I);
+ cast<CallInst>(I)->setCallingConv(
+ static_cast<CallingConv::ID>(CCInfo>>1));
+ cast<CallInst>(I)->setTailCall(CCInfo & 1);
+ cast<CallInst>(I)->setAttributes(PAL);
+ break;
+ }
+ case naclbitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]
+ if (Record.size() < 3)
+ return Error("Invalid VAARG record");
+ Type *OpTy = getTypeByID(Record[0]);
+ Value *Op = getValue(Record, 1, NextValueNo, OpTy);
+ Type *ResTy = getTypeByID(Record[2]);
+ if (!OpTy || !Op || !ResTy)
+ return Error("Invalid VAARG record");
+ I = new VAArgInst(Op, ResTy);
+ InstructionList.push_back(I);
+ break;
+ }
+ }
+
+ // Add instruction to end of current BB. If there is no current BB, reject
+ // this file.
+ if (CurBB == 0) {
+ delete I;
+ return Error("Invalid instruction with no BB");
+ }
+ CurBB->getInstList().push_back(I);
+
+ // If this was a terminator instruction, move to the next block.
+ if (isa<TerminatorInst>(I)) {
+ ++CurBBNo;
+ CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : 0;
+ }
+
+ // Non-void values get registered in the value table for future use.
+ if (I && !I->getType()->isVoidTy())
+ ValueList.AssignValue(I, NextValueNo++);
+ }
+
+OutOfRecordLoop:
+
+ // Check the function list for unresolved values.
+ if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
+ if (A->getParent() == 0) {
+ // We found at least one unresolved value. Nuke them all to avoid leaks.
+ for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
+ if ((A = dyn_cast<Argument>(ValueList[i])) && A->getParent() == 0) {
+ A->replaceAllUsesWith(UndefValue::get(A->getType()));
+ delete A;
+ }
+ }
+ return Error("Never resolved value found in function!");
+ }
+ }
+
+ // FIXME: Check for unresolved forward-declared metadata references
+ // and clean up leaks.
+
+ // See if anything took the address of blocks in this function. If so,
+ // resolve them now.
+ DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI =
+ BlockAddrFwdRefs.find(F);
+ if (BAFRI != BlockAddrFwdRefs.end()) {
+ std::vector<BlockAddrRefTy> &RefList = BAFRI->second;
+ for (unsigned i = 0, e = RefList.size(); i != e; ++i) {
+ unsigned BlockIdx = RefList[i].first;
+ if (BlockIdx >= FunctionBBs.size())
+ return Error("Invalid blockaddress block #");
+
+ GlobalVariable *FwdRef = RefList[i].second;
+ FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx]));
+ FwdRef->eraseFromParent();
+ }
+
+ BlockAddrFwdRefs.erase(BAFRI);
+ }
+
+ // Trim the value list down to the size it was before we parsed this function.
+ ValueList.shrinkTo(ModuleValueListSize);
+ MDValueList.shrinkTo(ModuleMDValueListSize);
+ std::vector<BasicBlock*>().swap(FunctionBBs);
+ return false;
+}
+
+/// FindFunctionInStream - Find the function body in the bitcode stream
+bool NaClBitcodeReader::FindFunctionInStream(Function *F,
+ DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) {
+ while (DeferredFunctionInfoIterator->second == 0) {
+ if (Stream.AtEndOfStream())
+ return Error("Could not find Function in stream");
+ // ParseModule will parse the next body in the stream and set its
+ // position in the DeferredFunctionInfo map.
+ if (ParseModule(true)) return true;
+ }
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// GVMaterializer implementation
+//===----------------------------------------------------------------------===//
+
+
+bool NaClBitcodeReader::isMaterializable(const GlobalValue *GV) const {
+ if (const Function *F = dyn_cast<Function>(GV)) {
+ return F->isDeclaration() &&
+ DeferredFunctionInfo.count(const_cast<Function*>(F));
+ }
+ return false;
+}
+
+bool NaClBitcodeReader::Materialize(GlobalValue *GV, std::string *ErrInfo) {
+ Function *F = dyn_cast<Function>(GV);
+ // If it's not a function or is already material, ignore the request.
+ if (!F || !F->isMaterializable()) return false;
+
+ DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F);
+ assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
+ // If its position is recorded as 0, its body is somewhere in the stream
+ // but we haven't seen it yet.
+ if (DFII->second == 0)
+ if (LazyStreamer && FindFunctionInStream(F, DFII)) return true;
+
+ // Move the bit stream to the saved position of the deferred function body.
+ Stream.JumpToBit(DFII->second);
+
+ if (ParseFunctionBody(F)) {
+ if (ErrInfo) *ErrInfo = ErrorString;
+ return true;
+ }
+
+ // Upgrade any old intrinsic calls in the function.
+ for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(),
+ E = UpgradedIntrinsics.end(); I != E; ++I) {
+ if (I->first != I->second) {
+ for (Value::use_iterator UI = I->first->use_begin(),
+ UE = I->first->use_end(); UI != UE; ) {
+ if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+ UpgradeIntrinsicCall(CI, I->second);
+ }
+ }
+ }
+
+ return false;
+}
+
+bool NaClBitcodeReader::isDematerializable(const GlobalValue *GV) const {
+ const Function *F = dyn_cast<Function>(GV);
+ if (!F || F->isDeclaration())
+ return false;
+ // @LOCALMOD-START
+ // Don't dematerialize functions with BBs which have their address taken;
+ // it will cause any referencing blockAddress constants to also be destroyed,
+ // but because they are GVs, they need to stay around until PassManager
+ // finalization.
+ for (Function::const_iterator BB = F->begin(); BB != F->end(); ++BB) {
+ if (BB->hasAddressTaken())
+ return false;
+ }
+ // @LOCALMOD-END
+ return DeferredFunctionInfo.count(const_cast<Function*>(F));
+}
+
+void NaClBitcodeReader::Dematerialize(GlobalValue *GV) {
+ Function *F = dyn_cast<Function>(GV);
+ // If this function isn't dematerializable, this is a noop.
+ if (!F || !isDematerializable(F))
+ return;
+
+ assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
+
+ // Just forget the function body, we can remat it later.
+ F->deleteBody();
+}
+
+
+bool NaClBitcodeReader::MaterializeModule(Module *M, std::string *ErrInfo) {
+ assert(M == TheModule &&
+ "Can only Materialize the Module this NaClBitcodeReader is attached to.");
+ // Iterate over the module, deserializing any functions that are still on
+ // disk.
+ for (Module::iterator F = TheModule->begin(), E = TheModule->end();
+ F != E; ++F)
+ if (F->isMaterializable() &&
+ Materialize(F, ErrInfo))
+ return true;
+
+ // At this point, if there are any function bodies, the current bit is
+ // pointing to the END_BLOCK record after them. Now make sure the rest
+ // of the bits in the module have been read.
+ if (NextUnreadBit)
+ ParseModule(true);
+
+ // Upgrade any intrinsic calls that slipped through (should not happen!) and
+ // delete the old functions to clean up. We can't do this unless the entire
+ // module is materialized because there could always be another function body
+ // with calls to the old function.
+ for (std::vector<std::pair<Function*, Function*> >::iterator I =
+ UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) {
+ if (I->first != I->second) {
+ for (Value::use_iterator UI = I->first->use_begin(),
+ UE = I->first->use_end(); UI != UE; ) {
+ if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+ UpgradeIntrinsicCall(CI, I->second);
+ }
+ if (!I->first->use_empty())
+ I->first->replaceAllUsesWith(I->second);
+ I->first->eraseFromParent();
+ }
+ }
+ std::vector<std::pair<Function*, Function*> >().swap(UpgradedIntrinsics);
+
+ return false;
+}
+
+bool NaClBitcodeReader::InitStream() {
+ if (LazyStreamer) return InitLazyStream();
+ return InitStreamFromBuffer();
+}
+
+bool NaClBitcodeReader::InitStreamFromBuffer() {
+ const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
+ const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
+
+ if (Buffer->getBufferSize() & 3) {
+ if (!isNaClRawBitcode(BufPtr, BufEnd) &&
+ !isNaClBitcodeWrapper(BufPtr, BufEnd))
+ return Error("Invalid bitcode signature");
+ else
+ return Error("Bitcode stream should be a multiple of 4 bytes in length");
+ }
+
+ // If we have a wrapper header, parse it and ignore the non-bc file contents.
+ // The magic number is 0x0B17C0DE stored in little endian.
+ if (isNaClBitcodeWrapper(BufPtr, BufEnd))
+ if (SkipNaClBitcodeWrapperHeader(BufPtr, BufEnd, true))
+ return Error("Invalid bitcode wrapper header");
+
+ StreamFile.reset(new NaClBitstreamReader(BufPtr, BufEnd));
+ Stream.init(*StreamFile);
+
+ return false;
+}
+
+bool NaClBitcodeReader::InitLazyStream() {
+ // Check and strip off the bitcode wrapper; NaClBitstreamReader expects
+ // never to see it.
+ StreamingMemoryObject *Bytes = new StreamingMemoryObject(LazyStreamer);
+ StreamFile.reset(new NaClBitstreamReader(Bytes));
+ Stream.init(*StreamFile);
+
+ unsigned char buf[16];
+ if (Bytes->readBytes(0, 16, buf, NULL) == -1)
+ return Error("Bitcode stream must be at least 16 bytes in length");
+
+ if (!isNaClBitcode(buf, buf + 16))
+ return Error("Invalid bitcode signature");
+
+ if (isNaClBitcodeWrapper(buf, buf + 4)) {
+ const unsigned char *bitcodeStart = buf;
+ const unsigned char *bitcodeEnd = buf + 16;
+ SkipNaClBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false);
+ Bytes->dropLeadingBytes(bitcodeStart - buf);
+ Bytes->setKnownObjectSize(bitcodeEnd - bitcodeStart);
+ }
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// External interface
+//===----------------------------------------------------------------------===//
+
+/// getNaClLazyBitcodeModule - lazy function-at-a-time loading from a file.
+///
+Module *llvm::getNaClLazyBitcodeModule(MemoryBuffer *Buffer,
+ LLVMContext& Context,
+ std::string *ErrMsg) {
+ Module *M = new Module(Buffer->getBufferIdentifier(), Context);
+ NaClBitcodeReader *R = new NaClBitcodeReader(Buffer, Context);
+ M->setMaterializer(R);
+ if (R->ParseBitcodeInto(M)) {
+ if (ErrMsg)
+ *ErrMsg = R->getErrorString();
+
+ delete M; // Also deletes R.
+ return 0;
+ }
+ // Have the NaClBitcodeReader dtor delete 'Buffer'.
+ R->setBufferOwned(true);
+
+ R->materializeForwardReferencedFunctions();
+
+ M->convertMetadataToLibraryList(); // @LOCALMOD
+
+ return M;
+}
+
+
+Module *llvm::getNaClStreamedBitcodeModule(const std::string &name,
+ DataStreamer *streamer,
+ LLVMContext &Context,
+ std::string *ErrMsg) {
+ Module *M = new Module(name, Context);
+ NaClBitcodeReader *R = new NaClBitcodeReader(streamer, Context);
+ M->setMaterializer(R);
+ if (R->ParseBitcodeInto(M)) {
+ if (ErrMsg)
+ *ErrMsg = R->getErrorString();
+ delete M; // Also deletes R.
+ return 0;
+ }
+ R->setBufferOwned(false); // no buffer to delete
+
+ R->materializeForwardReferencedFunctions();
+
+ M->convertMetadataToLibraryList(); // @LOCALMOD
+
+ return M;
+}
+
+/// NaClParseBitcodeFile - Read the specified bitcode file, returning the module.
+/// If an error occurs, return null and fill in *ErrMsg if non-null.
+Module *llvm::NaClParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
+ std::string *ErrMsg){
+ Module *M = getNaClLazyBitcodeModule(Buffer, Context, ErrMsg);
+ if (!M) return 0;
+
+ // Don't let the NaClBitcodeReader dtor delete 'Buffer', regardless of whether
+ // there was an error.
+ static_cast<NaClBitcodeReader*>(M->getMaterializer())->setBufferOwned(false);
+
+ // Read in the entire module, and destroy the NaClBitcodeReader.
+ if (M->MaterializeAllPermanently(ErrMsg)) {
+ delete M;
+ return 0;
+ }
+
+ // TODO: Restore the use-lists to the in-memory state when the bitcode was
+ // written. We must defer until the Module has been fully materialized.
+
+ return M;
+}
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h
new file mode 100644
index 0000000000..f6e3e94841
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h
@@ -0,0 +1,350 @@
+//===- NaClBitcodeReader.h ------------------------------------*- C++ -*-===//
+// Internal NaClBitcodeReader implementation
+//
+// 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 NaClBitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef NACL_BITCODE_READER_H
+#define NACL_BITCODE_READER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/NaCl/NaClBitstreamReader.h"
+#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
+#include "llvm/GVMaterializer.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/ValueHandle.h"
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+ class LLVMContext;
+
+//===----------------------------------------------------------------------===//
+// NaClBitcodeReaderValueList Class
+//===----------------------------------------------------------------------===//
+
+class NaClBitcodeReaderValueList {
+ std::vector<WeakVH> ValuePtrs;
+
+ /// ResolveConstants - As we resolve forward-referenced constants, we add
+ /// information about them to this vector. This allows us to resolve them in
+ /// bulk instead of resolving each reference at a time. See the code in
+ /// ResolveConstantForwardRefs for more information about this.
+ ///
+ /// The key of this vector is the placeholder constant, the value is the slot
+ /// number that holds the resolved value.
+ typedef std::vector<std::pair<Constant*, unsigned> > ResolveConstantsTy;
+ ResolveConstantsTy ResolveConstants;
+ LLVMContext &Context;
+public:
+ NaClBitcodeReaderValueList(LLVMContext &C) : Context(C) {}
+ ~NaClBitcodeReaderValueList() {
+ assert(ResolveConstants.empty() && "Constants not resolved?");
+ }
+
+ // vector compatibility methods
+ unsigned size() const { return ValuePtrs.size(); }
+ void resize(unsigned N) { ValuePtrs.resize(N); }
+ void push_back(Value *V) {
+ ValuePtrs.push_back(V);
+ }
+
+ void clear() {
+ assert(ResolveConstants.empty() && "Constants not resolved?");
+ ValuePtrs.clear();
+ }
+
+ Value *operator[](unsigned i) const {
+ assert(i < ValuePtrs.size());
+ return ValuePtrs[i];
+ }
+
+ Value *back() const { return ValuePtrs.back(); }
+ void pop_back() { ValuePtrs.pop_back(); }
+ bool empty() const { return ValuePtrs.empty(); }
+ void shrinkTo(unsigned N) {
+ assert(N <= size() && "Invalid shrinkTo request!");
+ ValuePtrs.resize(N);
+ }
+
+ Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
+ Value *getValueFwdRef(unsigned Idx, Type *Ty);
+
+ void AssignValue(Value *V, unsigned Idx);
+
+ /// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+ /// resolves any forward references.
+ void ResolveConstantForwardRefs();
+};
+
+
+//===----------------------------------------------------------------------===//
+// NaClBitcodeReaderMDValueList Class
+//===----------------------------------------------------------------------===//
+
+class NaClBitcodeReaderMDValueList {
+ std::vector<WeakVH> MDValuePtrs;
+
+ LLVMContext &Context;
+public:
+ NaClBitcodeReaderMDValueList(LLVMContext& C) : Context(C) {}
+
+ // vector compatibility methods
+ unsigned size() const { return MDValuePtrs.size(); }
+ void resize(unsigned N) { MDValuePtrs.resize(N); }
+ void push_back(Value *V) { MDValuePtrs.push_back(V); }
+ void clear() { MDValuePtrs.clear(); }
+ Value *back() const { return MDValuePtrs.back(); }
+ void pop_back() { MDValuePtrs.pop_back(); }
+ bool empty() const { return MDValuePtrs.empty(); }
+
+ Value *operator[](unsigned i) const {
+ assert(i < MDValuePtrs.size());
+ return MDValuePtrs[i];
+ }
+
+ void shrinkTo(unsigned N) {
+ assert(N <= size() && "Invalid shrinkTo request!");
+ MDValuePtrs.resize(N);
+ }
+
+ Value *getValueFwdRef(unsigned Idx);
+ void AssignValue(Value *V, unsigned Idx);
+};
+
+class NaClBitcodeReader : public GVMaterializer {
+ LLVMContext &Context;
+ Module *TheModule;
+ MemoryBuffer *Buffer;
+ bool BufferOwned;
+ OwningPtr<NaClBitstreamReader> StreamFile;
+ NaClBitstreamCursor Stream;
+ DataStreamer *LazyStreamer;
+ uint64_t NextUnreadBit;
+ bool SeenValueSymbolTable;
+
+ const char *ErrorString;
+
+ std::vector<Type*> TypeList;
+ NaClBitcodeReaderValueList ValueList;
+ NaClBitcodeReaderMDValueList MDValueList;
+ SmallVector<Instruction *, 64> InstructionList;
+ SmallVector<SmallVector<uint64_t, 64>, 64> UseListRecords;
+
+ std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
+ std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
+
+ /// MAttributes - The set of attributes by index. Index zero in the
+ /// file is for null, and is thus not represented here. As such all indices
+ /// are off by one.
+ std::vector<AttributeSet> MAttributes;
+
+ /// \brief The set of attribute groups.
+ std::map<unsigned, AttributeSet> MAttributeGroups;
+
+ /// FunctionBBs - While parsing a function body, this is a list of the basic
+ /// blocks for the function.
+ std::vector<BasicBlock*> FunctionBBs;
+
+ // When reading the module header, this list is populated with functions that
+ // have bodies later in the file.
+ std::vector<Function*> FunctionsWithBodies;
+
+ // When intrinsic functions are encountered which require upgrading they are
+ // stored here with their replacement function.
+ typedef std::vector<std::pair<Function*, Function*> > UpgradedIntrinsicMap;
+ UpgradedIntrinsicMap UpgradedIntrinsics;
+
+ // Map the bitcode's custom MDKind ID to the Module's MDKind ID.
+ DenseMap<unsigned, unsigned> MDKindMap;
+
+ // Several operations happen after the module header has been read, but
+ // before function bodies are processed. This keeps track of whether
+ // we've done this yet.
+ bool SeenFirstFunctionBody;
+
+ /// DeferredFunctionInfo - When function bodies are initially scanned, this
+ /// map contains info about where to find deferred function body in the
+ /// stream.
+ DenseMap<Function*, uint64_t> DeferredFunctionInfo;
+
+ /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These
+ /// are resolved lazily when functions are loaded.
+ typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
+ DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
+
+ /// UseRelativeIDs - Indicates that we are using a new encoding for
+ /// instruction operands where most operands in the current
+ /// FUNCTION_BLOCK are encoded relative to the instruction number,
+ /// for a more compact encoding. Some instruction operands are not
+ /// relative to the instruction ID: basic block numbers, and types.
+ /// Once the old style function blocks have been phased out, we would
+ /// not need this flag.
+ bool UseRelativeIDs;
+
+public:
+ explicit NaClBitcodeReader(MemoryBuffer *buffer, LLVMContext &C)
+ : Context(C), TheModule(0), Buffer(buffer), BufferOwned(false),
+ LazyStreamer(0), NextUnreadBit(0), SeenValueSymbolTable(false),
+ ErrorString(0), ValueList(C), MDValueList(C),
+ SeenFirstFunctionBody(false), UseRelativeIDs(false) {
+ }
+ explicit NaClBitcodeReader(DataStreamer *streamer, LLVMContext &C)
+ : Context(C), TheModule(0), Buffer(0), BufferOwned(false),
+ LazyStreamer(streamer), NextUnreadBit(0), SeenValueSymbolTable(false),
+ ErrorString(0), ValueList(C), MDValueList(C),
+ SeenFirstFunctionBody(false), UseRelativeIDs(false) {
+ }
+ ~NaClBitcodeReader() {
+ FreeState();
+ }
+
+ void materializeForwardReferencedFunctions();
+
+ void FreeState();
+
+ /// setBufferOwned - If this is true, the reader will destroy the MemoryBuffer
+ /// when the reader is destroyed.
+ void setBufferOwned(bool Owned) { BufferOwned = Owned; }
+
+ virtual bool isMaterializable(const GlobalValue *GV) const;
+ virtual bool isDematerializable(const GlobalValue *GV) const;
+ virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0);
+ virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0);
+ virtual void Dematerialize(GlobalValue *GV);
+
+ bool Error(const char *Str) {
+ ErrorString = Str;
+ return true;
+ }
+ const char *getErrorString() const { return ErrorString; }
+
+ /// @brief Main interface to parsing a bitcode buffer.
+ /// @returns true if an error occurred.
+ bool ParseBitcodeInto(Module *M);
+
+ /// @brief Cheap mechanism to just extract module triple
+ /// @returns true if an error occurred.
+ bool ParseTriple(std::string &Triple);
+
+ static uint64_t decodeSignRotatedValue(uint64_t V);
+
+private:
+ Type *getTypeByID(unsigned ID);
+ Value *getFnValueByID(unsigned ID, Type *Ty) {
+ if (Ty && Ty->isMetadataTy())
+ return MDValueList.getValueFwdRef(ID);
+ return ValueList.getValueFwdRef(ID, Ty);
+ }
+ BasicBlock *getBasicBlock(unsigned ID) const {
+ if (ID >= FunctionBBs.size()) return 0; // Invalid ID
+ return FunctionBBs[ID];
+ }
+ AttributeSet getAttributes(unsigned i) const {
+ if (i-1 < MAttributes.size())
+ return MAttributes[i-1];
+ return AttributeSet();
+ }
+
+ /// getValueTypePair - Read a value/type pair out of the specified record from
+ /// slot 'Slot'. Increment Slot past the number of slots used in the record.
+ /// Return true on failure.
+ bool getValueTypePair(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+ unsigned InstNum, Value *&ResVal) {
+ if (Slot == Record.size()) return true;
+ unsigned ValNo = (unsigned)Record[Slot++];
+ // Adjust the ValNo, if it was encoded relative to the InstNum.
+ if (UseRelativeIDs)
+ ValNo = InstNum - ValNo;
+ if (ValNo < InstNum) {
+ // If this is not a forward reference, just return the value we already
+ // have.
+ ResVal = getFnValueByID(ValNo, 0);
+ return ResVal == 0;
+ } else if (Slot == Record.size()) {
+ return true;
+ }
+
+ unsigned TypeNo = (unsigned)Record[Slot++];
+ ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
+ return ResVal == 0;
+ }
+
+ /// popValue - Read a value out of the specified record from slot 'Slot'.
+ /// Increment Slot past the number of slots used by the value in the record.
+ /// Return true if there is an error.
+ bool popValue(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+ unsigned InstNum, Type *Ty, Value *&ResVal) {
+ if (getValue(Record, Slot, InstNum, Ty, ResVal))
+ return true;
+ // All values currently take a single record slot.
+ ++Slot;
+ return false;
+ }
+
+ /// getValue -- Like popValue, but does not increment the Slot number.
+ bool getValue(SmallVector<uint64_t, 64> &Record, unsigned Slot,
+ unsigned InstNum, Type *Ty, Value *&ResVal) {
+ ResVal = getValue(Record, Slot, InstNum, Ty);
+ return ResVal == 0;
+ }
+
+ /// getValue -- Version of getValue that returns ResVal directly,
+ /// or 0 if there is an error.
+ Value *getValue(SmallVector<uint64_t, 64> &Record, unsigned Slot,
+ unsigned InstNum, Type *Ty) {
+ if (Slot == Record.size()) return 0;
+ unsigned ValNo = (unsigned)Record[Slot];
+ // Adjust the ValNo, if it was encoded relative to the InstNum.
+ if (UseRelativeIDs)
+ ValNo = InstNum - ValNo;
+ return getFnValueByID(ValNo, Ty);
+ }
+
+ /// getValueSigned -- Like getValue, but decodes signed VBRs.
+ Value *getValueSigned(SmallVector<uint64_t, 64> &Record, unsigned Slot,
+ unsigned InstNum, Type *Ty) {
+ if (Slot == Record.size()) return 0;
+ unsigned ValNo = (unsigned)decodeSignRotatedValue(Record[Slot]);
+ // Adjust the ValNo, if it was encoded relative to the InstNum.
+ if (UseRelativeIDs)
+ ValNo = InstNum - ValNo;
+ return getFnValueByID(ValNo, Ty);
+ }
+
+ bool ParseModule(bool Resume);
+ bool ParseAttributeBlock();
+ bool ParseAttributeGroupBlock();
+ bool ParseTypeTable();
+ bool ParseTypeTableBody();
+
+ bool ParseValueSymbolTable();
+ bool ParseConstants();
+ bool RememberAndSkipFunctionBody();
+ bool ParseFunctionBody(Function *F);
+ bool GlobalCleanup();
+ bool ResolveGlobalAndAliasInits();
+ bool ParseMetadata();
+ bool ParseMetadataAttachment();
+ bool ParseModuleTriple(std::string &Triple);
+ bool ParseUseLists();
+ bool InitStream();
+ bool InitStreamFromBuffer();
+ bool InitLazyStream();
+ bool FindFunctionInStream(Function *F,
+ DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp
new file mode 100644
index 0000000000..ab8f1a5c6d
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp
@@ -0,0 +1,373 @@
+//===- NaClBitstreamReader.cpp --------------------------------------------===//
+// NaClBitstreamReader implementation
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/NaCl/NaClBitstreamReader.h"
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// NaClBitstreamCursor implementation
+//===----------------------------------------------------------------------===//
+
+void NaClBitstreamCursor::operator=(const NaClBitstreamCursor &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 (size_t i = 0, e = CurAbbrevs.size(); i != e; ++i)
+ CurAbbrevs[i]->addRef();
+
+ // Copy block scope and bump ref counts.
+ BlockScope = RHS.BlockScope;
+ for (size_t S = 0, e = BlockScope.size(); S != e; ++S) {
+ std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs;
+ for (size_t i = 0, e = Abbrevs.size(); i != e; ++i)
+ Abbrevs[i]->addRef();
+ }
+}
+
+void NaClBitstreamCursor::freeState() {
+ // Free all the Abbrevs.
+ for (size_t i = 0, e = CurAbbrevs.size(); i != e; ++i)
+ CurAbbrevs[i]->dropRef();
+ CurAbbrevs.clear();
+
+ // Free all the Abbrevs in the block scope.
+ for (size_t S = 0, e = BlockScope.size(); S != e; ++S) {
+ std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs;
+ for (size_t i = 0, e = Abbrevs.size(); i != e; ++i)
+ Abbrevs[i]->dropRef();
+ }
+ BlockScope.clear();
+}
+
+/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
+/// the block, and return true if the block has an error.
+bool NaClBitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
+ // 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 NaClBitstreamReader::BlockInfo *Info =
+ BitStream->getBlockInfo(BlockID)) {
+ for (size_t i = 0, e = 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);
+ SkipToFourByteBoundary();
+ unsigned NumWords = Read(bitc::BlockSizeWidth);
+ if (NumWordsP) *NumWordsP = NumWords;
+
+ // Validate that this block is sane.
+ if (CurCodeSize == 0 || AtEndOfStream())
+ return true;
+
+ return false;
+}
+
+void NaClBitstreamCursor::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 NaClBitstreamCursor::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()) {
+ case BitCodeAbbrevOp::Array:
+ case BitCodeAbbrevOp::Blob:
+ assert(0 && "Should not reach here");
+ 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;
+ }
+}
+
+void NaClBitstreamCursor::skipAbbreviatedField(const BitCodeAbbrevOp &Op) {
+ assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!");
+
+ // Decode the value as we are commanded.
+ switch (Op.getEncoding()) {
+ case BitCodeAbbrevOp::Array:
+ case BitCodeAbbrevOp::Blob:
+ assert(0 && "Should not reach here");
+ case BitCodeAbbrevOp::Fixed:
+ (void)Read((unsigned)Op.getEncodingData());
+ break;
+ case BitCodeAbbrevOp::VBR:
+ (void)ReadVBR64((unsigned)Op.getEncodingData());
+ break;
+ case BitCodeAbbrevOp::Char6:
+ (void)Read(6);
+ break;
+ }
+}
+
+
+
+/// skipRecord - Read the current record and discard it.
+void NaClBitstreamCursor::skipRecord(unsigned AbbrevID) {
+ // Skip unabbreviated records by reading past their entries.
+ if (AbbrevID == bitc::UNABBREV_RECORD) {
+ unsigned Code = ReadVBR(6);
+ (void)Code;
+ unsigned NumElts = ReadVBR(6);
+ for (unsigned i = 0; i != NumElts; ++i)
+ (void)ReadVBR64(6);
+ return;
+ }
+
+ const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
+
+ for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) {
+ const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
+ if (Op.isLiteral())
+ continue;
+
+ if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
+ Op.getEncoding() != BitCodeAbbrevOp::Blob) {
+ skipAbbreviatedField(Op);
+ continue;
+ }
+
+ 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)
+ skipAbbreviatedField(EltEnc);
+ continue;
+ }
+
+ assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
+ // Blob case. Read the number of bytes as a vbr6.
+ unsigned NumElts = ReadVBR(6);
+ SkipToFourByteBoundary(); // 32-bit alignment
+
+ // Figure out where the end of this blob will be including tail padding.
+ size_t NewEnd = GetCurrentBitNo()+((NumElts+3)&~3)*8;
+
+ // If this would read off the end of the bitcode file, just set the
+ // record to empty and return.
+ if (!canSkipToPos(NewEnd/8)) {
+ NextChar = BitStream->getBitcodeBytes().getExtent();
+ break;
+ }
+
+ // Skip over the blob.
+ JumpToBit(NewEnd);
+ }
+}
+
+unsigned NaClBitstreamCursor::readRecord(unsigned AbbrevID,
+ SmallVectorImpl<uint64_t> &Vals,
+ StringRef *Blob) {
+ 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);
+ continue;
+ }
+
+ if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
+ Op.getEncoding() != BitCodeAbbrevOp::Blob) {
+ readAbbreviatedField(Op, Vals);
+ continue;
+ }
+
+ 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);
+ continue;
+ }
+
+ assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
+ // Blob case. Read the number of bytes as a vbr6.
+ unsigned NumElts = ReadVBR(6);
+ SkipToFourByteBoundary(); // 32-bit alignment
+
+ // Figure out where the end of this blob will be including tail padding.
+ size_t CurBitPos = GetCurrentBitNo();
+ size_t NewEnd = CurBitPos+((NumElts+3)&~3)*8;
+
+ // If this would read off the end of the bitcode file, just set the
+ // record to empty and return.
+ if (!canSkipToPos(NewEnd/8)) {
+ Vals.append(NumElts, 0);
+ NextChar = BitStream->getBitcodeBytes().getExtent();
+ break;
+ }
+
+ // Otherwise, inform the streamer that we need these bytes in memory.
+ const char *Ptr = (const char*)
+ BitStream->getBitcodeBytes().getPointer(CurBitPos/8, NumElts);
+
+ // If we can return a reference to the data, do so to avoid copying it.
+ if (Blob) {
+ *Blob = StringRef(Ptr, NumElts);
+ } else {
+ // Otherwise, unpack into Vals with zero extension.
+ for (; NumElts; --NumElts)
+ Vals.push_back((unsigned char)*Ptr++);
+ }
+ // Skip over tail padding.
+ JumpToBit(NewEnd);
+ }
+
+ unsigned Code = (unsigned)Vals[0];
+ Vals.erase(Vals.begin());
+ return Code;
+}
+
+
+void NaClBitstreamCursor::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)) {
+ unsigned Data = ReadVBR64(5);
+
+ // As a special case, handle fixed(0) (i.e., a fixed field with zero bits)
+ // and vbr(0) as a literal zero. This is decoded the same way, and avoids
+ // a slow path in Read() to have to handle reading zero bits.
+ if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&
+ Data == 0) {
+ Abbv->Add(BitCodeAbbrevOp(0));
+ continue;
+ }
+
+ Abbv->Add(BitCodeAbbrevOp(E, Data));
+ } else
+ Abbv->Add(BitCodeAbbrevOp(E));
+ }
+ CurAbbrevs.push_back(Abbv);
+}
+
+bool NaClBitstreamCursor::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;
+ NaClBitstreamReader::BlockInfo *CurBlockInfo = 0;
+
+ // Read all the records for this module.
+ while (1) {
+ NaClBitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
+
+ switch (Entry.Kind) {
+ case llvm::NaClBitstreamEntry::SubBlock: // Handled for us already.
+ case llvm::NaClBitstreamEntry::Error:
+ return true;
+ case llvm::NaClBitstreamEntry::EndBlock:
+ return false;
+ case llvm::NaClBitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read abbrev records, associate them with CurBID.
+ if (Entry.ID == 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(Entry.ID, 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;
+ }
+ }
+ }
+}
diff --git a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
index 1cadd02450..edaaadf681 100644
--- a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
+++ b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
@@ -15,7 +15,7 @@
#include "NaClValueEnumerator.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h"
-#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InlineAsm.h"
@@ -63,18 +63,18 @@ enum {
static unsigned GetEncodedCastOpcode(unsigned Opcode) {
switch (Opcode) {
default: llvm_unreachable("Unknown cast instruction!");
- case Instruction::Trunc : return bitc::CAST_TRUNC;
- case Instruction::ZExt : return bitc::CAST_ZEXT;
- case Instruction::SExt : return bitc::CAST_SEXT;
- case Instruction::FPToUI : return bitc::CAST_FPTOUI;
- case Instruction::FPToSI : return bitc::CAST_FPTOSI;
- case Instruction::UIToFP : return bitc::CAST_UITOFP;
- case Instruction::SIToFP : return bitc::CAST_SITOFP;
- case Instruction::FPTrunc : return bitc::CAST_FPTRUNC;
- case Instruction::FPExt : return bitc::CAST_FPEXT;
- case Instruction::PtrToInt: return bitc::CAST_PTRTOINT;
- case Instruction::IntToPtr: return bitc::CAST_INTTOPTR;
- case Instruction::BitCast : return bitc::CAST_BITCAST;
+ case Instruction::Trunc : return naclbitc::CAST_TRUNC;
+ case Instruction::ZExt : return naclbitc::CAST_ZEXT;
+ case Instruction::SExt : return naclbitc::CAST_SEXT;
+ case Instruction::FPToUI : return naclbitc::CAST_FPTOUI;
+ case Instruction::FPToSI : return naclbitc::CAST_FPTOSI;
+ case Instruction::UIToFP : return naclbitc::CAST_UITOFP;
+ case Instruction::SIToFP : return naclbitc::CAST_SITOFP;
+ case Instruction::FPTrunc : return naclbitc::CAST_FPTRUNC;
+ case Instruction::FPExt : return naclbitc::CAST_FPEXT;
+ case Instruction::PtrToInt: return naclbitc::CAST_PTRTOINT;
+ case Instruction::IntToPtr: return naclbitc::CAST_INTTOPTR;
+ case Instruction::BitCast : return naclbitc::CAST_BITCAST;
}
}
@@ -82,60 +82,60 @@ static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
switch (Opcode) {
default: llvm_unreachable("Unknown binary instruction!");
case Instruction::Add:
- case Instruction::FAdd: return bitc::BINOP_ADD;
+ case Instruction::FAdd: return naclbitc::BINOP_ADD;
case Instruction::Sub:
- case Instruction::FSub: return bitc::BINOP_SUB;
+ case Instruction::FSub: return naclbitc::BINOP_SUB;
case Instruction::Mul:
- case Instruction::FMul: return bitc::BINOP_MUL;
- case Instruction::UDiv: return bitc::BINOP_UDIV;
+ case Instruction::FMul: return naclbitc::BINOP_MUL;
+ case Instruction::UDiv: return naclbitc::BINOP_UDIV;
case Instruction::FDiv:
- case Instruction::SDiv: return bitc::BINOP_SDIV;
- case Instruction::URem: return bitc::BINOP_UREM;
+ case Instruction::SDiv: return naclbitc::BINOP_SDIV;
+ case Instruction::URem: return naclbitc::BINOP_UREM;
case Instruction::FRem:
- case Instruction::SRem: return bitc::BINOP_SREM;
- case Instruction::Shl: return bitc::BINOP_SHL;
- case Instruction::LShr: return bitc::BINOP_LSHR;
- case Instruction::AShr: return bitc::BINOP_ASHR;
- case Instruction::And: return bitc::BINOP_AND;
- case Instruction::Or: return bitc::BINOP_OR;
- case Instruction::Xor: return bitc::BINOP_XOR;
+ case Instruction::SRem: return naclbitc::BINOP_SREM;
+ case Instruction::Shl: return naclbitc::BINOP_SHL;
+ case Instruction::LShr: return naclbitc::BINOP_LSHR;
+ case Instruction::AShr: return naclbitc::BINOP_ASHR;
+ case Instruction::And: return naclbitc::BINOP_AND;
+ case Instruction::Or: return naclbitc::BINOP_OR;
+ case Instruction::Xor: return naclbitc::BINOP_XOR;
}
}
static unsigned GetEncodedRMWOperation(AtomicRMWInst::BinOp Op) {
switch (Op) {
default: llvm_unreachable("Unknown RMW operation!");
- case AtomicRMWInst::Xchg: return bitc::RMW_XCHG;
- case AtomicRMWInst::Add: return bitc::RMW_ADD;
- case AtomicRMWInst::Sub: return bitc::RMW_SUB;
- case AtomicRMWInst::And: return bitc::RMW_AND;
- case AtomicRMWInst::Nand: return bitc::RMW_NAND;
- case AtomicRMWInst::Or: return bitc::RMW_OR;
- case AtomicRMWInst::Xor: return bitc::RMW_XOR;
- case AtomicRMWInst::Max: return bitc::RMW_MAX;
- case AtomicRMWInst::Min: return bitc::RMW_MIN;
- case AtomicRMWInst::UMax: return bitc::RMW_UMAX;
- case AtomicRMWInst::UMin: return bitc::RMW_UMIN;
+ case AtomicRMWInst::Xchg: return naclbitc::RMW_XCHG;
+ case AtomicRMWInst::Add: return naclbitc::RMW_ADD;
+ case AtomicRMWInst::Sub: return naclbitc::RMW_SUB;
+ case AtomicRMWInst::And: return naclbitc::RMW_AND;
+ case AtomicRMWInst::Nand: return naclbitc::RMW_NAND;
+ case AtomicRMWInst::Or: return naclbitc::RMW_OR;
+ case AtomicRMWInst::Xor: return naclbitc::RMW_XOR;
+ case AtomicRMWInst::Max: return naclbitc::RMW_MAX;
+ case AtomicRMWInst::Min: return naclbitc::RMW_MIN;
+ case AtomicRMWInst::UMax: return naclbitc::RMW_UMAX;
+ case AtomicRMWInst::UMin: return naclbitc::RMW_UMIN;
}
}
static unsigned GetEncodedOrdering(AtomicOrdering Ordering) {
switch (Ordering) {
- case NotAtomic: return bitc::ORDERING_NOTATOMIC;
- case Unordered: return bitc::ORDERING_UNORDERED;
- case Monotonic: return bitc::ORDERING_MONOTONIC;
- case Acquire: return bitc::ORDERING_ACQUIRE;
- case Release: return bitc::ORDERING_RELEASE;
- case AcquireRelease: return bitc::ORDERING_ACQREL;
- case SequentiallyConsistent: return bitc::ORDERING_SEQCST;
+ case NotAtomic: return naclbitc::ORDERING_NOTATOMIC;
+ case Unordered: return naclbitc::ORDERING_UNORDERED;
+ case Monotonic: return naclbitc::ORDERING_MONOTONIC;
+ case Acquire: return naclbitc::ORDERING_ACQUIRE;
+ case Release: return naclbitc::ORDERING_RELEASE;
+ case AcquireRelease: return naclbitc::ORDERING_ACQREL;
+ case SequentiallyConsistent: return naclbitc::ORDERING_SEQCST;
}
llvm_unreachable("Invalid ordering");
}
static unsigned GetEncodedSynchScope(SynchronizationScope SynchScope) {
switch (SynchScope) {
- case SingleThread: return bitc::SYNCHSCOPE_SINGLETHREAD;
- case CrossThread: return bitc::SYNCHSCOPE_CROSSTHREAD;
+ case SingleThread: return naclbitc::SYNCHSCOPE_SINGLETHREAD;
+ case CrossThread: return naclbitc::SYNCHSCOPE_CROSSTHREAD;
}
llvm_unreachable("Invalid synch scope");
}
@@ -160,7 +160,7 @@ static void WriteAttributeGroupTable(const NaClValueEnumerator &VE,
const std::vector<AttributeSet> &AttrGrps = VE.getAttributeGroups();
if (AttrGrps.empty()) return;
- Stream.EnterSubblock(bitc::PARAMATTR_GROUP_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::PARAMATTR_GROUP_BLOCK_ID, 3);
SmallVector<uint64_t, 64> Record;
for (unsigned i = 0, e = AttrGrps.size(); i != e; ++i) {
@@ -195,7 +195,7 @@ static void WriteAttributeGroupTable(const NaClValueEnumerator &VE,
}
}
- Stream.EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record);
+ Stream.EmitRecord(naclbitc::PARAMATTR_GRP_CODE_ENTRY, Record);
Record.clear();
}
}
@@ -208,7 +208,7 @@ static void WriteAttributeTable(const NaClValueEnumerator &VE,
const std::vector<AttributeSet> &Attrs = VE.getAttributes();
if (Attrs.empty()) return;
- Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::PARAMATTR_BLOCK_ID, 3);
SmallVector<uint64_t, 64> Record;
for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
@@ -216,7 +216,7 @@ static void WriteAttributeTable(const NaClValueEnumerator &VE,
for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i)
Record.push_back(VE.getAttributeGroupID(A.getSlotAttributes(i)));
- Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
+ Stream.EmitRecord(naclbitc::PARAMATTR_CODE_ENTRY, Record);
Record.clear();
}
@@ -228,21 +228,21 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
NaClBitstreamWriter &Stream) {
const NaClValueEnumerator::TypeList &TypeList = VE.getTypes();
- Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */);
+ Stream.EnterSubblock(naclbitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */);
SmallVector<uint64_t, 64> TypeVals;
uint64_t NumBits = Log2_32_Ceil(VE.getTypes().size()+1);
// Abbrev for TYPE_CODE_POINTER.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::TYPE_CODE_POINTER));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits));
Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0
unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for TYPE_CODE_FUNCTION.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_FUNCTION));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::TYPE_CODE_FUNCTION));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isvararg
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits));
@@ -251,7 +251,7 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
// Abbrev for TYPE_CODE_STRUCT_ANON.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_ANON));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::TYPE_CODE_STRUCT_ANON));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits));
@@ -260,14 +260,14 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
// Abbrev for TYPE_CODE_STRUCT_NAME.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAME));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::TYPE_CODE_STRUCT_NAME));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for TYPE_CODE_STRUCT_NAMED.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAMED));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::TYPE_CODE_STRUCT_NAMED));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits));
@@ -276,7 +276,7 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
// Abbrev for TYPE_CODE_ARRAY.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::TYPE_CODE_ARRAY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits));
@@ -284,7 +284,7 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
// Emit an entry count so the reader can reserve space.
TypeVals.push_back(TypeList.size());
- Stream.EmitRecord(bitc::TYPE_CODE_NUMENTRY, TypeVals);
+ Stream.EmitRecord(naclbitc::TYPE_CODE_NUMENTRY, TypeVals);
TypeVals.clear();
// Loop over all of the types, emitting each in turn.
@@ -295,25 +295,25 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
switch (T->getTypeID()) {
default: llvm_unreachable("Unknown type!");
- case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
- case Type::HalfTyID: Code = bitc::TYPE_CODE_HALF; break;
- case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
- case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
- case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
- case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
- case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
- case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
- case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
- case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
+ case Type::VoidTyID: Code = naclbitc::TYPE_CODE_VOID; break;
+ case Type::HalfTyID: Code = naclbitc::TYPE_CODE_HALF; break;
+ case Type::FloatTyID: Code = naclbitc::TYPE_CODE_FLOAT; break;
+ case Type::DoubleTyID: Code = naclbitc::TYPE_CODE_DOUBLE; break;
+ case Type::X86_FP80TyID: Code = naclbitc::TYPE_CODE_X86_FP80; break;
+ case Type::FP128TyID: Code = naclbitc::TYPE_CODE_FP128; break;
+ case Type::PPC_FP128TyID: Code = naclbitc::TYPE_CODE_PPC_FP128; break;
+ case Type::LabelTyID: Code = naclbitc::TYPE_CODE_LABEL; break;
+ case Type::MetadataTyID: Code = naclbitc::TYPE_CODE_METADATA; break;
+ case Type::X86_MMXTyID: Code = naclbitc::TYPE_CODE_X86_MMX; break;
case Type::IntegerTyID:
// INTEGER: [width]
- Code = bitc::TYPE_CODE_INTEGER;
+ Code = naclbitc::TYPE_CODE_INTEGER;
TypeVals.push_back(cast<IntegerType>(T)->getBitWidth());
break;
case Type::PointerTyID: {
PointerType *PTy = cast<PointerType>(T);
// POINTER: [pointee type, address space]
- Code = bitc::TYPE_CODE_POINTER;
+ Code = naclbitc::TYPE_CODE_POINTER;
TypeVals.push_back(VE.getTypeID(PTy->getElementType()));
unsigned AddressSpace = PTy->getAddressSpace();
TypeVals.push_back(AddressSpace);
@@ -323,7 +323,7 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
case Type::FunctionTyID: {
FunctionType *FT = cast<FunctionType>(T);
// FUNCTION: [isvararg, retty, paramty x N]
- Code = bitc::TYPE_CODE_FUNCTION;
+ Code = naclbitc::TYPE_CODE_FUNCTION;
TypeVals.push_back(FT->isVarArg());
TypeVals.push_back(VE.getTypeID(FT->getReturnType()));
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
@@ -341,19 +341,19 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
TypeVals.push_back(VE.getTypeID(*I));
if (ST->isLiteral()) {
- Code = bitc::TYPE_CODE_STRUCT_ANON;
+ Code = naclbitc::TYPE_CODE_STRUCT_ANON;
AbbrevToUse = StructAnonAbbrev;
} else {
if (ST->isOpaque()) {
- Code = bitc::TYPE_CODE_OPAQUE;
+ Code = naclbitc::TYPE_CODE_OPAQUE;
} else {
- Code = bitc::TYPE_CODE_STRUCT_NAMED;
+ Code = naclbitc::TYPE_CODE_STRUCT_NAMED;
AbbrevToUse = StructNamedAbbrev;
}
// Emit the name if it is present.
if (!ST->getName().empty())
- WriteStringRecord(bitc::TYPE_CODE_STRUCT_NAME, ST->getName(),
+ WriteStringRecord(naclbitc::TYPE_CODE_STRUCT_NAME, ST->getName(),
StructNameAbbrev, Stream);
}
break;
@@ -361,7 +361,7 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
case Type::ArrayTyID: {
ArrayType *AT = cast<ArrayType>(T);
// ARRAY: [numelts, eltty]
- Code = bitc::TYPE_CODE_ARRAY;
+ Code = naclbitc::TYPE_CODE_ARRAY;
TypeVals.push_back(AT->getNumElements());
TypeVals.push_back(VE.getTypeID(AT->getElementType()));
AbbrevToUse = ArrayAbbrev;
@@ -370,7 +370,7 @@ static void WriteTypeTable(const NaClValueEnumerator &VE,
case Type::VectorTyID: {
VectorType *VT = cast<VectorType>(T);
// VECTOR [numelts, eltty]
- Code = bitc::TYPE_CODE_VECTOR;
+ Code = naclbitc::TYPE_CODE_VECTOR;
TypeVals.push_back(VT->getNumElements());
TypeVals.push_back(VE.getTypeID(VT->getElementType()));
break;
@@ -433,13 +433,13 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
NaClBitstreamWriter &Stream) {
// Emit various pieces of data attached to a module.
if (!M->getTargetTriple().empty())
- WriteStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(),
+ WriteStringRecord(naclbitc::MODULE_CODE_TRIPLE, M->getTargetTriple(),
0/*TODO*/, Stream);
if (!M->getDataLayout().empty())
- WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, M->getDataLayout(),
+ WriteStringRecord(naclbitc::MODULE_CODE_DATALAYOUT, M->getDataLayout(),
0/*TODO*/, Stream);
if (!M->getModuleInlineAsm().empty())
- WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(),
+ WriteStringRecord(naclbitc::MODULE_CODE_ASM, M->getModuleInlineAsm(),
0/*TODO*/, Stream);
// Emit information about sections and GC, computing how many there are. Also
@@ -456,7 +456,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
// Give section names unique ID's.
unsigned &Entry = SectionMap[GV->getSection()];
if (!Entry) {
- WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(),
+ WriteStringRecord(naclbitc::MODULE_CODE_SECTIONNAME, GV->getSection(),
0/*TODO*/, Stream);
Entry = SectionMap.size();
}
@@ -468,7 +468,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
// Give section names unique ID's.
unsigned &Entry = SectionMap[F->getSection()];
if (!Entry) {
- WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(),
+ WriteStringRecord(naclbitc::MODULE_CODE_SECTIONNAME, F->getSection(),
0/*TODO*/, Stream);
Entry = SectionMap.size();
}
@@ -477,7 +477,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
// Same for GC names.
unsigned &Entry = GCMap[F->getGC()];
if (!Entry) {
- WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(),
+ WriteStringRecord(naclbitc::MODULE_CODE_GCNAME, F->getGC(),
0/*TODO*/, Stream);
Entry = GCMap.size();
}
@@ -489,7 +489,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
if (!M->global_empty()) {
// Add an abbrev for common globals with no visibility or thread localness.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::MODULE_CODE_GLOBALVAR));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(MaxGlobalType+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant.
@@ -538,7 +538,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
AbbrevToUse = SimpleGVarAbbrev;
}
- Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse);
+ Stream.EmitRecord(naclbitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse);
Vals.clear();
}
@@ -558,7 +558,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
Vals.push_back(F->hasUnnamedAddr());
unsigned AbbrevToUse = 0;
- Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
+ Stream.EmitRecord(naclbitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
Vals.clear();
}
@@ -571,7 +571,7 @@ static void WriteModuleInfo(const Module *M, const NaClValueEnumerator &VE,
Vals.push_back(getEncodedLinkage(AI));
Vals.push_back(getEncodedVisibility(AI));
unsigned AbbrevToUse = 0;
- Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
+ Stream.EmitRecord(naclbitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
Vals.clear();
}
}
@@ -582,13 +582,13 @@ static uint64_t GetOptimizationFlags(const Value *V) {
if (const OverflowingBinaryOperator *OBO =
dyn_cast<OverflowingBinaryOperator>(V)) {
if (OBO->hasNoSignedWrap())
- Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP;
+ Flags |= 1 << naclbitc::OBO_NO_SIGNED_WRAP;
if (OBO->hasNoUnsignedWrap())
- Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP;
+ Flags |= 1 << naclbitc::OBO_NO_UNSIGNED_WRAP;
} else if (const PossiblyExactOperator *PEO =
dyn_cast<PossiblyExactOperator>(V)) {
if (PEO->isExact())
- Flags |= 1 << bitc::PEO_EXACT;
+ Flags |= 1 << naclbitc::PEO_EXACT;
} else if (const FPMathOperator *FPMO =
dyn_cast<const FPMathOperator>(V)) {
if (FPMO->hasUnsafeAlgebra())
@@ -619,8 +619,8 @@ static void WriteMDNode(const MDNode *N,
Record.push_back(0);
}
}
- unsigned MDCode = N->isFunctionLocal() ? bitc::METADATA_FN_NODE :
- bitc::METADATA_NODE;
+ unsigned MDCode = N->isFunctionLocal() ? naclbitc::METADATA_FN_NODE :
+ naclbitc::METADATA_NODE;
Stream.EmitRecord(MDCode, Record, 0);
Record.clear();
}
@@ -637,18 +637,18 @@ static void WriteModuleMetadata(const Module *M,
if (const MDNode *N = dyn_cast<MDNode>(Vals[i].first)) {
if (!N->isFunctionLocal() || !N->getFunction()) {
if (!StartedMetadataBlock) {
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::METADATA_BLOCK_ID, 3);
StartedMetadataBlock = true;
}
WriteMDNode(N, VE, Stream, Record);
}
} else if (const MDString *MDS = dyn_cast<MDString>(Vals[i].first)) {
if (!StartedMetadataBlock) {
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::METADATA_BLOCK_ID, 3);
// Abbrev for METADATA_STRING.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::METADATA_STRING));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
MDSAbbrev = Stream.EmitAbbrev(Abbv);
@@ -659,7 +659,7 @@ static void WriteModuleMetadata(const Module *M,
Record.append(MDS->begin(), MDS->end());
// Emit the finished record.
- Stream.EmitRecord(bitc::METADATA_STRING, Record, MDSAbbrev);
+ Stream.EmitRecord(naclbitc::METADATA_STRING, Record, MDSAbbrev);
Record.clear();
}
}
@@ -669,7 +669,7 @@ static void WriteModuleMetadata(const Module *M,
E = M->named_metadata_end(); I != E; ++I) {
const NamedMDNode *NMD = I;
if (!StartedMetadataBlock) {
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::METADATA_BLOCK_ID, 3);
StartedMetadataBlock = true;
}
@@ -677,13 +677,13 @@ static void WriteModuleMetadata(const Module *M,
StringRef Str = NMD->getName();
for (unsigned i = 0, e = Str.size(); i != e; ++i)
Record.push_back(Str[i]);
- Stream.EmitRecord(bitc::METADATA_NAME, Record, 0/*TODO*/);
+ Stream.EmitRecord(naclbitc::METADATA_NAME, Record, 0/*TODO*/);
Record.clear();
// Write named metadata operands.
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
Record.push_back(VE.getValueID(NMD->getOperand(i)));
- Stream.EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0);
+ Stream.EmitRecord(naclbitc::METADATA_NAMED_NODE, Record, 0);
Record.clear();
}
@@ -701,7 +701,7 @@ static void WriteFunctionLocalMetadata(const Function &F,
if (const MDNode *N = Vals[i])
if (N->isFunctionLocal() && N->getFunction() == &F) {
if (!StartedMetadataBlock) {
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::METADATA_BLOCK_ID, 3);
StartedMetadataBlock = true;
}
WriteMDNode(N, VE, Stream, Record);
@@ -714,7 +714,7 @@ static void WriteFunctionLocalMetadata(const Function &F,
static void WriteMetadataAttachment(const Function &F,
const NaClValueEnumerator &VE,
NaClBitstreamWriter &Stream) {
- Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3);
+ Stream.EnterSubblock(naclbitc::METADATA_ATTACHMENT_ID, 3);
SmallVector<uint64_t, 64> Record;
@@ -737,7 +737,7 @@ static void WriteMetadataAttachment(const Function &F,
Record.push_back(MDs[i].first);
Record.push_back(VE.getValueID(MDs[i].second));
}
- Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
+ Stream.EmitRecord(naclbitc::METADATA_ATTACHMENT, Record, 0);
Record.clear();
}
@@ -754,14 +754,14 @@ static void WriteModuleMetadataStore(const Module *M, NaClBitstreamWriter &Strea
if (Names.empty()) return;
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::METADATA_BLOCK_ID, 3);
for (unsigned MDKindID = 0, e = Names.size(); MDKindID != e; ++MDKindID) {
Record.push_back(MDKindID);
StringRef KName = Names[MDKindID];
Record.append(KName.begin(), KName.end());
- Stream.EmitRecord(bitc::METADATA_KIND, Record, 0);
+ Stream.EmitRecord(naclbitc::METADATA_KIND, Record, 0);
Record.clear();
}
@@ -782,7 +782,7 @@ static void EmitAPInt(SmallVectorImpl<uint64_t> &Vals,
if (Val.getBitWidth() <= 64) {
uint64_t V = Val.getSExtValue();
emitSignedInt64(Vals, V);
- Code = bitc::CST_CODE_INTEGER;
+ Code = naclbitc::CST_CODE_INTEGER;
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
} else {
// Wide integers, > 64 bits in size.
@@ -799,7 +799,7 @@ static void EmitAPInt(SmallVectorImpl<uint64_t> &Vals,
for (unsigned i = 0; i != NWords; ++i) {
emitSignedInt64(Vals, RawWords[i]);
}
- Code = bitc::CST_CODE_WIDE_INTEGER;
+ Code = naclbitc::CST_CODE_WIDE_INTEGER;
}
}
@@ -808,7 +808,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
NaClBitstreamWriter &Stream, bool isGlobal) {
if (FirstVal == LastVal) return;
- Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 4);
+ Stream.EnterSubblock(naclbitc::CONSTANTS_BLOCK_ID, 4);
unsigned AggregateAbbrev = 0;
unsigned String8Abbrev = 0;
@@ -818,26 +818,26 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
if (isGlobal) {
// Abbrev for CST_CODE_AGGREGATE.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_AGGREGATE));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_AGGREGATE));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(LastVal+1)));
AggregateAbbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for CST_CODE_STRING.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_STRING));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
String8Abbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for CST_CODE_CSTRING.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_CSTRING));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
CString7Abbrev = Stream.EmitAbbrev(Abbv);
// Abbrev for CST_CODE_CSTRING.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_CSTRING));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
CString6Abbrev = Stream.EmitAbbrev(Abbv);
@@ -853,7 +853,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
if (V->getType() != LastTy) {
LastTy = V->getType();
Record.push_back(VE.getTypeID(LastTy));
- Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record,
+ Stream.EmitRecord(naclbitc::CST_CODE_SETTYPE, Record,
CONSTANTS_SETTYPE_ABBREV);
Record.clear();
}
@@ -874,7 +874,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
Record.push_back(ConstraintStr.size());
for (unsigned i = 0, e = ConstraintStr.size(); i != e; ++i)
Record.push_back(ConstraintStr[i]);
- Stream.EmitRecord(bitc::CST_CODE_INLINEASM, Record);
+ Stream.EmitRecord(naclbitc::CST_CODE_INLINEASM, Record);
Record.clear();
continue;
}
@@ -882,13 +882,13 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
unsigned Code = -1U;
unsigned AbbrevToUse = 0;
if (C->isNullValue()) {
- Code = bitc::CST_CODE_NULL;
+ Code = naclbitc::CST_CODE_NULL;
} else if (isa<UndefValue>(C)) {
- Code = bitc::CST_CODE_UNDEF;
+ Code = naclbitc::CST_CODE_UNDEF;
} else if (const ConstantInt *IV = dyn_cast<ConstantInt>(C)) {
EmitAPInt(Record, Code, AbbrevToUse, IV->getValue());
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
- Code = bitc::CST_CODE_FLOAT;
+ Code = naclbitc::CST_CODE_FLOAT;
Type *Ty = CFP->getType();
if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy()) {
Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
@@ -914,14 +914,14 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
unsigned NumElts = Str->getNumElements();
// If this is a null-terminated string, use the denser CSTRING encoding.
if (Str->isCString()) {
- Code = bitc::CST_CODE_CSTRING;
+ Code = naclbitc::CST_CODE_CSTRING;
--NumElts; // Don't encode the null, which isn't allowed by char6.
} else {
- Code = bitc::CST_CODE_STRING;
+ Code = naclbitc::CST_CODE_STRING;
AbbrevToUse = String8Abbrev;
}
- bool isCStr7 = Code == bitc::CST_CODE_CSTRING;
- bool isCStrChar6 = Code == bitc::CST_CODE_CSTRING;
+ bool isCStr7 = Code == naclbitc::CST_CODE_CSTRING;
+ bool isCStrChar6 = Code == naclbitc::CST_CODE_CSTRING;
for (unsigned i = 0; i != NumElts; ++i) {
unsigned char V = Str->getElementAsInteger(i);
Record.push_back(V);
@@ -936,7 +936,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
AbbrevToUse = CString7Abbrev;
} else if (const ConstantDataSequential *CDS =
dyn_cast<ConstantDataSequential>(C)) {
- Code = bitc::CST_CODE_DATA;
+ Code = naclbitc::CST_CODE_DATA;
Type *EltTy = CDS->getType()->getElementType();
if (isa<IntegerType>(EltTy)) {
for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i)
@@ -957,7 +957,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
}
} else if (isa<ConstantArray>(C) || isa<ConstantStruct>(C) ||
isa<ConstantVector>(C)) {
- Code = bitc::CST_CODE_AGGREGATE;
+ Code = naclbitc::CST_CODE_AGGREGATE;
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
Record.push_back(VE.getValueID(C->getOperand(i)));
AbbrevToUse = AggregateAbbrev;
@@ -965,14 +965,14 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
switch (CE->getOpcode()) {
default:
if (Instruction::isCast(CE->getOpcode())) {
- Code = bitc::CST_CODE_CE_CAST;
+ Code = naclbitc::CST_CODE_CE_CAST;
Record.push_back(GetEncodedCastOpcode(CE->getOpcode()));
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getValueID(C->getOperand(0)));
AbbrevToUse = CONSTANTS_CE_CAST_Abbrev;
} else {
assert(CE->getNumOperands() == 2 && "Unknown constant expr!");
- Code = bitc::CST_CODE_CE_BINOP;
+ Code = naclbitc::CST_CODE_CE_BINOP;
Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode()));
Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(1)));
@@ -982,28 +982,28 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
}
break;
case Instruction::GetElementPtr:
- Code = bitc::CST_CODE_CE_GEP;
+ Code = naclbitc::CST_CODE_CE_GEP;
if (cast<GEPOperator>(C)->isInBounds())
- Code = bitc::CST_CODE_CE_INBOUNDS_GEP;
+ Code = naclbitc::CST_CODE_CE_INBOUNDS_GEP;
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
Record.push_back(VE.getValueID(C->getOperand(i)));
}
break;
case Instruction::Select:
- Code = bitc::CST_CODE_CE_SELECT;
+ Code = naclbitc::CST_CODE_CE_SELECT;
Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(1)));
Record.push_back(VE.getValueID(C->getOperand(2)));
break;
case Instruction::ExtractElement:
- Code = bitc::CST_CODE_CE_EXTRACTELT;
+ Code = naclbitc::CST_CODE_CE_EXTRACTELT;
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(1)));
break;
case Instruction::InsertElement:
- Code = bitc::CST_CODE_CE_INSERTELT;
+ Code = naclbitc::CST_CODE_CE_INSERTELT;
Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(1)));
Record.push_back(VE.getValueID(C->getOperand(2)));
@@ -1014,9 +1014,9 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
// then the shuffle is widening or truncating the input vectors, and
// the argument type must also be encoded.
if (C->getType() == C->getOperand(0)->getType()) {
- Code = bitc::CST_CODE_CE_SHUFFLEVEC;
+ Code = naclbitc::CST_CODE_CE_SHUFFLEVEC;
} else {
- Code = bitc::CST_CODE_CE_SHUFVEC_EX;
+ Code = naclbitc::CST_CODE_CE_SHUFVEC_EX;
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
}
Record.push_back(VE.getValueID(C->getOperand(0)));
@@ -1025,7 +1025,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
break;
case Instruction::ICmp:
case Instruction::FCmp:
- Code = bitc::CST_CODE_CE_CMP;
+ Code = naclbitc::CST_CODE_CE_CMP;
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(1)));
@@ -1033,7 +1033,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
break;
}
} else if (const BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
- Code = bitc::CST_CODE_BLOCKADDRESS;
+ Code = naclbitc::CST_CODE_BLOCKADDRESS;
Record.push_back(VE.getTypeID(BA->getFunction()->getType()));
Record.push_back(VE.getValueID(BA->getFunction()));
Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock()));
@@ -1119,14 +1119,14 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
switch (I.getOpcode()) {
default:
if (Instruction::isCast(I.getOpcode())) {
- Code = bitc::FUNC_CODE_INST_CAST;
+ Code = naclbitc::FUNC_CODE_INST_CAST;
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))
AbbrevToUse = FUNCTION_INST_CAST_ABBREV;
Vals.push_back(VE.getTypeID(I.getType()));
Vals.push_back(GetEncodedCastOpcode(I.getOpcode()));
} else {
assert(isa<BinaryOperator>(I) && "Unknown instruction!");
- Code = bitc::FUNC_CODE_INST_BINOP;
+ Code = naclbitc::FUNC_CODE_INST_BINOP;
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))
AbbrevToUse = FUNCTION_INST_BINOP_ABBREV;
pushValue(I.getOperand(1), InstID, Vals, VE);
@@ -1141,14 +1141,14 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
case Instruction::GetElementPtr:
- Code = bitc::FUNC_CODE_INST_GEP;
+ Code = naclbitc::FUNC_CODE_INST_GEP;
if (cast<GEPOperator>(&I)->isInBounds())
- Code = bitc::FUNC_CODE_INST_INBOUNDS_GEP;
+ Code = naclbitc::FUNC_CODE_INST_INBOUNDS_GEP;
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
PushValueAndType(I.getOperand(i), InstID, Vals, VE);
break;
case Instruction::ExtractValue: {
- Code = bitc::FUNC_CODE_INST_EXTRACTVAL;
+ Code = naclbitc::FUNC_CODE_INST_EXTRACTVAL;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
const ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i)
@@ -1156,7 +1156,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
}
case Instruction::InsertValue: {
- Code = bitc::FUNC_CODE_INST_INSERTVAL;
+ Code = naclbitc::FUNC_CODE_INST_INSERTVAL;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
PushValueAndType(I.getOperand(1), InstID, Vals, VE);
const InsertValueInst *IVI = cast<InsertValueInst>(&I);
@@ -1165,24 +1165,24 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
}
case Instruction::Select:
- Code = bitc::FUNC_CODE_INST_VSELECT;
+ Code = naclbitc::FUNC_CODE_INST_VSELECT;
PushValueAndType(I.getOperand(1), InstID, Vals, VE);
pushValue(I.getOperand(2), InstID, Vals, VE);
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
break;
case Instruction::ExtractElement:
- Code = bitc::FUNC_CODE_INST_EXTRACTELT;
+ Code = naclbitc::FUNC_CODE_INST_EXTRACTELT;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
pushValue(I.getOperand(1), InstID, Vals, VE);
break;
case Instruction::InsertElement:
- Code = bitc::FUNC_CODE_INST_INSERTELT;
+ Code = naclbitc::FUNC_CODE_INST_INSERTELT;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
pushValue(I.getOperand(1), InstID, Vals, VE);
pushValue(I.getOperand(2), InstID, Vals, VE);
break;
case Instruction::ShuffleVector:
- Code = bitc::FUNC_CODE_INST_SHUFFLEVEC;
+ Code = naclbitc::FUNC_CODE_INST_SHUFFLEVEC;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
pushValue(I.getOperand(1), InstID, Vals, VE);
pushValue(I.getOperand(2), InstID, Vals, VE);
@@ -1190,7 +1190,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::ICmp:
case Instruction::FCmp:
// compare returning Int1Ty or vector of Int1Ty
- Code = bitc::FUNC_CODE_INST_CMP2;
+ Code = naclbitc::FUNC_CODE_INST_CMP2;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
pushValue(I.getOperand(1), InstID, Vals, VE);
Vals.push_back(cast<CmpInst>(I).getPredicate());
@@ -1198,7 +1198,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::Ret:
{
- Code = bitc::FUNC_CODE_INST_RET;
+ Code = naclbitc::FUNC_CODE_INST_RET;
unsigned NumOperands = I.getNumOperands();
if (NumOperands == 0)
AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV;
@@ -1213,7 +1213,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
case Instruction::Br:
{
- Code = bitc::FUNC_CODE_INST_BR;
+ Code = naclbitc::FUNC_CODE_INST_BR;
const BranchInst &II = cast<BranchInst>(I);
Vals.push_back(VE.getValueID(II.getSuccessor(0)));
if (II.isConditional()) {
@@ -1228,7 +1228,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
// explicitly to store large APInt numbers.
SmallVector<uint64_t, 128> Vals64;
- Code = bitc::FUNC_CODE_INST_SWITCH;
+ Code = naclbitc::FUNC_CODE_INST_SWITCH;
const SwitchInst &SI = cast<SwitchInst>(I);
uint32_t SwitchRecordHeader = SI.hash() | (SWITCH_INST_MAGIC << 16);
@@ -1284,7 +1284,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
}
break;
case Instruction::IndirectBr:
- Code = bitc::FUNC_CODE_INST_INDIRECTBR;
+ Code = naclbitc::FUNC_CODE_INST_INDIRECTBR;
Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
// Encode the address operand as relative, but not the basic blocks.
pushValue(I.getOperand(0), InstID, Vals, VE);
@@ -1297,7 +1297,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
const Value *Callee(II->getCalledValue());
PointerType *PTy = cast<PointerType>(Callee->getType());
FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
- Code = bitc::FUNC_CODE_INST_INVOKE;
+ Code = naclbitc::FUNC_CODE_INST_INVOKE;
Vals.push_back(VE.getAttributeID(II->getAttributes()));
Vals.push_back(II->getCallingConv());
@@ -1318,17 +1318,17 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
}
case Instruction::Resume:
- Code = bitc::FUNC_CODE_INST_RESUME;
+ Code = naclbitc::FUNC_CODE_INST_RESUME;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
break;
case Instruction::Unreachable:
- Code = bitc::FUNC_CODE_INST_UNREACHABLE;
+ Code = naclbitc::FUNC_CODE_INST_UNREACHABLE;
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
break;
case Instruction::PHI: {
const PHINode &PN = cast<PHINode>(I);
- Code = bitc::FUNC_CODE_INST_PHI;
+ Code = naclbitc::FUNC_CODE_INST_PHI;
// With the newer instruction encoding, forward references could give
// negative valued IDs. This is most common for PHIs, so we use
// signed VBRs.
@@ -1346,7 +1346,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::LandingPad: {
const LandingPadInst &LP = cast<LandingPadInst>(I);
- Code = bitc::FUNC_CODE_INST_LANDINGPAD;
+ Code = naclbitc::FUNC_CODE_INST_LANDINGPAD;
Vals.push_back(VE.getTypeID(LP.getType()));
PushValueAndType(LP.getPersonalityFn(), InstID, Vals, VE);
Vals.push_back(LP.isCleanup());
@@ -1362,7 +1362,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
}
case Instruction::Alloca:
- Code = bitc::FUNC_CODE_INST_ALLOCA;
+ Code = naclbitc::FUNC_CODE_INST_ALLOCA;
Vals.push_back(VE.getTypeID(I.getType()));
Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
Vals.push_back(VE.getValueID(I.getOperand(0))); // size.
@@ -1371,10 +1371,10 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::Load:
if (cast<LoadInst>(I).isAtomic()) {
- Code = bitc::FUNC_CODE_INST_LOADATOMIC;
+ Code = naclbitc::FUNC_CODE_INST_LOADATOMIC;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
} else {
- Code = bitc::FUNC_CODE_INST_LOAD;
+ Code = naclbitc::FUNC_CODE_INST_LOAD;
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr
AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
}
@@ -1387,9 +1387,9 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
case Instruction::Store:
if (cast<StoreInst>(I).isAtomic())
- Code = bitc::FUNC_CODE_INST_STOREATOMIC;
+ Code = naclbitc::FUNC_CODE_INST_STOREATOMIC;
else
- Code = bitc::FUNC_CODE_INST_STORE;
+ Code = naclbitc::FUNC_CODE_INST_STORE;
PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr
pushValue(I.getOperand(0), InstID, Vals, VE); // val.
Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1);
@@ -1400,7 +1400,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
}
break;
case Instruction::AtomicCmpXchg:
- Code = bitc::FUNC_CODE_INST_CMPXCHG;
+ Code = naclbitc::FUNC_CODE_INST_CMPXCHG;
PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr
pushValue(I.getOperand(1), InstID, Vals, VE); // cmp.
pushValue(I.getOperand(2), InstID, Vals, VE); // newval.
@@ -1411,7 +1411,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
cast<AtomicCmpXchgInst>(I).getSynchScope()));
break;
case Instruction::AtomicRMW:
- Code = bitc::FUNC_CODE_INST_ATOMICRMW;
+ Code = naclbitc::FUNC_CODE_INST_ATOMICRMW;
PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr
pushValue(I.getOperand(1), InstID, Vals, VE); // val.
Vals.push_back(GetEncodedRMWOperation(
@@ -1422,7 +1422,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
cast<AtomicRMWInst>(I).getSynchScope()));
break;
case Instruction::Fence:
- Code = bitc::FUNC_CODE_INST_FENCE;
+ Code = naclbitc::FUNC_CODE_INST_FENCE;
Vals.push_back(GetEncodedOrdering(cast<FenceInst>(I).getOrdering()));
Vals.push_back(GetEncodedSynchScope(cast<FenceInst>(I).getSynchScope()));
break;
@@ -1431,7 +1431,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
PointerType *PTy = cast<PointerType>(CI.getCalledValue()->getType());
FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
- Code = bitc::FUNC_CODE_INST_CALL;
+ Code = naclbitc::FUNC_CODE_INST_CALL;
Vals.push_back(VE.getAttributeID(CI.getAttributes()));
Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()));
@@ -1455,7 +1455,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
break;
}
case Instruction::VAArg:
- Code = bitc::FUNC_CODE_INST_VAARG;
+ Code = naclbitc::FUNC_CODE_INST_VAARG;
Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty
pushValue(I.getOperand(0), InstID, Vals, VE); // valist.
Vals.push_back(VE.getTypeID(I.getType())); // restype.
@@ -1471,7 +1471,7 @@ static void WriteValueSymbolTable(const ValueSymbolTable &VST,
const NaClValueEnumerator &VE,
NaClBitstreamWriter &Stream) {
if (VST.empty()) return;
- Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
+ Stream.EnterSubblock(naclbitc::VALUE_SYMTAB_BLOCK_ID, 4);
// FIXME: Set up the abbrev, we know how many values there are!
// FIXME: We know if the type names can use 7-bit ascii.
@@ -1501,11 +1501,11 @@ static void WriteValueSymbolTable(const ValueSymbolTable &VST,
// VST_BBENTRY: [bbid, namechar x N]
unsigned Code;
if (isa<BasicBlock>(SI->getValue())) {
- Code = bitc::VST_CODE_BBENTRY;
+ Code = naclbitc::VST_CODE_BBENTRY;
if (isChar6)
AbbrevToUse = VST_BBENTRY_6_ABBREV;
} else {
- Code = bitc::VST_CODE_ENTRY;
+ Code = naclbitc::VST_CODE_ENTRY;
if (isChar6)
AbbrevToUse = VST_ENTRY_6_ABBREV;
else if (is7Bit)
@@ -1527,7 +1527,7 @@ static void WriteValueSymbolTable(const ValueSymbolTable &VST,
/// WriteFunction - Emit a function body to the module stream.
static void WriteFunction(const Function &F, NaClValueEnumerator &VE,
NaClBitstreamWriter &Stream) {
- Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4);
+ Stream.EnterSubblock(naclbitc::FUNCTION_BLOCK_ID, 4);
VE.incorporateFunction(F);
SmallVector<unsigned, 64> Vals;
@@ -1535,7 +1535,7 @@ static void WriteFunction(const Function &F, NaClValueEnumerator &VE,
// Emit the number of basic blocks, so the reader can create them ahead of
// time.
Vals.push_back(VE.getBasicBlocks().size());
- Stream.EmitRecord(bitc::FUNC_CODE_DECLAREBLOCKS, Vals);
+ Stream.EmitRecord(naclbitc::FUNC_CODE_DECLAREBLOCKS, Vals);
Vals.clear();
// If there are function-local constants, emit them now.
@@ -1571,7 +1571,7 @@ static void WriteFunction(const Function &F, NaClValueEnumerator &VE,
// nothing todo.
} else if (DL == LastDL) {
// Just repeat the same debug loc as last time.
- Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals);
+ Stream.EmitRecord(naclbitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals);
} else {
MDNode *Scope, *IA;
DL.getScopeAndInlinedAt(Scope, IA, I->getContext());
@@ -1580,7 +1580,7 @@ static void WriteFunction(const Function &F, NaClValueEnumerator &VE,
Vals.push_back(DL.getCol());
Vals.push_back(Scope ? VE.getValueID(Scope)+1 : 0);
Vals.push_back(IA ? VE.getValueID(IA)+1 : 0);
- Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals);
+ Stream.EmitRecord(naclbitc::FUNC_CODE_DEBUG_LOC, Vals);
Vals.clear();
LastDL = DL;
@@ -1609,38 +1609,38 @@ static void WriteBlockInfo(const NaClValueEnumerator &VE, NaClBitstreamWriter &S
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
- if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID,
Abbv) != VST_ENTRY_8_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // 7-bit fixed width VST_ENTRY strings.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::VST_CODE_ENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
- if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID,
Abbv) != VST_ENTRY_7_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // 6-bit char6 VST_ENTRY strings.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::VST_CODE_ENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
- if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID,
Abbv) != VST_ENTRY_6_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // 6-bit char6 VST_BBENTRY strings.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::VST_CODE_BBENTRY));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
- if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::VALUE_SYMTAB_BLOCK_ID,
Abbv) != VST_BBENTRY_6_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
@@ -1649,39 +1649,39 @@ static void WriteBlockInfo(const NaClValueEnumerator &VE, NaClBitstreamWriter &S
{ // SETTYPE abbrev for CONSTANTS_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_SETTYPE));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
- if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID,
Abbv) != CONSTANTS_SETTYPE_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INTEGER abbrev for CONSTANTS_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_INTEGER));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
- if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID,
Abbv) != CONSTANTS_INTEGER_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // CE_CAST abbrev for CONSTANTS_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_CE_CAST));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid
Log2_32_Ceil(VE.getTypes().size()+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
- if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID,
Abbv) != CONSTANTS_CE_CAST_Abbrev)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // NULL abbrev for CONSTANTS_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL));
- if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::CST_CODE_NULL));
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::CONSTANTS_BLOCK_ID,
Abbv) != CONSTANTS_NULL_Abbrev)
llvm_unreachable("Unexpected abbrev ordering!");
}
@@ -1690,66 +1690,66 @@ static void WriteBlockInfo(const NaClValueEnumerator &VE, NaClBitstreamWriter &S
{ // INST_LOAD abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_LOAD));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_LOAD_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INST_BINOP abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_BINOP));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_BINOP_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_BINOP));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INST_CAST abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_CAST));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty
Log2_32_Ceil(VE.getTypes().size()+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_CAST_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INST_RET abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET));
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_RET));
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_RET_VOID_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INST_RET abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET));
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_RET));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_RET_VAL_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
{ // INST_UNREACHABLE abbrev for FUNCTION_BLOCK.
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE));
- if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
+ Abbv->Add(BitCodeAbbrevOp(naclbitc::FUNC_CODE_INST_UNREACHABLE));
+ if (Stream.EmitBlockInfoAbbrev(naclbitc::FUNCTION_BLOCK_ID,
Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV)
llvm_unreachable("Unexpected abbrev ordering!");
}
@@ -1759,12 +1759,12 @@ static void WriteBlockInfo(const NaClValueEnumerator &VE, NaClBitstreamWriter &S
/// WriteModule - Emit the specified module to the bitstream.
static void WriteModule(const Module *M, NaClBitstreamWriter &Stream) {
- Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
+ Stream.EnterSubblock(naclbitc::MODULE_BLOCK_ID, 3);
SmallVector<unsigned, 1> Vals;
unsigned CurVersion = 1;
Vals.push_back(CurVersion);
- Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
+ Stream.EmitRecord(naclbitc::MODULE_CODE_VERSION, Vals);
// Analyze the module, enumerating globals, functions, etc.
NaClValueEnumerator VE(M);
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index dd30c77a5d..7e32507e91 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -44,6 +44,7 @@ add_subdirectory(llvm-mcmarkup)
add_subdirectory(llvm-symbolizer)
add_subdirectory(pnacl-abicheck)
add_subdirectory(pnacl-freeze)
+add_subdirectory(pnacl-thaw)
add_subdirectory(bc-wrap)
if( NOT WIN32 )
diff --git a/tools/Makefile b/tools/Makefile
index 5a51ba8948..f46e3b5fac 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -35,7 +35,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \
llvm-diff macho-dump llvm-objdump llvm-readobj \
llvm-rtdyld llvm-dwarfdump llvm-cov \
llvm-size llvm-stress llvm-mcmarkup bc-wrap pso-stub \
- llvm-symbolizer pnacl-abicheck pnacl-freeze
+ llvm-symbolizer pnacl-abicheck pnacl-freeze pnacl-thaw
# If Intel JIT Events support is configured, build an extra tool to test it.
ifeq ($(USE_INTEL_JITEVENTS), 1)
diff --git a/tools/pnacl-thaw/CMakeLists.txt b/tools/pnacl-thaw/CMakeLists.txt
new file mode 100644
index 0000000000..91b818efe6
--- /dev/null
+++ b/tools/pnacl-thaw/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS bitwriter naclbitreader)
+
+add_llvm_tool(pnacl-thaw
+ pnacl-thaw.cpp
+ )
diff --git a/tools/pnacl-thaw/LLVMBuild.txt b/tools/pnacl-thaw/LLVMBuild.txt
new file mode 100644
index 0000000000..864da2cbd5
--- /dev/null
+++ b/tools/pnacl-thaw/LLVMBuild.txt
@@ -0,0 +1,16 @@
+;===- ./tools/pnacl-thaw/LLVMBuild.txt -----------------------*- Conf -*--===;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = pnacl-thaw
+parent = Tools
+required_libraries = BitWriter NaClBitReader
diff --git a/tools/pnacl-thaw/Makefile b/tools/pnacl-thaw/Makefile
new file mode 100644
index 0000000000..8e7699e185
--- /dev/null
+++ b/tools/pnacl-thaw/Makefile
@@ -0,0 +1,17 @@
+##===- tools/pnacl-thaw/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../..
+TOOLNAME := pnacl-thaw
+LINK_COMPONENTS := bitwriter naclbitreader
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/pnacl-thaw/pnacl-thaw.cpp b/tools/pnacl-thaw/pnacl-thaw.cpp
new file mode 100644
index 0000000000..b28c357165
--- /dev/null
+++ b/tools/pnacl-thaw/pnacl-thaw.cpp
@@ -0,0 +1,94 @@
+/* Copyright 2013 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+//===-- pnacl-thaw.cpp - The low-level NaCl bitcode thawer ----------------===//
+//
+//===----------------------------------------------------------------------===//
+//
+// Converts NaCl wire format back to LLVM bitcode.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/LLVMContext.h"
+// Note: We need the following to provide the API for calling the NaCl
+// Bitcode Reader to read the frozen file.
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+// Note: We need the following to provide the API for calling the (LLVM)
+// Bitcode Writer to generate the corresponding LLVM bitcode file.
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+using namespace llvm;
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Specify thawed pexe filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<frozen file>"), cl::Required);
+
+static void WriteOutputFile(const Module *M) {
+
+ std::string ThawedFilename =
+ (OutputFilename.size() == 0 ? (InputFilename + ".thawed") : OutputFilename);
+
+ std::string ErrorInfo;
+ OwningPtr<tool_output_file> Out
+ (new tool_output_file(ThawedFilename.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary));
+ if (!ErrorInfo.empty()) {
+ errs() << ErrorInfo << '\n';
+ exit(1);
+ }
+
+ WriteBitcodeToFile(M, Out->os());
+
+ // Declare success.
+ Out->keep();
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ LLVMContext &Context = getGlobalContext();
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(
+ argc, argv, "Converts NaCl pexe wire format into LLVM bitcode format\n");
+
+ std::string ErrorMessage;
+ std::auto_ptr<Module> M;
+
+ // Use the bitcode streaming interface
+ DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
+ if (streamer) {
+ std::string DisplayFilename = InputFilename;
+ M.reset(getNaClStreamedBitcodeModule(DisplayFilename, streamer, Context,
+ &ErrorMessage));
+ if(M.get() != 0 && M->MaterializeAllPermanently(&ErrorMessage)) {
+ M.reset();
+ }
+ }
+
+ if (M.get() == 0) {
+ errs() << argv[0] << ": ";
+ if (ErrorMessage.size())
+ errs() << ErrorMessage << "\n";
+ else
+ errs() << "bitcode didn't read correctly.\n";
+ return 1;
+ }
+
+ WriteOutputFile(M.get());
+ return 0;
+}