| Index: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
|
| diff --git a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
|
| index 2d88585ab5c81813db593a15b3473cc1d74627f9..effe128cac9e5f4d4ce9539864837383de623ded 100644
|
| --- a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
|
| +++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp
|
| @@ -15,7 +15,6 @@
|
|
|
| #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
|
| #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
|
| -#include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h"
|
| #include "llvm/Bitcode/NaCl/NaClCompress.h"
|
| #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
|
| #include "llvm/IR/LLVMContext.h"
|
| @@ -27,9 +26,8 @@
|
|
|
| using namespace llvm;
|
|
|
| -// For debugging. When true, shows each PNaCl record that is
|
| -// emitted to the bitcode file.
|
| -static bool DebugEmitRecord = false;
|
| +// For debugging. When true, shows each test being run.
|
| +static bool TraceTestRuns = false;
|
|
|
| void NaClBitcodeMunger::setupTest(
|
| const char *TestName, const uint64_t Munges[], size_t MungesSize,
|
| @@ -42,18 +40,21 @@ void NaClBitcodeMunger::setupTest(
|
| std::string DumpBuffer;
|
| DumpStream = new raw_string_ostream(DumpResults);
|
| MungedInputBuffer.clear();
|
| - NaClBitstreamWriter OutStream(MungedInputBuffer);
|
| - Writer = &OutStream;
|
|
|
| - if (DebugEmitRecord) {
|
| + if (TraceTestRuns) {
|
| errs() << "*** Run test: " << TestName << "\n";
|
| }
|
|
|
| - WriteBlockID = -1;
|
| - SetBID = -1;
|
| -
|
| MungedBitcode.munge(Munges, MungesSize, RecordTerminator);
|
| - writeMungedBitcode(MungedBitcode, AddHeader);
|
| + WriteFlags.setErrStream(getDumpStream());
|
| + NaClMungedBitcode::WriteResults Results =
|
| + MungedBitcode.writeMaybeRepair(MungedInputBuffer, AddHeader, WriteFlags);
|
| + if (Results.NumErrors != 0
|
| + && !(WriteFlags.getTryToRecover()
|
| + && Results.NumRepairs == Results.NumErrors)
|
| + && !(WriteFlags.getWriteBadAbbrevIndex()
|
| + && Results.WroteBadAbbrevIndex && Results.NumErrors == 1))
|
| + report_fatal_error("Unable to generate bitcode file due to write errors");
|
|
|
| // Add null terminator, so that we meet the requirements of the
|
| // MemoryBuffer API.
|
| @@ -65,13 +66,14 @@ void NaClBitcodeMunger::setupTest(
|
| }
|
|
|
| void NaClBitcodeMunger::cleanupTest() {
|
| + RunAsDeathTest = false;
|
| + WriteFlags.reset();
|
| MungedBitcode.removeEdits();
|
| 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
|
| @@ -108,230 +110,13 @@ getLinesWithTextMatch(const std::string &Substring, bool MustBePrefix) const {
|
| return Messages;
|
| }
|
|
|
| -void NaClBitcodeMunger::writeMungedBitcode(const NaClMungedBitcode &Bitcode,
|
| - bool AddHeader) {
|
| - if (AddHeader) {
|
| - NaClWriteHeader(*Writer, true);
|
| - }
|
| - for (const NaClBitcodeAbbrevRecord &Record : Bitcode) {
|
| - emitRecord(Record);
|
| - }
|
| -}
|
| -
|
| -void NaClBitcodeMunger::emitRecord(const NaClBitcodeAbbrevRecord &Record) {
|
| - if (DebugEmitRecord) {
|
| - errs() << "Emit " << Record.Abbrev << ": <" << Record.Code;
|
| - for (size_t i = 0, e = Record.Values.size(); i < e; ++i) {
|
| - errs() << ", " << Record.Values[i];
|
| - }
|
| - errs() << ">\n";
|
| - }
|
| -
|
| - switch (Record.Code) {
|
| - case naclbitc::BLK_CODE_ENTER: {
|
| - unsigned NumBits = naclbitc::DEFAULT_MAX_ABBREV;
|
| - WriteBlockID = -1;
|
| - if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) {
|
| - Fatal() << "Enter block record code " << Record.Code
|
| - << " uses illegal abbreviation index " << Record.Abbrev << "\n";
|
| - ReportFatalError();
|
| - }
|
| - if (Record.Values.size() == 2) {
|
| - WriteBlockID = Record.Values[0];
|
| - NumBits = Record.Values[1];
|
| - if (NumBits > 32) {
|
| - Fatal() << "Error: Bit size " << NumBits
|
| - << " for record should be <= 32\n";
|
| - ReportFatalError();
|
| - }
|
| - if (NumBits < 2) {
|
| - Fatal() << "Error: Bit size " << NumBits
|
| - << " for record should be >= 2\n";
|
| - ReportFatalError();
|
| - }
|
| - } else {
|
| - Fatal() << "Error: Values for enter record should be of size 2. Found: "
|
| - << Record.Values.size();
|
| - ReportFatalError();
|
| - }
|
| - uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1;
|
| - AbbrevIndexLimitStack.push_back(MaxAbbrev);
|
| - 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 {
|
| - NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev);
|
| - Writer->EnterSubblock(WriteBlockID, CurCodeLen);
|
| - }
|
| - return;
|
| - }
|
| - case naclbitc::BLK_CODE_EXIT:
|
| - if (Record.Abbrev != naclbitc::END_BLOCK) {
|
| - Fatal() << "Error: Exit block record code " << Record.Code
|
| - << " uses illegal abbreviation index " << Record.Abbrev << "\n";
|
| - ReportFatalError();
|
| - }
|
| - if (!Record.Values.empty()) {
|
| - Fatal() << "Error: Exit block should not have values. Found: "
|
| - << Record.Values.size() << "\n";
|
| - ReportFatalError();
|
| - }
|
| - if (!AbbrevIndexLimitStack.empty())
|
| - AbbrevIndexLimitStack.pop_back();
|
| - Writer->ExitBlock();
|
| - return;
|
| - case naclbitc::BLK_CODE_DEFINE_ABBREV: {
|
| - if (Record.Abbrev != naclbitc::DEFINE_ABBREV) {
|
| - Fatal() << "Error: Define abbreviation record code " << Record.Code
|
| - << " uses illegal abbreviation index " << Record.Abbrev << "\n";
|
| - ReportFatalError();
|
| - }
|
| - NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record);
|
| - 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 (uint64_t Value : Record.Values)
|
| - Writer->Emit(Value, 8);
|
| - return;
|
| - default:
|
| - if ((Record.Abbrev != naclbitc::UNABBREV_RECORD
|
| - && !Writer->isUserRecordAbbreviation(Record.Abbrev))) {
|
| - uint64_t BlockAbbrevIndexLimit = 0;
|
| - if (!AbbrevIndexLimitStack.empty())
|
| - BlockAbbrevIndexLimit = AbbrevIndexLimitStack.back();
|
| - if (Record.Abbrev > BlockAbbrevIndexLimit) {
|
| - Fatal() << "Error: Record code " << Record.Code
|
| - << " uses illegal abbreviation index " << Record.Abbrev
|
| - << ". Must not exceed " << BlockAbbrevIndexLimit << "\n";
|
| - ReportFatalError();
|
| - }
|
| - // Note: If this point is reached, the abbreviation is
|
| - // bad. However, that may be the point of munge being
|
| - // applied. Hence, emit the bad abbreviation and the data so
|
| - // that the reader can be tested on this bad input. For
|
| - // simplicity, we output the record data using the default
|
| - // abbreviation pattern.
|
| - errs() << "Warning: Record code " << Record.Code
|
| - << " uses illegal abbreviation index " << Record.Abbrev << "\n";
|
| - Writer->EmitCode(Record.Abbrev);
|
| - Writer->EmitVBR(Record.Code, 6);
|
| - uint32_t NumValues = static_cast<uint32_t>(Record.Values.size());
|
| - Writer->EmitVBR(NumValues, 6);
|
| - for (uint32_t i = 0; i < NumValues; ++i) {
|
| - Writer->EmitVBR64(Record.Values[i], 6);
|
| - }
|
| - return;
|
| - }
|
| - if (Record.Abbrev == naclbitc::UNABBREV_RECORD)
|
| - Writer->EmitRecord(Record.Code, Record.Values);
|
| - else
|
| - Writer->EmitRecord(Record.Code, Record.Values, Record.Abbrev);
|
| - return;
|
| - }
|
| - Fatal() << "emitRecord on unimplemented code" << "\n";
|
| - ReportFatalError();
|
| -}
|
| -
|
| -NaClBitCodeAbbrev *NaClBitcodeMunger::buildAbbrev(
|
| - const NaClBitcodeAbbrevRecord &Record) {
|
| - NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
|
| - size_t Index = 0;
|
| - if (Record.Values.empty()) {
|
| - Fatal() << "Empty abbreviation record not allowed\n";
|
| - ReportFatalError();
|
| - }
|
| - size_t NumAbbreviations = Record.Values[Index++];
|
| - size_t NumValues = Record.Values.size();
|
| - if (NumAbbreviations == 0) {
|
| - Fatal() << "Abbreviation must contain at least one operator\n";
|
| - ReportFatalError();
|
| - }
|
| - for (size_t Count = 0; Count < NumAbbreviations; ++Count) {
|
| - if (Index >= NumValues) {
|
| - Fatal() << "Malformed abbreviation found. Expects "
|
| - << NumAbbreviations << " operands. Found: "
|
| - << Count << "\n";
|
| - ReportFatalError();
|
| - }
|
| - switch (Record.Values[Index++]) {
|
| - case 1:
|
| - if (Index >= NumValues) {
|
| - Fatal() << "Malformed literal abbreviation.\n";
|
| - ReportFatalError();
|
| - }
|
| - Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++]));
|
| - break;
|
| - case 0: {
|
| - if (Index >= NumValues) {
|
| - Fatal() << "Malformed abbreviation found.\n";
|
| - ReportFatalError();
|
| - }
|
| - unsigned Kind = Record.Values[Index++];
|
| - switch (Kind) {
|
| - case NaClBitCodeAbbrevOp::Fixed:
|
| - if (Index >= NumValues) {
|
| - Fatal() << "Malformed fixed abbreviation found.\n";
|
| - ReportFatalError();
|
| - }
|
| - Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed,
|
| - Record.Values[Index++]));
|
| - break;
|
| - case NaClBitCodeAbbrevOp::VBR:
|
| - if (Index >= NumValues) {
|
| - Fatal() << "Malformed vbr abbreviation found.\n";
|
| - ReportFatalError();
|
| - }
|
| - Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR,
|
| - Record.Values[Index++]));
|
| - break;
|
| - case NaClBitCodeAbbrevOp::Array:
|
| - if (Index >= NumValues) {
|
| - 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: "
|
| - << Record.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);
|
|
|
| - /// If running in death mode, redirect output directly to the
|
| - /// error stream (rather than buffering in DumpStream), so that
|
| - /// output can be seen in gtest death test.
|
| - raw_ostream &Output = RunAsDeathTest ? errs() : *DumpStream;
|
| if (NaClObjDump(MungedInput.get()->getMemBufferRef(),
|
| - Output, NoRecords, NoAssembly))
|
| + getDumpStream(), NoRecords, NoAssembly))
|
| FoundErrors = true;
|
| cleanupTest();
|
| return !FoundErrors;
|
| @@ -343,13 +128,13 @@ bool NaClParseBitcodeMunger::runTest(
|
| bool AddHeader = true;
|
| setupTest(Name, Munges, MungesSize, AddHeader);
|
| LLVMContext &Context = getGlobalContext();
|
| - raw_ostream *VerboseStrm = VerboseErrors ? DumpStream : nullptr;
|
| + raw_ostream *VerboseStrm = VerboseErrors ? &getDumpStream() : nullptr;
|
| ErrorOr<Module *> ModuleOrError =
|
| NaClParseBitcodeFile(MungedInput->getMemBufferRef(), Context,
|
| VerboseStrm);
|
| if (ModuleOrError) {
|
| if (VerboseErrors)
|
| - *DumpStream << "Successful parse!\n";
|
| + getDumpStream() << "Successful parse!\n";
|
| delete ModuleOrError.get();
|
| } else {
|
| Error() << ModuleOrError.getError().message() << "\n";
|
| @@ -363,7 +148,7 @@ bool NaClCompressMunger::runTest(const char* Name, const uint64_t Munges[],
|
| bool AddHeader = true;
|
| setupTest(Name, Munges, MungesSize, AddHeader);
|
| NaClBitcodeCompressor Compressor;
|
| - bool Result = Compressor.compress(MungedInput.get(), *DumpStream);
|
| + bool Result = Compressor.compress(MungedInput.get(), getDumpStream());
|
| cleanupTest();
|
| return Result;
|
| }
|
|
|