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

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

Issue 1113023005: Add abilities to generate bitcode buffers from munged bitcode. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Fix nits. Created 5 years, 7 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/NaClBitcodeMungeReader.cpp ('k') | unittests/Bitcode/CMakeLists.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
diff --git a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d036c15c53848c3c674eaa18ebf7da6078a2340b
--- /dev/null
+++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
@@ -0,0 +1,333 @@
+//===- NaClBitcodeMungeWriter.cpp - Write munged bitcode --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements method NaClMungedBitcode.write(), which writes out a munged
+// list of bitcode records using a bitstream writer.
+
+#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
+
+#include "llvm/Bitcode/NaCl/NaClBitstreamWriter.h"
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+
+using namespace llvm;
+
+namespace {
+
+// For debugging. When true, shows each PNaCl record that is
+// emitted to the bitcode file.
+static bool DebugEmitRecord = false;
+
+// State of bitcode writing.
+struct WriteState {
+ // The block ID associated with the block being written.
+ int WriteBlockID = -1;
+ // The SetBID for the blockinfo block.
+ int SetBID = -1;
+ // The stack of maximum abbreviation indices allowed by block enter record.
+ SmallVector<uint64_t, 3> AbbrevIndexLimitStack;
+ // The set of write flags to use.
+ const NaClMungedBitcode::WriteFlags &Flags;
+ // The results of the attempted write.
+ NaClMungedBitcode::WriteResults Results;
+
+ WriteState(const NaClMungedBitcode::WriteFlags &Flags) : Flags(Flags) {}
+
+ // Returns stream to print error message to.
+ raw_ostream &Error() {
+ ++Results.NumErrors;
+ return Flags.getErrStream() << "Error (Block " << WriteBlockID << "): ";
+ }
+
+ // Returns stream to print error message to, assuming that
+ // the error message can be repaired if Flags.TryToRecover is true.
+ raw_ostream &RecoverableError() {
+ if (Flags.getTryToRecover())
+ ++Results.NumRepairs;
+ return Error();
+ }
+
+ // Converts the abbreviation record to the corresponding abbreviation.
+ // Returns nullptr if unable to build abbreviation.
+ NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record);
+
+ // Emits the given record to the bitcode file. Returns true if
+ // successful.
+ bool emitRecord(NaClBitstreamWriter &Writer,
+ const NaClBitcodeAbbrevRecord &Record);
+
+ // Adds any missing end blocks to written bitcode.
+ void writeMissingEndBlocks(NaClBitstreamWriter &Writer) {
+ while (!AbbrevIndexLimitStack.empty()) {
+ Writer.ExitBlock();
+ AbbrevIndexLimitStack.pop_back();
+ }
+ }
+};
+
+bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
+ const NaClBitcodeAbbrevRecord &Record) {
+ size_t NumValues = Record.Values.size();
+ if (DebugEmitRecord) {
+ errs() << "Emit " << Record.Abbrev << ": <" << Record.Code;
+ for (size_t i = 0; i < NumValues; ++i) {
+ errs() << ", " << Record.Values[i];
+ }
+ errs() << ">\n";
+ }
+
+ switch (Record.Code) {
+ case naclbitc::BLK_CODE_ENTER: {
+ unsigned NumBits = NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV);
+ WriteBlockID = -1;
+ if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) {
+ RecoverableError()
+ << "Uses illegal abbreviation index in enter block record: "
+ << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ }
+ if (NumValues == 2) {
+ WriteBlockID = Record.Values[0];
+ NumBits = Record.Values[1];
+ if (NumBits > 32 || NumBits < 2) {
+ RecoverableError()
+ << "Bit size " << NumBits << " for record should be "
+ << (NumBits > 32 ? "<= 32" : ">= 2") << ": " << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ NumBits = 32;
+ }
+ } else {
+ Error() << "Values for enter record should be of size 2, but found "
+ << NumValues << ": " << Record << "\n";
+ return false;
+ }
+ uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1;
+ AbbrevIndexLimitStack.push_back(MaxAbbrev);
+ if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) {
+ unsigned DefaultMaxBits =
+ NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV);
+ if (NumBits != DefaultMaxBits) {
+ RecoverableError()
+ << "Numbits entry for abbreviations record not "
+ << DefaultMaxBits << " but found " << NumBits <<
+ ": " << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ }
+ Writer.EnterBlockInfoBlock();
+ } else {
+ NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev);
+ Writer.EnterSubblock(WriteBlockID, CurCodeLen);
+ }
+ break;
+ }
+ case naclbitc::BLK_CODE_EXIT:
+ if (Record.Abbrev != naclbitc::END_BLOCK) {
+ RecoverableError()
+ << "Uses illegal abbreviation index in exit block record: "
+ << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ }
+ if (NumValues != 0) {
+ RecoverableError() << "Exit block should not have values: "
+ << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ }
+ if (!AbbrevIndexLimitStack.empty())
+ AbbrevIndexLimitStack.pop_back();
+ Writer.ExitBlock();
+ break;
+ case naclbitc::BLK_CODE_DEFINE_ABBREV: {
+ if (Record.Abbrev != naclbitc::DEFINE_ABBREV) {
+ RecoverableError()
+ << "Uses illegal abbreviation index in define abbreviation record: "
+ << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ }
+ NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record);
+ if (Abbrev == NULL)
+ return Flags.getTryToRecover();
+ if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) {
+ Writer.EmitBlockInfoAbbrev(SetBID, Abbrev);
+ } else {
+ Writer.EmitAbbrev(Abbrev);
+ }
+ break;
+ }
+ case naclbitc::BLK_CODE_HEADER:
+ // Note: There is no abbreviation index here. Ignore.
+ for (uint64_t Value : Record.Values)
+ Writer.Emit(Value, 8);
+ break;
+ default:
+ if (AbbrevIndexLimitStack.empty()) {
+ Error() << "Can't write record outside record block: " << Record << "\n";
+ return false;
+ }
+ bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD;
+ if (!UsesDefaultAbbrev
+ && !Writer.isUserRecordAbbreviation(Record.Abbrev)) {
+ // Illegal abbreviation index found.
+ if (Flags.getWriteBadAbbrevIndex()) {
+ Error() << "Uses illegal abbreviation index: " << Record << "\n";
+ // Generate bad abbreviation index so that the bitcode reader
+ // can be tested.
+ Results.WroteBadAbbrevIndex = true;
+ Writer.EmitCode(Record.Abbrev);
+ // Note: We need to close blocks or the bitcode Writer will terminate
+ // due to assertions.
+ writeMissingEndBlocks(Writer);
+ return false;
+ }
+ RecoverableError() << "Uses illegal abbreviation index: "
+ << Record << "\n";
+ if (!Flags.getTryToRecover())
+ return false;
+ UsesDefaultAbbrev = true;
+ }
+ if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID
+ && Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) {
+ // Note: SetBID records are handled by Writer->EmitBlockInfoAbbrev,
+ // based on the SetBID value. Don't bother to generate SetBID record here.
+ // Rather just set SetBID and let call to Writer->EmitBlockInfoAbbrev
+ // generate the SetBID record.
+ if (NumValues != 1) {
+ Error() << "SetBID record expects 1 value but found "
+ << NumValues << ": " << Record << "\n";
+ return false;
+ }
+ SetBID = Record.Values[0];
+ return true;
+ }
+ if (UsesDefaultAbbrev)
+ Writer.EmitRecord(Record.Code, Record.Values);
+ else
+ Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev);
+ }
+ return true;
+}
+
+static NaClBitCodeAbbrev *deleteAbbrev(NaClBitCodeAbbrev *Abbrev) {
+ Abbrev->dropRef();
+ return nullptr;
+}
+
+NaClBitCodeAbbrev *WriteState::buildAbbrev(
+ const NaClBitcodeAbbrevRecord &Record) {
+ // Note: Recover by removing abbreviation.
+ NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
+ size_t Index = 0;
+ size_t NumValues = Record.Values.size();
+ if (NumValues == 0) {
+ RecoverableError() << "Empty abbreviation record not allowed: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ size_t NumAbbreviations = Record.Values[Index++];
+ if (NumAbbreviations == 0) {
+ RecoverableError() << "Abbreviation must contain at least one operator: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ for (size_t Count = 0; Count < NumAbbreviations; ++Count) {
+ if (Index >= NumValues) {
+ RecoverableError()
+ << "Malformed abbreviation found. Expects " << NumAbbreviations
+ << " operands but ound " << Count << ": " << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ switch (Record.Values[Index++]) {
+ case 1:
+ if (Index >= NumValues) {
+ RecoverableError() << "Malformed literal abbreviation: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++]));
+ break;
+ case 0: {
+ if (Index >= NumValues) {
+ RecoverableError() << "Malformed abbreviation found: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ unsigned Kind = Record.Values[Index++];
+ switch (Kind) {
+ case NaClBitCodeAbbrevOp::Fixed:
+ if (Index >= NumValues) {
+ RecoverableError() << "Malformed fixed abbreviation found: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed,
+ Record.Values[Index++]));
+ break;
+ case NaClBitCodeAbbrevOp::VBR:
+ if (Index >= NumValues) {
+ RecoverableError() << "Malformed vbr abbreviation found: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR,
+ Record.Values[Index++]));
+ break;
+ case NaClBitCodeAbbrevOp::Array:
+ if (Index >= NumValues) {
+ RecoverableError() << "Malformed array abbreviation found: "
+ << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Array));
+ break;
+ case NaClBitCodeAbbrevOp::Char6:
+ Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Char6));
+ break;
+ default:
+ RecoverableError() << "Unknown abbreviation kind " << Kind
+ << ": " << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ break;
+ }
+ default:
+ RecoverableError() << "Error: Bad literal flag " << Record.Values[Index]
+ << ": " << Record << "\n";
+ return deleteAbbrev(Abbrev);
+ }
+ }
+ return Abbrev;
+}
+
+} // end of anonymous namespace.
+
+NaClMungedBitcode::WriteResults NaClMungedBitcode::writeMaybeRepair(
+ SmallVectorImpl<char> &Buffer, bool AddHeader,
+ const WriteFlags &Flags) const {
+ NaClBitstreamWriter Writer(Buffer);
+ WriteState State(Flags);
+ if (AddHeader) {
+ NaClWriteHeader(Writer, true);
+ }
+ for (const NaClBitcodeAbbrevRecord &Record : *this) {
+ if (!State.emitRecord(Writer, Record))
+ break;
+ }
+ if (!State.AbbrevIndexLimitStack.empty()) {
+ State.RecoverableError()
+ << "Bitcode missing " << State.AbbrevIndexLimitStack.size()
+ << " close blocks.\n";
+ if (Flags.getTryToRecover())
+ State.writeMissingEndBlocks(Writer);
+ }
+ return State.Results;
+}
« no previous file with comments | « lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeReader.cpp ('k') | unittests/Bitcode/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698