Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp (revision 167527) +++ lib/Bitcode/Writer/BitcodeWriter.cpp (working copy) @@ -32,6 +32,20 @@ #include using namespace llvm; +/// Version 1 introduces relative ID encoding which result in a significant +/// bitcode file size savings. Active in LLVM 3.2. +/// +/// Version 0 was active up to LLVM 3.1, but bitcode compatibility was never a +/// guarantee. Multiple LLVM versions have resulted in bitcode enhancements +/// which have broken compatibility with older BitcodeReaders. +static int CurrentVersion = 1; + +static cl::opt +EmitBitcodeVersion("emit-bitcode-version", + cl::desc("Emit bitcode that will be usable by older " + "versions of LLVM."), + cl::init(CurrentVersion), cl::Hidden); + static cl::opt EnablePreserveUseListOrdering("enable-bc-uselist-preserve", cl::desc("Turn on experimental support for " @@ -1016,6 +1030,29 @@ } } +static void VersionSensitivePushValue(SmallVector &Vals, + unsigned InstID, + unsigned ValID) +{ + // Bitcode Version 0 did not have relative ID encoding + if (CurrentVersion == 0) + Vals.push_back(ValID); + // Bitcode Version 1 introduces relative ID encoding + else + Vals.push_back(InstID - ValID); +} + +static void VersionSensitivePushValue64(SmallVector &Vals, + unsigned InstID, + unsigned ValID) +{ + // Bitcode Version 0 did not have relative ID encoding + if (CurrentVersion == 0) + Vals.push_back(ValID); + // Bitcode Version 1 introduces relative ID encoding + else + Vals.push_back(InstID - ValID); +} /// PushValueAndType - The file has to encode both the value and type id for /// many values, because we need to know what type to create for forward /// references. However, most operands are not forward references, so this type @@ -1028,8 +1065,9 @@ SmallVector &Vals, ValueEnumerator &VE) { unsigned ValID = VE.getValueID(V); - // Make encoding relative to the InstID. - Vals.push_back(InstID - ValID); + + VersionSensitivePushValue(Vals, InstID, ValID); + if (ValID >= InstID) { Vals.push_back(VE.getTypeID(V->getType())); return true; @@ -1043,14 +1081,14 @@ SmallVector &Vals, ValueEnumerator &VE) { unsigned ValID = VE.getValueID(V); - Vals.push_back(InstID - ValID); + VersionSensitivePushValue(Vals, InstID, ValID); } static void pushValue64(const Value *V, unsigned InstID, SmallVector &Vals, ValueEnumerator &VE) { uint64_t ValID = VE.getValueID(V); - Vals.push_back(InstID - ValID); + VersionSensitivePushValue64(Vals, InstID, ValID); } static void pushValueSigned(const Value *V, unsigned InstID, @@ -1284,16 +1322,27 @@ // With the newer instruction encoding, forward references could give // negative valued IDs. This is most common for PHIs, so we use // signed VBRs. - SmallVector Vals64; - Vals64.push_back(VE.getTypeID(PN.getType())); - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { - pushValueSigned(PN.getIncomingValue(i), InstID, Vals64, VE); - Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i))); + if (CurrentVersion == 0) + { + Vals.push_back(VE.getTypeID(PN.getType())); + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + pushValue(PN.getIncomingValue(i), InstID, Vals, VE); + Vals.push_back(VE.getValueID(PN.getIncomingBlock(i))); + } } - // Emit a Vals64 vector and exit. - Stream.EmitRecord(Code, Vals64, AbbrevToUse); - Vals64.clear(); - return; + else + { + SmallVector Vals64; + Vals64.push_back(VE.getTypeID(PN.getType())); + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + pushValueSigned(PN.getIncomingValue(i), InstID, Vals64, VE); + Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i))); + } + // Emit a Vals64 vector and exit. + Stream.EmitRecord(Code, Vals64, AbbrevToUse); + Vals64.clear(); + } + break; } case Instruction::LandingPad: { @@ -1811,8 +1860,7 @@ Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); SmallVector Vals; - unsigned CurVersion = 1; - Vals.push_back(CurVersion); + Vals.push_back(CurrentVersion); Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); // Analyze the module, enumerating globals, functions, etc.