Index: llvm/include/llvm/Bitcode/BitstreamWriter.h =================================================================== --- llvm/include/llvm/Bitcode/BitstreamWriter.h +++ llvm/include/llvm/Bitcode/BitstreamWriter.h @@ -201,6 +201,8 @@ return nullptr; } + bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } + void EnterSubblock(unsigned BlockID, unsigned CodeLen) { // Block header: // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4234,6 +4234,12 @@ continue; } + if (Entry.ID == bitc::BLOCKINFO_BLOCK_ID) { + if (Stream.ReadBlockInfoBlock()) + return error("Malformed block"); + continue; + } + if (Entry.ID == bitc::MODULE_BLOCK_ID) return parseModule(0, ShouldLazyLoadMetadata); @@ -6580,6 +6586,12 @@ if (Entry.Kind != BitstreamEntry::SubBlock) return error("Malformed block"); + if (Entry.ID == bitc::BLOCKINFO_BLOCK_ID) { + if (Stream.ReadBlockInfoBlock()) + return error("Malformed block"); + continue; + } + // If we see a MODULE_BLOCK, parse it to find the blocks needed for // building the function summary index. if (Entry.ID == bitc::MODULE_BLOCK_ID) Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -48,20 +48,15 @@ VST_BBENTRY_6_ABBREV, // CONSTANTS_BLOCK abbrev id's. - CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV, - CONSTANTS_INTEGER_ABBREV, - CONSTANTS_CE_CAST_Abbrev, + CONSTANTS_INTEGER_ABBREV = bitc::FIRST_APPLICATION_ABBREV, CONSTANTS_NULL_Abbrev, // FUNCTION_BLOCK abbrev id's. - FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, - FUNCTION_INST_BINOP_ABBREV, + FUNCTION_INST_BINOP_ABBREV = bitc::FIRST_APPLICATION_ABBREV, FUNCTION_INST_BINOP_FLAGS_ABBREV, - FUNCTION_INST_CAST_ABBREV, FUNCTION_INST_RET_VOID_ABBREV, FUNCTION_INST_RET_VAL_ABBREV, FUNCTION_INST_UNREACHABLE_ABBREV, - FUNCTION_INST_GEP_ABBREV, }; /// Abstract class to manage the bitcode writing, subclassed for each bitcode @@ -127,6 +122,10 @@ /// Tracks the last value id recorded in the GUIDToValueMap. unsigned GlobalValueId; + /// Abbreviations that are local to the module. + unsigned ConstantsSettypeAbbrev, ConstantsCECastAbbrev, + FunctionInstCastAbbrev, FunctionInstGEPAbbrev, FunctionInstLoadAbbrev; + public: /// Constructs a ModuleBitcodeWriter object for the given Module, /// writing to the provided \p Buffer. @@ -800,7 +799,7 @@ Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); SmallVector TypeVals; - uint64_t NumBits = VE.computeBitsRequiredForTypeIndicies(); + uint64_t NumBits = VE.computeBitsRequiredForTypeIndices(); // Abbrev for TYPE_CODE_POINTER. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -2082,8 +2081,7 @@ if (V->getType() != LastTy) { LastTy = V->getType(); Record.push_back(VE.getTypeID(LastTy)); - Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record, - CONSTANTS_SETTYPE_ABBREV); + Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record, ConstantsSettypeAbbrev); Record.clear(); } @@ -2202,7 +2200,7 @@ Record.push_back(getEncodedCastOpcode(CE->getOpcode())); Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); Record.push_back(VE.getValueID(C->getOperand(0))); - AbbrevToUse = CONSTANTS_CE_CAST_Abbrev; + AbbrevToUse = ConstantsCECastAbbrev; } else { assert(CE->getNumOperands() == 2 && "Unknown constant expr!"); Code = bitc::CST_CODE_CE_BINOP; @@ -2365,7 +2363,7 @@ if (Instruction::isCast(I.getOpcode())) { Code = bitc::FUNC_CODE_INST_CAST; if (!pushValueAndType(I.getOperand(0), InstID, Vals)) - AbbrevToUse = FUNCTION_INST_CAST_ABBREV; + AbbrevToUse = FunctionInstCastAbbrev; Vals.push_back(VE.getTypeID(I.getType())); Vals.push_back(getEncodedCastOpcode(I.getOpcode())); } else { @@ -2386,7 +2384,7 @@ case Instruction::GetElementPtr: { Code = bitc::FUNC_CODE_INST_GEP; - AbbrevToUse = FUNCTION_INST_GEP_ABBREV; + AbbrevToUse = FunctionInstGEPAbbrev; auto &GEPInst = cast(I); Vals.push_back(GEPInst.isInBounds()); Vals.push_back(VE.getTypeID(GEPInst.getSourceElementType())); @@ -2632,7 +2630,7 @@ } else { Code = bitc::FUNC_CODE_INST_LOAD; if (!pushValueAndType(I.getOperand(0), InstID, Vals)) // ptr - AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; + AbbrevToUse = FunctionInstLoadAbbrev; } Vals.push_back(VE.getTypeID(I.getType())); Vals.push_back(Log2_32(cast(I).getAlignment())+1); @@ -3026,13 +3024,8 @@ Stream.ExitBlock(); } -// Emit blockinfo, which defines the standard abbreviations etc. -void ModuleBitcodeWriter::writeBlockInfo() { - // We only want to emit block info records for blocks that have multiple - // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. - // Other blocks can define their abbrevs inline. - Stream.EnterBlockInfoBlock(2); - +// Write block info abbreviations that are independent of the module contents. +static void writeGlobalBlockInfoAbbrevs(BitstreamWriter &Stream) { { // 8-bit fixed-width VST_CODE_ENTRY/VST_CODE_BBENTRY strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); @@ -3077,16 +3070,6 @@ - { // SETTYPE abbrev for CONSTANTS_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); - Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - VE.computeBitsRequiredForTypeIndicies())); - if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != - CONSTANTS_SETTYPE_ABBREV) - llvm_unreachable("Unexpected abbrev ordering!"); - } - { // INTEGER abbrev for CONSTANTS_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER)); @@ -3096,18 +3079,6 @@ llvm_unreachable("Unexpected abbrev ordering!"); } - { // CE_CAST abbrev for CONSTANTS_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); - Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid - VE.computeBitsRequiredForTypeIndicies())); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id - - if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != - CONSTANTS_CE_CAST_Abbrev) - llvm_unreachable("Unexpected abbrev ordering!"); - } { // NULL abbrev for CONSTANTS_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL)); @@ -3118,18 +3089,6 @@ // FIXME: This should only use space for first class types! - { // INST_LOAD abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); - Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != - FUNCTION_INST_LOAD_ABBREV) - llvm_unreachable("Unexpected abbrev ordering!"); - } { // INST_BINOP abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); @@ -3151,17 +3110,6 @@ FUNCTION_INST_BINOP_FLAGS_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } - { // INST_CAST abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); - Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != - FUNCTION_INST_CAST_ABBREV) - llvm_unreachable("Unexpected abbrev ordering!"); - } { // INST_RET abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -3185,17 +3133,68 @@ FUNCTION_INST_UNREACHABLE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } +} + +// Emit blockinfo, which defines the standard abbreviations etc. +void ModuleBitcodeWriter::writeBlockInfo() { + // We only want to emit block info records for blocks that have multiple + // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. + // Other blocks can define their abbrevs inline. + Stream.EnterBlockInfoBlock(2); + + // Only emit the global block info abbreviations once. + if (!Stream.hasBlockInfoRecords()) + writeGlobalBlockInfoAbbrevs(Stream); + + uint64_t NumBits = VE.computeBitsRequiredForTypeIndices(); + + { // SETTYPE abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); + ConstantsSettypeAbbrev = + Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv); + } + { // CE_CAST abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); // typeid + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id + ConstantsCECastAbbrev = + Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv); + } + + // FIXME: This should only use space for first class types! + + { // INST_LOAD abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); // dest ty + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile + FunctionInstLoadAbbrev = + Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv); + } + { // INST_CAST abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); // dest ty + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + FunctionInstCastAbbrev = + Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv); + } { BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_GEP)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - Log2_32_Ceil(VE.getTypes().size() + 1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); // dest ty Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != - FUNCTION_INST_GEP_ABBREV) - llvm_unreachable("Unexpected abbrev ordering!"); + FunctionInstGEPAbbrev = + Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv); } Stream.ExitBlock(); @@ -3661,6 +3660,9 @@ } void ModuleBitcodeWriter::writeModule() { + // Emit blockinfo, which defines the standard abbreviations etc. + writeBlockInfo(); + Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); size_t BlockStartPos = Buffer.size(); @@ -3669,9 +3671,6 @@ Vals.push_back(CurVersion); Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); - // Emit blockinfo, which defines the standard abbreviations etc. - writeBlockInfo(); - // Emit information about attribute groups. writeAttributeGroupTable(); Index: llvm/lib/Bitcode/Writer/ValueEnumerator.h =================================================================== --- llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ llvm/lib/Bitcode/Writer/ValueEnumerator.h @@ -226,7 +226,7 @@ /// void incorporateFunction(const Function &F); void purgeFunction(); - uint64_t computeBitsRequiredForTypeIndicies() const; + uint64_t computeBitsRequiredForTypeIndices() const; private: void OptimizeConstants(unsigned CstStart, unsigned CstEnd); Index: llvm/lib/Bitcode/Writer/ValueEnumerator.cpp =================================================================== --- llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -1000,6 +1000,6 @@ return getGlobalBasicBlockID(BB); } -uint64_t ValueEnumerator::computeBitsRequiredForTypeIndicies() const { +uint64_t ValueEnumerator::computeBitsRequiredForTypeIndices() const { return Log2_32_Ceil(getTypes().size() + 1); }