summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Bitcode
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Bitcode')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp67
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp25
2 files changed, 92 insertions, 0 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index e8d45790e3b..d926f324145 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -152,6 +152,8 @@ class BitcodeReader : public GVMaterializer {
uint64_t LastFunctionBlockBit = 0;
bool SeenValueSymbolTable = false;
unsigned VSTOffset = 0;
+ // Contains an arbitrary and optional string identifying the bitcode producer
+ std::string ProducerIdentification;
std::vector<Type*> TypeList;
BitcodeReaderValueList ValueList;
@@ -273,6 +275,11 @@ public:
void setStripDebugInfo() override;
private:
+ /// Parse the "IDENTIFICATION_BLOCK_ID" block, populate the
+ // ProducerIdentification data member, and do some basic enforcement on the
+ // "epoch" encoded in the bitcode.
+ std::error_code parseBitcodeVersion();
+
std::vector<StructType *> IdentifiedStructTypes;
StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
StructType *createIdentifiedStructType(LLVMContext &Context);
@@ -518,10 +525,21 @@ static std::error_code error(DiagnosticHandlerFunction DiagnosticHandler,
}
std::error_code BitcodeReader::error(BitcodeError E, const Twine &Message) {
+ if (!ProducerIdentification.empty()) {
+ Twine MsgWithID = Message + " (Producer: '" + ProducerIdentification +
+ "' Reader: 'LLVM " + LLVM_VERSION_STRING "')";
+ return ::error(DiagnosticHandler, make_error_code(E), MsgWithID);
+ }
return ::error(DiagnosticHandler, make_error_code(E), Message);
}
std::error_code BitcodeReader::error(const Twine &Message) {
+ if (!ProducerIdentification.empty()) {
+ Twine MsgWithID = Message + " (Producer: '" + ProducerIdentification +
+ "' Reader: 'LLVM " + LLVM_VERSION_STRING "')";
+ return ::error(DiagnosticHandler,
+ make_error_code(BitcodeError::CorruptedBitcode), MsgWithID);
+ }
return ::error(DiagnosticHandler,
make_error_code(BitcodeError::CorruptedBitcode), Message);
}
@@ -3061,6 +3079,50 @@ std::error_code BitcodeReader::rememberAndSkipFunctionBodies() {
}
}
+std::error_code BitcodeReader::parseBitcodeVersion() {
+ if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID))
+ return error("Invalid record");
+
+ // Read all the records.
+ SmallVector<uint64_t, 64> Record;
+ while (1) {
+ BitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ default:
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ unsigned BitCode = Stream.readRecord(Entry.ID, Record);
+ switch (BitCode) {
+ default: // Default behavior: reject
+ return error("Invalid value");
+ case bitc::IDENTIFICATION_CODE_STRING: { // IDENTIFICATION: [strchr x
+ // N]
+ convertToString(Record, 0, ProducerIdentification);
+ break;
+ }
+ case bitc::IDENTIFICATION_CODE_EPOCH: { // EPOCH: [epoch#]
+ unsigned epoch = (unsigned)Record[0];
+ if (epoch != bitc::BITCODE_CURRENT_EPOCH) {
+ auto BitcodeEpoch = std::to_string(epoch);
+ auto CurrentEpoch = std::to_string(bitc::BITCODE_CURRENT_EPOCH);
+ return error(Twine("Incompatible epoch: Bitcode '") + BitcodeEpoch +
+ "' vs current: '" + CurrentEpoch + "'");
+ }
+ }
+ }
+ }
+}
+
std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
bool ShouldLazyLoadMetadata) {
if (ResumeBit)
@@ -3552,6 +3614,11 @@ BitcodeReader::parseBitcodeInto(std::unique_ptr<DataStreamer> Streamer,
if (Entry.Kind != BitstreamEntry::SubBlock)
return error("Malformed block");
+ if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) {
+ parseBitcodeVersion();
+ continue;
+ }
+
if (Entry.ID == bitc::MODULE_BLOCK_ID)
return parseModule(0, ShouldLazyLoadMetadata);
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 5b50a905e1b..5e90cd1bf10 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2829,6 +2829,29 @@ static void WriteCombinedFunctionSummary(const FunctionInfoIndex &I,
Stream.ExitBlock();
}
+// Create the "IDENTIFICATION_BLOCK_ID" containing a single string with the
+// current llvm version, and a record for the epoch number.
+static void WriteIdentificationBlock(const Module *M, BitstreamWriter &Stream) {
+ Stream.EnterSubblock(bitc::IDENTIFICATION_BLOCK_ID, 5);
+
+ // Write the "user readable" string identifying the bitcode producer
+ BitCodeAbbrev *Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::IDENTIFICATION_CODE_STRING));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
+ auto StringAbbrev = Stream.EmitAbbrev(Abbv);
+ WriteStringRecord(bitc::IDENTIFICATION_CODE_STRING,
+ "LLVM" LLVM_VERSION_STRING, StringAbbrev, Stream);
+
+ // Write the epoch version
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::IDENTIFICATION_CODE_EPOCH));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
+ SmallVector<unsigned, 1> Vals = {bitc::BITCODE_CURRENT_EPOCH};
+ Stream.EmitRecord(bitc::IDENTIFICATION_CODE_EPOCH, Vals);
+ Stream.ExitBlock();
+}
+
/// WriteModule - Emit the specified module to the bitstream.
static void WriteModule(const Module *M, BitstreamWriter &Stream,
bool ShouldPreserveUseListOrder,
@@ -3000,6 +3023,8 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
// Emit the file header.
WriteBitcodeHeader(Stream);
+ WriteIdentificationBlock(M, Stream);
+
// Emit the module.
WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit,
EmitFunctionSummary);
OpenPOWER on IntegriCloud