Index: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp |
diff --git a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6cab2f8ea08943a1cf6641cc9cc819acea66f2bd |
--- /dev/null |
+++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp |
@@ -0,0 +1,157 @@ |
+//===- NaClBitcodeMungeReader.cpp - Read bitcode record list ----*- C++ -*-===// |
+// |
+// The LLVM Compiler Infrastructure |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// Implements bitcode reader for NaClBitcodeRecordList and NaClMungedBitcode. |
+ |
+#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" |
+ |
+#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
+#include "llvm/Support/MemoryBuffer.h" |
+ |
+using namespace llvm; |
+ |
+namespace { |
+ |
+class BitcodeParser; |
+ |
+// \brief The state associated with parsing a bitcode buffer. |
+class BitcodeParseState { |
+ BitcodeParseState(const BitcodeParseState&) = delete; |
+ BitcodeParseState &operator=(const BitcodeParseState&) = delete; |
+public: |
+ // \brief Construct the bitcode parse state. |
+ // |
+ // \param Parser The parser used to parse the bitcode. |
+ // \param[out] Records Filled with parsed records. |
+ BitcodeParseState(BitcodeParser *Parser, |
+ NaClBitcodeRecordList &Records); |
+ |
+ // List to read records into. |
+ NaClBitcodeRecordList &Records; |
+ // Listener used to get abbreviations as they are read. |
+ NaClBitcodeParserListener AbbrevListener; |
+}; |
+ |
+// \brief The bitcode parser to extract bitcode records. |
+class BitcodeParser : public NaClBitcodeParser { |
+ BitcodeParser(const BitcodeParser &) = delete; |
+ BitcodeParser &operator=(const BitcodeParser&) = delete; |
+public: |
+ // \brief Top-level constructor for a bitcode parser. |
+ // |
+ // \param Cursor The beginning position of the bitcode to parse. |
+ // \param[out] Records Filled with parsed records. |
+ BitcodeParser(NaClBitstreamCursor &Cursor, |
+ NaClBitcodeRecordList &Records) |
+ : NaClBitcodeParser(Cursor), |
+ State(new BitcodeParseState(this, Records)) { |
+ SetListener(&State->AbbrevListener); |
+ } |
+ |
+ ~BitcodeParser() override { |
+ if (EnclosingParser == nullptr) |
+ delete State; |
+ } |
+ |
+ bool ParseBlock(unsigned BlockID) override { |
+ BitcodeParser NestedParser(BlockID, this); |
+ return NestedParser.ParseThisBlock(); |
+ } |
+ |
+ void EnterBlock(unsigned NumWords) override { |
+ NaClRecordVector Values; |
+ Values.push_back(GetBlockID()); |
+ Values.push_back(Record.GetCursor().getAbbrevIDWidth()); |
+ std::unique_ptr<NaClBitcodeAbbrevRecord> AbbrevRec( |
+ new NaClBitcodeAbbrevRecord(naclbitc::ENTER_SUBBLOCK, |
+ naclbitc::BLK_CODE_ENTER, |
+ Values)); |
+ State->Records.push_back(std::move(AbbrevRec)); |
+ } |
+ |
+ void ExitBlock() override { |
+ NaClRecordVector Values; |
+ std::unique_ptr<NaClBitcodeAbbrevRecord> AbbrevRec( |
+ new NaClBitcodeAbbrevRecord(naclbitc::END_BLOCK, |
+ naclbitc::BLK_CODE_EXIT, |
+ Values)); |
+ State->Records.push_back(std::move(AbbrevRec)); |
+ } |
+ |
+ void ProcessRecord() override { |
+ std::unique_ptr<NaClBitcodeAbbrevRecord> AbbrevRec( |
+ new NaClBitcodeAbbrevRecord(Record.GetAbbreviationIndex(), |
+ Record.GetCode(), |
+ Record.GetValues())); |
+ State->Records.push_back(std::move(AbbrevRec)); |
+ } |
+ |
+ void SetBID() override { |
+ ProcessRecord(); |
+ } |
+ |
+ void ProcessAbbreviation(unsigned BlockID, |
+ NaClBitCodeAbbrev *Abbrev, |
+ bool IsLocal) override { |
+ ProcessRecord(); |
+ } |
+ |
+private: |
+ // \brief Nested constructor for blocks within the bitcode buffer. |
+ // |
+ // \param BlockID The identifying constant associated with the block. |
+ // \param EnclosingParser The bitcode parser parsing the enclosing block. |
+ BitcodeParser(unsigned BlockID, BitcodeParser *EnclosingParser) |
+ : NaClBitcodeParser(BlockID, EnclosingParser), |
+ State(EnclosingParser->State) {} |
+ |
+ // The state of the bitcode parser. |
+ BitcodeParseState* State; |
+}; |
+ |
+BitcodeParseState::BitcodeParseState(BitcodeParser *Parser, |
+ NaClBitcodeRecordList &Records) |
+ : Records(Records), AbbrevListener(Parser) {} |
+ |
+} // end of anonymous namespace |
+ |
+void llvm::readNaClBitcodeRecordList( |
+ NaClBitcodeRecordList &RecordList, |
+ std::unique_ptr<MemoryBuffer> InputBuffer) { |
+ if (InputBuffer->getBufferSize() % 4 != 0) |
+ report_fatal_error( |
+ "Bitcode stream must be a multiple of 4 bytes in length"); |
+ |
+ const unsigned char *BufPtr = |
+ (const unsigned char *) InputBuffer->getBufferStart(); |
+ const unsigned char *EndBufPtr = BufPtr + InputBuffer->getBufferSize(); |
+ const unsigned char *HeaderPtr = BufPtr; |
+ |
+ // Read header and verify it is good. |
+ NaClBitcodeHeader Header; |
+ if (Header.Read(HeaderPtr, EndBufPtr) || !Header.IsSupported()) |
+ report_fatal_error("Invalid PNaCl bitcode header.\n"); |
+ |
+ NaClBitstreamReader Reader(BufPtr, EndBufPtr, Header.getHeaderSize()); |
+ NaClBitstreamCursor Cursor(Reader); |
+ |
+ // Parse the bitcode buffer. |
+ BitcodeParser Parser(Cursor, RecordList); |
+ |
+ while (!Cursor.AtEndOfStream()) { |
+ if (Parser.Parse()) |
+ report_fatal_error("Malformed records founds, unable to continue"); |
+ } |
+} |
+ |
+ |
+NaClMungedBitcode::NaClMungedBitcode(std::unique_ptr<MemoryBuffer> InputBuffer) |
+ : BaseRecords(new NaClBitcodeRecordList()) { |
+ readNaClBitcodeRecordList(*BaseRecords, std::move(InputBuffer)); |
+} |