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

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: Try to get better patch. 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
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..85da68ddaf3cbcb769ad2f29c2a59d8c67696384
--- /dev/null
+++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
@@ -0,0 +1,336 @@
+//===- 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.HasErrors = true;
+ return errs() << "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.TryToRecover)
+ Results.HasRepairs = true;
+ 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 = naclbitc::DEFAULT_MAX_ABBREV;
jvoung (off chromium) 2015/05/06 22:08:09 Should this also be NaClBitsNeededForValue( naclbi
Karl 2015/05/07 20:09:18 Good catch. Fixing!
+ WriteBlockID = -1;
+ if (Record.Abbrev != naclbitc::ENTER_SUBBLOCK) {
+ RecoverableError()
+ << "Uses illegal abbreviation index in enter block record: "
+ << Record << "\n";
+ if (!Flags.TryToRecover)
+ 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.TryToRecover)
+ 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.TryToRecover)
+ 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.TryToRecover)
+ return false;
+ }
+ if (NumValues != 0) {
+ RecoverableError() << "Exit block should not have values: "
+ << Record << "\n";
+ if (!Flags.TryToRecover)
+ 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.TryToRecover)
+ return false;
+ }
+ NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record);
+ if (Abbrev == NULL)
+ return Flags.TryToRecover;
+ 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:
+ bool UsesDefaultAbbrev = Record.Abbrev == naclbitc::UNABBREV_RECORD;
+ if (!UsesDefaultAbbrev
+ && !Writer.isUserRecordAbbreviation(Record.Abbrev)) {
+ uint64_t BlockAbbrevIndexLimit = 0;
+ if (!AbbrevIndexLimitStack.empty())
+ BlockAbbrevIndexLimit = AbbrevIndexLimitStack.back();
+ // Can't generate abbreviation ID because not enough bits
+ // specified in block ID.
+ raw_ostream &ErrStrm = RecoverableError();
+ ErrStrm << "Uses illegal abbreviation index";
+ if (Record.Abbrev > BlockAbbrevIndexLimit)
jvoung (off chromium) 2015/05/06 22:08:09 When does this > check fail? If for some reason th
Karl 2015/05/07 20:09:18 Decided to simplify this code and be more generic.
+ ErrStrm << ". Must not exceed " << BlockAbbrevIndexLimit;
+ ErrStrm << ": " << Record << "\n";
+ if (!Flags.TryToRecover && !Flags.SaveBadAbbrevIndices)
jvoung (off chromium) 2015/05/06 22:08:09 So this code is saying that SaveBadAbbrevIndices w
Karl 2015/05/07 20:09:18 Hopefully the code is now clearer since I simplifi
jvoung (off chromium) 2015/05/07 21:33:56 Thanks -- I like the new version more.
+ return false;
+ if (Flags.SaveBadAbbrevIndices) {
+ // Note: If this point is reached, the abbreviation is bad and
+ // RecoverOnBadAbbrevID is true. Generate bad abbreviation index
jvoung (off chromium) 2015/05/06 22:08:09 there is no RecoverOnBadAbbrevID anymore You also
Karl 2015/05/07 20:09:18 Again, I simplified this code so that we don't nee
+ // so that the bitcode reader can be tested.
+ Writer.EmitCode(Record.Abbrev);
+ // Note: We need to close blocks or the bitcode Writer will terminate
+ // due to assertions.
+ writeMissingEndBlocks(Writer);
+ Results.SavedBadAbbrevIndices = true;
jvoung (off chromium) 2015/05/06 22:08:09 Perhaps "Save..." should be "Write..." ? In some
Karl 2015/05/07 20:09:18 Hopefully I have clarified that the Save Case (now
+ 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.TryToRecover)
+ State.writeMissingEndBlocks(Writer);
+ }
+ return State.Results;
+}

Powered by Google App Engine
This is Rietveld 408576698