Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Unified Diff: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/Bitcode/NaCl/TestUtils/Makefile ('k') | lib/Bitcode/NaCl/Writer/CMakeLists.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
diff --git a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6cb093238bdd40abd6c7d41f6f46c5ac9802a14e
--- /dev/null
+++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
@@ -0,0 +1,377 @@
+//===--- Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp - Bitcode Munger -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Bitcode writer/munger implementation for testing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/NaCl/NaClBitcodeMunge.h"
+
+#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
+#include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h"
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <memory>
+
+using namespace llvm;
+
+// For debugging. When true, shows each PNaCl record that is
+// emitted to the bitcode file.
+static bool DebugEmitRecord = false;
+
+void NaClBitcodeMunger::setupTest(
+ const char *TestName, const uint64_t Munges[], size_t MungesSize,
+ bool AddHeader) {
+ assert(DumpStream == nullptr && "Test run with DumpStream already defined");
+ assert(MungedInput.get() == nullptr
+ && "Test run with MungedInput already defined");
+ FoundErrors = false;
+ DumpResults.clear(); // Throw away any previous results.
+ std::string DumpBuffer;
+ DumpStream = new raw_string_ostream(DumpResults);
+ SmallVector<char, 0> StreamBuffer;
+ StreamBuffer.reserve(256*1024);
+ NaClBitstreamWriter OutStream(StreamBuffer);
+ Writer = &OutStream;
+
+ if (DebugEmitRecord) {
+ errs() << "*** Run test: " << TestName << "\n";
+ }
+
+ WriteBlockID = -1;
+ SetBID = -1;
+ writeMungedData(Munges, MungesSize, AddHeader);
+
+ std::string OutBuffer;
+ raw_string_ostream BitcodeStrm(OutBuffer);
+ for (SmallVectorImpl<char>::const_iterator
+ Iter = StreamBuffer.begin(), IterEnd = StreamBuffer.end();
+ Iter != IterEnd; ++Iter) {
+ BitcodeStrm << *Iter;
+ }
+ MungedInput = MemoryBuffer::getMemBufferCopy(BitcodeStrm.str(), TestName);
+}
+
+void NaClBitcodeMunger::cleanupTest() {
+ MungedInput.reset();
+ assert(DumpStream && "Dump stream removed before cleanup!");
+ DumpStream->flush();
+ delete DumpStream;
+ DumpStream = nullptr;
+ Writer = nullptr;
+}
+
+// Return the next line of input (including eoln), starting from
+// Pos. Then increment Pos past the end of that line.
+static std::string getLine(const std::string &Input, size_t &Pos) {
+ std::string Line;
+ if (Pos >= Input.size()) {
+ Pos = std::string::npos;
+ return Line;
+ }
+ size_t Eoln = Input.find_first_of("\n", Pos);
+ if (Eoln != std::string::npos) {
+ for (size_t i = Pos; i <= Eoln; ++i)
+ Line.push_back(Input[i]);
+ Pos = Eoln + 1;
+ return Line;
+ }
+ Pos = std::string::npos;
+ return Input.substr(Pos);
+}
+
+std::string NaClBitcodeMunger::
+getLinesWithTextMatch(const std::string &Substring, bool MustBePrefix) const {
+ std::string Messages;
+ size_t LastLinePos = 0;
+ while (1) {
+ std::string Line = getLine(DumpResults, LastLinePos);
+ if (LastLinePos == std::string::npos) break;
+ size_t Pos = Line.find(Substring);
+ if (Pos != std::string::npos && (!MustBePrefix || Pos == 0)) {
+ Messages.append(Line);
+ }
+ }
+ return Messages;
+}
+
+void NaClBitcodeMunger::writeMungedData(const uint64_t Munges[],
+ size_t MungesSize, bool AddHeader) {
+ uint64_t RecordCount = 0;
+ size_t MungesIndex = 0;
+ if (AddHeader) {
+ NaClWriteHeader(*Writer, true);
+ }
+ for (size_t RecordsIndex = 0; RecordsIndex < RecordsSize;) {
+ if (MungesIndex < MungesSize && Munges[MungesIndex] == RecordCount) {
+ if (MungesIndex + 2 > MungesSize) {
+ Fatal() << "Munges entry must contain at least 2 elements. Found: "
+ << MungesIndex;
+ ReportFatalError();
+ }
+ ++MungesIndex;
+ switch (Munges[MungesIndex++]) {
+ case NaClBitcodeMunger::AddBefore:
+ emitRecordAtIndex(Munges, MungesSize, MungesIndex);
+ break;
+ case NaClBitcodeMunger::AddAfter:
+ emitRecordAtIndex(Records, RecordsSize, RecordsIndex);
+ ++RecordCount;
+ emitRecordAtIndex(Munges, MungesSize, MungesIndex);
+ break;
+ case NaClBitcodeMunger::Remove:
+ deleteRecord(Records, RecordsSize, RecordsIndex);
+ ++RecordCount;
+ break;
+ case NaClBitcodeMunger::Replace:
+ deleteRecord(Records, RecordsSize, RecordsIndex);
+ emitRecordAtIndex(Munges, MungesSize, MungesIndex);
+ ++RecordCount;
+ break;
+ default:
+ Fatal() << "Munge directive not understood: " << Munges[MungesIndex];
+ ReportFatalError();
+ break;
+ }
+ } else {
+ emitRecordAtIndex(Records, RecordsSize, RecordsIndex);
+ ++RecordCount;
+ }
+ }
+ if (MungesIndex < MungesSize) {
+ Fatal() << "Unprocessed modifications. At index " << MungesIndex << "\n";
+ ReportFatalError();
+ }
+}
+
+void NaClBitcodeMunger::deleteRecord(
+ const uint64_t Record[], size_t RecordSize, size_t &Index) {
+ while (Index < RecordSize) {
+ if (Record[Index++] == RecordTerminator)
+ break;
+ }
+}
+
+void NaClBitcodeMunger::emitRecordAtIndex(
+ const uint64_t Record[], size_t RecordSize, size_t &Index) {
+ if (Index + 3 > RecordSize) {
+ Fatal() << "Last record doesn't contain at least 3 elements. Found: "
+ << (RecordSize - Index);
+ ReportFatalError();
+ }
+ SmallVector<uint64_t, 32> RecordValues;
+ unsigned AbbrevIndex = static_cast<unsigned>(Record[Index++]);
+ unsigned RecordCode = static_cast<unsigned>(Record[Index++]);
+ while (Index < RecordSize && Record[Index] != RecordTerminator) {
+ RecordValues.push_back(Record[Index++]);
+ }
+ emitRecord(AbbrevIndex, RecordCode, RecordValues);
+ if (Index == RecordSize) {
+ Fatal() << "Last record not followed by terminator.\n";
+ ReportFatalError();
+ }
+ ++Index;
+}
+
+void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex,
+ unsigned RecordCode,
+ SmallVectorImpl<uint64_t> &Values) {
+ if (DebugEmitRecord) {
+ errs() << "Emit " << AbbrevIndex << ": <" << RecordCode;
+ for (size_t i = 0; i < Values.size(); ++i) {
+ errs() << ", " << Values[i];
+ }
+ errs() << ">\n";
+ }
+
+ switch (RecordCode) {
+ case naclbitc::BLK_CODE_ENTER: {
+ unsigned NumBits = naclbitc::DEFAULT_MAX_ABBREV;
+ WriteBlockID = -1;
+ if (AbbrevIndex != naclbitc::ENTER_SUBBLOCK) {
+ Fatal() << "Enter block record code " << RecordCode
+ << " uses illegal abbreviation index " << AbbrevIndex << "\n";
+ ReportFatalError();
+ }
+ if (Values.size() == 2) {
+ WriteBlockID = Values[0];
+ NumBits = Values[1];
+ if (NumBits > 32) {
+ Fatal() << "Error: Bit size " << NumBits
+ << " for record should be <= 32\n";
+ ReportFatalError();
+ }
+ } else {
+ Fatal() << "Error: Values for enter record should be of size 2. Found: "
+ << Values.size();
+ ReportFatalError();
+ }
+ if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) {
+ if (NumBits != naclbitc::DEFAULT_MAX_ABBREV) {
+ Fatal()
+ << "Error: Numbits entry for abbreviations record not 2. Found: "
+ << NumBits << "\n";
+ ReportFatalError();
+ }
+ Writer->EnterBlockInfoBlock();
+ } else {
+ Writer->EnterSubblock(WriteBlockID, NumBits);
+ }
+ return;
+ }
+ case naclbitc::BLK_CODE_EXIT:
+ if (AbbrevIndex != naclbitc::END_BLOCK) {
+ Fatal() << "Error: Exit block record code " << RecordCode
+ << " uses illegal abbreviation index " << AbbrevIndex << "\n";
+ ReportFatalError();
+ }
+ if (!Values.empty()) {
+ Fatal() << "Error: Exit block should not have values. Found: "
+ << Values.size() << "\n";
+ ReportFatalError();
+ }
+ Writer->ExitBlock();
+ return;
+ case naclbitc::BLK_CODE_DEFINE_ABBREV: {
+ if (AbbrevIndex != naclbitc::DEFINE_ABBREV) {
+ Fatal() << "Error: Define abbreviation record code " << RecordCode
+ << " uses illegal abbreviation index " << AbbrevIndex << "\n";
+ ReportFatalError();
+ }
+ NaClBitCodeAbbrev *Abbrev = buildAbbrev(RecordCode, Values);
+ if (Abbrev == NULL) return;
+ if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) {
+ Writer->EmitBlockInfoAbbrev(SetBID, Abbrev);
+ } else {
+ Writer->EmitAbbrev(Abbrev);
+ }
+ return;
+ }
+ case naclbitc::BLK_CODE_HEADER:
+ // Note: There is no abbreviation index here. Ignore.
+ for (SmallVectorImpl<uint64_t>::const_iterator
+ Iter = Values.begin(), IterEnd = Values.end();
+ Iter != IterEnd; ++Iter) {
+ Writer->Emit(*Iter, 8);
+ }
+ return;
+ default:
+ if ((AbbrevIndex != naclbitc::UNABBREV_RECORD
+ && !Writer->isUserRecordAbbreviation(AbbrevIndex))) {
+ Fatal() << "Error: Record code " << RecordCode
+ << " uses illegal abbreviation index " << AbbrevIndex << "\n";
+ ReportFatalError();
+ }
+ if (AbbrevIndex == naclbitc::UNABBREV_RECORD)
+ Writer->EmitRecord(RecordCode, Values);
+ else
+ Writer->EmitRecord(RecordCode, Values, AbbrevIndex);
+ return;
+ }
+ Fatal() << "emitRecord on unimplemented code" << "\n";
+ ReportFatalError();
+}
+
+NaClBitCodeAbbrev *NaClBitcodeMunger::buildAbbrev(
+ unsigned RecordCode, SmallVectorImpl<uint64_t> &Values) {
+ NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
+ for (size_t Index = 0; Index < Values.size(); ) {
+ switch (Values[Index]) {
+ case 1:
+ if (Index + 1 >= Values.size()) {
+ Fatal() << "Malformed literal abbreviation.\n";
+ ReportFatalError();
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(Values[++Index]));
+ break;
+ case 0: {
+ if (Index >= Values.size()) {
+ Fatal() << "Malformed abbreviation found.\n";
+ ReportFatalError();
+ }
+ unsigned Kind = Values[++Index];
+ switch (Kind) {
+ case NaClBitCodeAbbrevOp::Fixed:
+ if (Index >= Values.size()) {
+ Fatal() << "Malformed fixed abbreviation found.\n";
+ ReportFatalError();
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed,
+ Values[++Index]));
+ break;
+ case NaClBitCodeAbbrevOp::VBR:
+ if (Index >= Values.size()) {
+ Fatal() << "Malformed vbr abbreviation found.\n";
+ ReportFatalError();
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR,
+ Values[++Index]));
+ break;
+ case NaClBitCodeAbbrevOp::Array:
+ if (Index >= Values.size()) {
+ Fatal() << "Malformed array abbreviation found.\n";
+ ReportFatalError();
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array));
+ break;
+ case NaClBitCodeAbbrevOp::Char6:
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6));
+ break;
+ default:
+ Fatal() << "Unknown abbreviation kind. Found: " << Kind << "\n";
+ ReportFatalError();
+ }
+ break;
+ }
+ default:
+ Fatal() << "Error: Bad literal flag in abbreviation. Found: "
+ << Values[Index];
+ ReportFatalError();
+ }
+ }
+ return Abbrev;
+}
+
+bool NaClObjDumpMunger::runTestWithFlags(
+ const char *Name, const uint64_t Munges[], size_t MungesSize,
+ bool AddHeader, bool NoRecords, bool NoAssembly) {
+ setupTest(Name, Munges, MungesSize, AddHeader);
+ // TODO(jvoung,kschimpf): Should NaClObjDump take a MemoryBufferRef
+ // like the parser?
+ if (NaClObjDump(MungedInput.get(), *DumpStream, NoRecords, NoAssembly))
+ FoundErrors = true;
+ cleanupTest();
+ return !FoundErrors;
+}
+
+bool NaClParseBitcodeMunger::runTest(
+ const char *Name, const uint64_t Munges[], size_t MungesSize,
+ bool VerboseErrors) {
+ bool AddHeader = true;
+ setupTest(Name, Munges, MungesSize, AddHeader);
+ LLVMContext &Context = getGlobalContext();
+ raw_ostream *VerboseStrm = VerboseErrors ? DumpStream : nullptr;
+ ErrorOr<Module *> ModuleOrError =
+ NaClParseBitcodeFile(MungedInput->getMemBufferRef(), Context,
+ VerboseStrm);
+ if (ModuleOrError) {
+ if (VerboseErrors)
+ *DumpStream << "Successful parse!\n";
+ delete ModuleOrError.get();
+ } else {
+ Error() << ModuleOrError.getError().message() << "\n";
+ }
+ cleanupTest();
+ return !FoundErrors;
+}
« no previous file with comments | « lib/Bitcode/NaCl/TestUtils/Makefile ('k') | lib/Bitcode/NaCl/Writer/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698