Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -63,7 +63,264 @@ FUNCTION_INST_GEP_ABBREV, }; -static unsigned GetEncodedCastOpcode(unsigned Opcode) { +/// Class to manage the bitcode writing for all bitcode file types. +/// Owns the BitstreamWriter, and includes the main entry point for +/// writing. +class BitcodeWriter { + /// Pointer to the buffer allocated by caller for bitcode writing. + SmallVectorImpl *Buffer; + + /// The stream created and owned by the BitodeWriter. + BitstreamWriter Stream; + + /// Saves the offset of the VSTOffset record that must eventually be + /// backpatched with the offset of the actual VST. + uint64_t VSTOffsetPlaceholder = 0; + +public: + /// Constructs a BitcodeWriter object, and initializes a BitstreamRecord, + /// writing to the provided \p Buffer. + BitcodeWriter(SmallVectorImpl *Buffer) + : Buffer(Buffer), Stream(*Buffer) {} + + virtual ~BitcodeWriter() = default; + + /// Main entry point to write the bitcode file, which writes the bitcode + /// header and will then invoke the virtual writeBlocks() method. + void write(); + +private: + /// Derived classes must implement this to write the corresponding blocks for + /// that bitcode file type. + virtual void writeBlocks() = 0; + +protected: + bool hasVSTOffsetPlaceholder() { return VSTOffsetPlaceholder != 0; } + uint64_t getVSTOffsetPlaceholder() { return VSTOffsetPlaceholder; } + SmallVectorImpl &buffer() { return *Buffer; } + BitstreamWriter &stream() { return Stream; } + void writeValueSymbolTableForwardDecl(); + void writeBitcodeHeader(); +}; + +/// Class to manage the bitcode writing for a module. +class ModuleBitcodeWriter : public BitcodeWriter { + /// The Module to write to bitcode. + const Module *M; + + /// Enumerates ids for all values in the module. + ValueEnumerator VE; + + /// Optional per-module index to write for ThinLTO. + const ModuleSummaryIndex *Index; + + /// True if a module hash record should be written. + bool GenerateHash; + + /// The start bit of the module block, for use in generating a module hash + uint64_t BitcodeStartBit = 0; + +public: + /// Constructs a ModuleBitcodeWriter object for the given Module, + /// writing to the provided \p Buffer. + ModuleBitcodeWriter(const Module *M, SmallVectorImpl *Buffer, + bool ShouldPreserveUseListOrder, + const ModuleSummaryIndex *Index, bool GenerateHash) + : BitcodeWriter(Buffer), M(M), VE(*M, ShouldPreserveUseListOrder), + Index(Index), GenerateHash(GenerateHash) { + // Save the start bit of the actual bitcode, in case there is space + // saved at the start for the darwin header above. The reader stream + // will start at the bitcode, and we need the offset of the VST + // to line up. + BitcodeStartBit = stream().GetCurrentBitNo(); + } + +private: + /// Main entry point for writing a module to bitcode, invoked by + /// BitcodeWriter::write() after it writes the header. + void writeBlocks() override; + + /// Create the "IDENTIFICATION_BLOCK_ID" containing a single string with the + /// current llvm version, and a record for the epoch number. + void writeIdentificationBlock(); + + /// Emit the current module to the bitstream. + void writeModule(); + + uint64_t bitcodeStartBit() { return BitcodeStartBit; } + + void writeStringRecord(unsigned Code, StringRef Str, unsigned AbbrevToUse); + void writeAttributeGroupTable(); + void writeAttributeTable(); + void writeTypeTable(); + void writeComdats(); + void writeModuleInfo(); + void writeValueAsMetadata(const ValueAsMetadata *MD, + SmallVectorImpl &Record); + void writeMDTuple(const MDTuple *N, SmallVectorImpl &Record, + unsigned Abbrev); + unsigned createDILocationAbbrev(); + void writeDILocation(const DILocation *N, SmallVectorImpl &Record, + unsigned &Abbrev); + unsigned createGenericDINodeAbbrev(); + void writeGenericDINode(const GenericDINode *N, + SmallVectorImpl &Record, unsigned &Abbrev); + void writeDISubrange(const DISubrange *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIEnumerator(const DIEnumerator *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDIBasicType(const DIBasicType *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIDerivedType(const DIDerivedType *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDICompositeType(const DICompositeType *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDISubroutineType(const DISubroutineType *N, + SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIFile(const DIFile *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDICompileUnit(const DICompileUnit *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDISubprogram(const DISubprogram *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDILexicalBlock(const DILexicalBlock *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDILexicalBlockFile(const DILexicalBlockFile *N, + SmallVectorImpl &Record, + unsigned Abbrev); + void writeDINamespace(const DINamespace *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIMacro(const DIMacro *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIMacroFile(const DIMacroFile *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIModule(const DIModule *N, SmallVectorImpl &Record, + unsigned Abbrev); + void writeDITemplateTypeParameter(const DITemplateTypeParameter *N, + SmallVectorImpl &Record, + unsigned Abbrev); + void writeDITemplateValueParameter(const DITemplateValueParameter *N, + SmallVectorImpl &Record, + unsigned Abbrev); + void writeDIGlobalVariable(const DIGlobalVariable *N, + SmallVectorImpl &Record, + unsigned Abbrev); + void writeDILocalVariable(const DILocalVariable *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDIExpression(const DIExpression *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDIObjCProperty(const DIObjCProperty *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDIImportedEntity(const DIImportedEntity *N, + SmallVectorImpl &Record, + unsigned Abbrev); + unsigned createNamedMetadataAbbrev(); + void writeNamedMetadata(SmallVectorImpl &Record); + unsigned createMetadataStringsAbbrev(); + void writeMetadataStrings(ArrayRef Strings, + SmallVectorImpl &Record); + void writeMetadataRecords(ArrayRef MDs, + SmallVectorImpl &Record); + void writeModuleMetadata(); + void writeFunctionMetadata(const Function &F); + void writeMetadataAttachment(const Function &F); + void writeModuleMetadataStore(); + void writeOperandBundleTags(); + void writeConstants(unsigned FirstVal, unsigned LastVal, bool isGlobal); + void writeModuleConstants(); + bool pushValueAndType(const Value *V, unsigned InstID, + SmallVectorImpl &Vals); + void writeOperandBundles(ImmutableCallSite CS, unsigned InstID); + void pushValue(const Value *V, unsigned InstID, + SmallVectorImpl &Vals); + void pushValueSigned(const Value *V, unsigned InstID, + SmallVectorImpl &Vals); + void writeInstruction(const Instruction &I, unsigned InstID, + SmallVectorImpl &Vals); + void writeValueSymbolTable( + const ValueSymbolTable &VST, bool IsModuleLevel = false, + DenseMap *FunctionToBitcodeIndex = nullptr); + void writeUseList(UseListOrder &&Order); + void writeUseListBlock(const Function *F); + void + writeFunction(const Function &F, + DenseMap &FunctionToBitcodeIndex); + void writeBlockInfo(); + void writePerModuleFunctionSummaryRecord(SmallVector &NameVals, + GlobalValueInfo *Info, + unsigned ValueID, + unsigned FSCallsAbbrev, + unsigned FSCallsProfileAbbrev, + const Function &F); + void writeModuleLevelReferences(const GlobalVariable &V, + SmallVector &NameVals, + unsigned FSModRefsAbbrev); + void writePerModuleGlobalValueSummary(); + void writeModuleHash(size_t BlockStartPos); +}; + +/// Class to manage the bitcode writing for a combined index. +class IndexBitcodeWriter : public BitcodeWriter { + /// The combined index to write to bitcode. + const ModuleSummaryIndex *Index; + + /// Map that holds the correspondence between the GUID used in the combined + /// index and a value id generated by this class to use in references. + std::map GUIDToValueIdMap; + + /// Tracks the last value id recorded in the GUIDToValueMap. + unsigned GlobalValueId = 0; + +public: + /// Constructs a IndexBitcodeWriter object for the given combined index, + /// writing to the provided \p Buffer. + IndexBitcodeWriter(SmallVectorImpl *Buffer, + const ModuleSummaryIndex *Index) + : BitcodeWriter(Buffer), Index(Index) { + // Assign unique value ids to all functions in the index for use + // in writing out the call graph edges. Save the mapping from GUID + // to the new global value id to use when writing those edges, which + // are currently saved in the index in terms of GUID. + for (auto &II : *Index) + GUIDToValueIdMap[II.first] = ++GlobalValueId; + } + +private: + /// Main entry point for writing a combined index to bitcode, invoked by + /// BitcodeWriter::write() after it writes the header. + void writeBlocks() override; + + void writeIndex(); + void writeModStrings(); + void writeCombinedValueSymbolTable(); + void writeCombinedGlobalValueSummary(); + + bool hasValueId(GlobalValue::GUID ValGUID) { + const auto &VMI = GUIDToValueIdMap.find(ValGUID); + return VMI != GUIDToValueIdMap.end(); + } + unsigned getValueId(GlobalValue::GUID ValGUID) { + const auto &VMI = GUIDToValueIdMap.find(ValGUID); + // If this GUID doesn't have an entry, assign one. + if (VMI == GUIDToValueIdMap.end()) { + GUIDToValueIdMap[ValGUID] = ++GlobalValueId; + return GlobalValueId; + } else { + return VMI->second; + } + } + unsigned popValueId(GlobalValue::GUID ValGUID) { + const auto &VMI = GUIDToValueIdMap.find(ValGUID); + assert(VMI != GUIDToValueIdMap.end()); + unsigned ValueId = VMI->second; + GUIDToValueIdMap.erase(VMI); + return ValueId; + } + std::map &valueIds() { return GUIDToValueIdMap; } +}; + +static unsigned getEncodedCastOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown cast instruction!"); case Instruction::Trunc : return bitc::CAST_TRUNC; @@ -82,7 +339,7 @@ } } -static unsigned GetEncodedBinaryOpcode(unsigned Opcode) { +static unsigned getEncodedBinaryOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown binary instruction!"); case Instruction::Add: @@ -106,7 +363,7 @@ } } -static unsigned GetEncodedRMWOperation(AtomicRMWInst::BinOp Op) { +static unsigned getEncodedRMWOperation(AtomicRMWInst::BinOp Op) { switch (Op) { default: llvm_unreachable("Unknown RMW operation!"); case AtomicRMWInst::Xchg: return bitc::RMW_XCHG; @@ -123,7 +380,7 @@ } } -static unsigned GetEncodedOrdering(AtomicOrdering Ordering) { +static unsigned getEncodedOrdering(AtomicOrdering Ordering) { switch (Ordering) { case AtomicOrdering::NotAtomic: return bitc::ORDERING_NOTATOMIC; case AtomicOrdering::Unordered: return bitc::ORDERING_UNORDERED; @@ -136,7 +393,7 @@ llvm_unreachable("Invalid ordering"); } -static unsigned GetEncodedSynchScope(SynchronizationScope SynchScope) { +static unsigned getEncodedSynchScope(SynchronizationScope SynchScope) { switch (SynchScope) { case SingleThread: return bitc::SYNCHSCOPE_SINGLETHREAD; case CrossThread: return bitc::SYNCHSCOPE_CROSSTHREAD; @@ -144,8 +401,8 @@ llvm_unreachable("Invalid synch scope"); } -static void WriteStringRecord(unsigned Code, StringRef Str, - unsigned AbbrevToUse, BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeStringRecord(unsigned Code, StringRef Str, + unsigned AbbrevToUse) { SmallVector Vals; // Code: [strchar x N] @@ -156,7 +413,7 @@ } // Emit the finished record. - Stream.EmitRecord(Code, Vals, AbbrevToUse); + stream().EmitRecord(Code, Vals, AbbrevToUse); } static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { @@ -272,12 +529,11 @@ llvm_unreachable("Trying to encode unknown attribute"); } -static void WriteAttributeGroupTable(const ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeAttributeGroupTable() { const std::vector &AttrGrps = VE.getAttributeGroups(); if (AttrGrps.empty()) return; - Stream.EnterSubblock(bitc::PARAMATTR_GROUP_BLOCK_ID, 3); + stream().EnterSubblock(bitc::PARAMATTR_GROUP_BLOCK_ID, 3); SmallVector Record; for (unsigned i = 0, e = AttrGrps.size(); i != e; ++i) { @@ -312,20 +568,19 @@ } } - Stream.EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record); + stream().EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record); Record.clear(); } } - Stream.ExitBlock(); + stream().ExitBlock(); } -static void WriteAttributeTable(const ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeAttributeTable() { const std::vector &Attrs = VE.getAttributes(); if (Attrs.empty()) return; - Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); + stream().EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); SmallVector Record; for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { @@ -333,18 +588,18 @@ for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) Record.push_back(VE.getAttributeGroupID(A.getSlotAttributes(i))); - Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); + stream().EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); Record.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } /// WriteTypeTable - Write out the type table for a module. -static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeTypeTable() { const ValueEnumerator::TypeList &TypeList = VE.getTypes(); - Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); + stream().EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); SmallVector TypeVals; uint64_t NumBits = VE.computeBitsRequiredForTypeIndicies(); @@ -354,7 +609,7 @@ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0 - unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv); + unsigned PtrAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_FUNCTION. Abbv = new BitCodeAbbrev(); @@ -363,7 +618,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FunctionAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_STRUCT_ANON. Abbv = new BitCodeAbbrev(); @@ -372,14 +627,14 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv); + unsigned StructAnonAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_STRUCT_NAME. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAME)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv); + unsigned StructNameAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_STRUCT_NAMED. Abbv = new BitCodeAbbrev(); @@ -388,7 +643,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv); + unsigned StructNamedAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for TYPE_CODE_ARRAY. Abbv = new BitCodeAbbrev(); @@ -396,11 +651,11 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv); + unsigned ArrayAbbrev = stream().EmitAbbrev(Abbv); // Emit an entry count so the reader can reserve space. TypeVals.push_back(TypeList.size()); - Stream.EmitRecord(bitc::TYPE_CODE_NUMENTRY, TypeVals); + stream().EmitRecord(bitc::TYPE_CODE_NUMENTRY, TypeVals); TypeVals.clear(); // Loop over all of the types, emitting each in turn. @@ -469,8 +724,8 @@ // Emit the name if it is present. if (!ST->getName().empty()) - WriteStringRecord(bitc::TYPE_CODE_STRUCT_NAME, ST->getName(), - StructNameAbbrev, Stream); + writeStringRecord(bitc::TYPE_CODE_STRUCT_NAME, ST->getName(), + StructNameAbbrev); } break; } @@ -494,11 +749,11 @@ } // Emit the finished record. - Stream.EmitRecord(Code, TypeVals, AbbrevToUse); + stream().EmitRecord(Code, TypeVals, AbbrevToUse); TypeVals.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } static unsigned getEncodedLinkage(const GlobalValue::LinkageTypes Linkage) { @@ -578,7 +833,7 @@ llvm_unreachable("Invalid selection kind"); } -static void writeComdats(const ValueEnumerator &VE, BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeComdats() { SmallVector Vals; for (const Comdat *C : VE.getComdats()) { // COMDAT: [selection_kind, name] @@ -588,15 +843,15 @@ Vals.push_back(Size); for (char Chr : C->getName()) Vals.push_back((unsigned char)Chr); - Stream.EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0); + stream().EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0); Vals.clear(); } } /// Write a record that will eventually hold the word offset of the /// module-level VST. For now the offset is 0, which will be backpatched -/// after the real VST is written. Returns the bit offset to backpatch. -static uint64_t WriteValueSymbolTableForwardDecl(BitstreamWriter &Stream) { +/// after the real VST is written. Saves the bit offset to backpatch. +void BitcodeWriter::writeValueSymbolTableForwardDecl() { // Write a placeholder value in for the offset of the real VST, // which is written after the function blocks so that it can include // the offset of each function. The placeholder offset will be @@ -607,16 +862,16 @@ // hold the real VST offset. Must use fixed instead of VBR as we don't // know how many VBR chunks to reserve ahead of time. Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - unsigned VSTOffsetAbbrev = Stream.EmitAbbrev(Abbv); + unsigned VSTOffsetAbbrev = stream().EmitAbbrev(Abbv); // Emit the placeholder uint64_t Vals[] = {bitc::MODULE_CODE_VSTOFFSET, 0}; - Stream.EmitRecordWithAbbrev(VSTOffsetAbbrev, Vals); + stream().EmitRecordWithAbbrev(VSTOffsetAbbrev, Vals); - // Compute and return the bit offset to the placeholder, which will be + // Compute and save the bit offset to the placeholder, which will be // patched when the real VST is written. We can simply subtract the 32-bit // fixed size from the current bit number to get the location to backpatch. - return Stream.GetCurrentBitNo() - 32; + VSTOffsetPlaceholder = stream().GetCurrentBitNo() - 32; } enum StringEncoding { SE_Char6, SE_Fixed7, SE_Fixed8 }; @@ -640,18 +895,17 @@ /// Emit top-level description of module, including target triple, inline asm, /// descriptors for global variables, and function prototype info. /// Returns the bit offset to backpatch with the location of the real VST. -static uint64_t WriteModuleInfo(const Module *M, const ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeModuleInfo() { // Emit various pieces of data attached to a module. if (!M->getTargetTriple().empty()) - WriteStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(), - 0/*TODO*/, Stream); + writeStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(), + 0 /*TODO*/); const std::string &DL = M->getDataLayoutStr(); if (!DL.empty()) - WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, DL, 0 /*TODO*/, Stream); + writeStringRecord(bitc::MODULE_CODE_DATALAYOUT, DL, 0 /*TODO*/); if (!M->getModuleInlineAsm().empty()) - WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), - 0/*TODO*/, Stream); + writeStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), + 0 /*TODO*/); // Emit information about sections and GC, computing how many there are. Also // compute the maximum alignment value. @@ -666,8 +920,8 @@ // Give section names unique ID's. unsigned &Entry = SectionMap[GV.getSection()]; if (!Entry) { - WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV.getSection(), - 0/*TODO*/, Stream); + writeStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV.getSection(), + 0 /*TODO*/); Entry = SectionMap.size(); } } @@ -678,8 +932,8 @@ // Give section names unique ID's. unsigned &Entry = SectionMap[F.getSection()]; if (!Entry) { - WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F.getSection(), - 0/*TODO*/, Stream); + writeStringRecord(bitc::MODULE_CODE_SECTIONNAME, F.getSection(), + 0 /*TODO*/); Entry = SectionMap.size(); } } @@ -687,8 +941,7 @@ // Same for GC names. unsigned &Entry = GCMap[F.getGC()]; if (!Entry) { - WriteStringRecord(bitc::MODULE_CODE_GCNAME, F.getGC(), - 0/*TODO*/, Stream); + writeStringRecord(bitc::MODULE_CODE_GCNAME, F.getGC(), 0 /*TODO*/); Entry = GCMap.size(); } } @@ -720,7 +973,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(SectionMap.size()+1))); // Don't bother emitting vis + thread local. - SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv); + SimpleGVarAbbrev = stream().EmitAbbrev(Abbv); } // Emit the global variable information. @@ -754,7 +1007,7 @@ AbbrevToUse = SimpleGVarAbbrev; } - Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse); + stream().EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse); Vals.clear(); } @@ -783,7 +1036,7 @@ F.hasPersonalityFn() ? (VE.getValueID(F.getPersonalityFn()) + 1) : 0); unsigned AbbrevToUse = 0; - Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); + stream().EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); Vals.clear(); } @@ -799,7 +1052,7 @@ Vals.push_back(getEncodedThreadLocalMode(A)); Vals.push_back(A.hasUnnamedAddr()); unsigned AbbrevToUse = 0; - Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); + stream().EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); Vals.clear(); } @@ -811,7 +1064,7 @@ Vals.push_back(VE.getValueID(I.getResolver())); Vals.push_back(getEncodedLinkage(I)); Vals.push_back(getEncodedVisibility(I)); - Stream.EmitRecord(bitc::MODULE_CODE_IFUNC, Vals); + stream().EmitRecord(bitc::MODULE_CODE_IFUNC, Vals); Vals.clear(); } @@ -830,24 +1083,24 @@ Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_SOURCE_FILENAME)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(AbbrevOpToUse); - unsigned FilenameAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FilenameAbbrev = stream().EmitAbbrev(Abbv); for (const auto P : M->getSourceFileName()) Vals.push_back((unsigned char)P); // Emit the finished record. - Stream.EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, FilenameAbbrev); + stream().EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, + FilenameAbbrev); Vals.clear(); } - // If we have a VST, write the VSTOFFSET record placeholder and return - // its offset. + // If we have a VST, write the VSTOFFSET record placeholder. if (M->getValueSymbolTable().empty()) - return 0; - return WriteValueSymbolTableForwardDecl(Stream); + return; + writeValueSymbolTableForwardDecl(); } -static uint64_t GetOptimizationFlags(const Value *V) { +static uint64_t getOptimizationFlags(const Value *V) { uint64_t Flags = 0; if (const auto *OBO = dyn_cast(V)) { @@ -874,34 +1127,32 @@ return Flags; } -static void writeValueAsMetadata(const ValueAsMetadata *MD, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record) { +void ModuleBitcodeWriter::writeValueAsMetadata( + const ValueAsMetadata *MD, SmallVectorImpl &Record) { // Mimic an MDNode with a value as one operand. Value *V = MD->getValue(); Record.push_back(VE.getTypeID(V->getType())); Record.push_back(VE.getValueID(V)); - Stream.EmitRecord(bitc::METADATA_VALUE, Record, 0); + stream().EmitRecord(bitc::METADATA_VALUE, Record, 0); Record.clear(); } -static void writeMDTuple(const MDTuple *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, unsigned Abbrev) { +void ModuleBitcodeWriter::writeMDTuple(const MDTuple *N, + SmallVectorImpl &Record, + unsigned Abbrev) { for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { Metadata *MD = N->getOperand(i); assert(!(MD && isa(MD)) && "Unexpected function-local metadata"); Record.push_back(VE.getMetadataOrNullID(MD)); } - Stream.EmitRecord(N->isDistinct() ? bitc::METADATA_DISTINCT_NODE - : bitc::METADATA_NODE, - Record, Abbrev); + stream().EmitRecord(N->isDistinct() ? bitc::METADATA_DISTINCT_NODE + : bitc::METADATA_NODE, + Record, Abbrev); Record.clear(); } -static unsigned createDILocationAbbrev(BitstreamWriter &Stream) { +unsigned ModuleBitcodeWriter::createDILocationAbbrev() { // Assume the column is usually under 128, and always output the inlined-at // location (it's never more expensive than building an array size 1). BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -911,15 +1162,14 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - return Stream.EmitAbbrev(Abbv); + return stream().EmitAbbrev(Abbv); } -static void writeDILocation(const DILocation *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned &Abbrev) { +void ModuleBitcodeWriter::writeDILocation(const DILocation *N, + SmallVectorImpl &Record, + unsigned &Abbrev) { if (!Abbrev) - Abbrev = createDILocationAbbrev(Stream); + Abbrev = createDILocationAbbrev(); Record.push_back(N->isDistinct()); Record.push_back(N->getLine()); @@ -927,11 +1177,11 @@ Record.push_back(VE.getMetadataID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getInlinedAt())); - Stream.EmitRecord(bitc::METADATA_LOCATION, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_LOCATION, Record, Abbrev); Record.clear(); } -static unsigned createGenericDINodeAbbrev(BitstreamWriter &Stream) { +unsigned ModuleBitcodeWriter::createGenericDINodeAbbrev() { // Assume the column is usually under 128, and always output the inlined-at // location (it's never more expensive than building an array size 1). BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -942,16 +1192,14 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - return Stream.EmitAbbrev(Abbv); + return stream().EmitAbbrev(Abbv); } -static void writeGenericDINode(const GenericDINode *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned &Abbrev) { +void ModuleBitcodeWriter::writeGenericDINode(const GenericDINode *N, + SmallVectorImpl &Record, + unsigned &Abbrev) { if (!Abbrev) - Abbrev = createGenericDINodeAbbrev(Stream); + Abbrev = createGenericDINodeAbbrev(); Record.push_back(N->isDistinct()); Record.push_back(N->getTag()); @@ -960,7 +1208,7 @@ for (auto &I : N->operands()) Record.push_back(VE.getMetadataOrNullID(I)); - Stream.EmitRecord(bitc::METADATA_GENERIC_DEBUG, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_GENERIC_DEBUG, Record, Abbrev); Record.clear(); } @@ -969,34 +1217,31 @@ return I < 0 ? ~(U << 1) : U << 1; } -static void writeDISubrange(const DISubrange *N, const ValueEnumerator &, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getCount()); Record.push_back(rotateSign(N->getLowerBound())); - Stream.EmitRecord(bitc::METADATA_SUBRANGE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_SUBRANGE, Record, Abbrev); Record.clear(); } -static void writeDIEnumerator(const DIEnumerator *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(rotateSign(N->getValue())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); - Stream.EmitRecord(bitc::METADATA_ENUMERATOR, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_ENUMERATOR, Record, Abbrev); Record.clear(); } -static void writeDIBasicType(const DIBasicType *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getTag()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1004,15 +1249,13 @@ Record.push_back(N->getAlignInBits()); Record.push_back(N->getEncoding()); - Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev); Record.clear(); } -static void writeDIDerivedType(const DIDerivedType *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getTag()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1026,15 +1269,13 @@ Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getExtraData())); - Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } -static void writeDICompositeType(const DICompositeType *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDICompositeType( + const DICompositeType *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getTag()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1052,39 +1293,35 @@ Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get())); Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier())); - Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev); Record.clear(); } -static void writeDISubroutineType(const DISubroutineType *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDISubroutineType( + const DISubroutineType *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getFlags()); Record.push_back(VE.getMetadataOrNullID(N->getTypeArray().get())); - Stream.EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev); Record.clear(); } -static void writeDIFile(const DIFile *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIFile(const DIFile *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getRawFilename())); Record.push_back(VE.getMetadataOrNullID(N->getRawDirectory())); - Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_FILE, Record, Abbrev); Record.clear(); } -static void writeDICompileUnit(const DICompileUnit *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N, + SmallVectorImpl &Record, + unsigned Abbrev) { assert(N->isDistinct() && "Expected distinct compile units"); Record.push_back(/* IsDistinct */ true); Record.push_back(N->getSourceLanguage()); @@ -1103,14 +1340,13 @@ Record.push_back(N->getDWOId()); Record.push_back(VE.getMetadataOrNullID(N->getMacros().get())); - Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev); Record.clear(); } -static void writeDISubprogram(const DISubprogram *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDISubprogram(const DISubprogram *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1131,124 +1367,112 @@ Record.push_back(VE.getMetadataOrNullID(N->getDeclaration())); Record.push_back(VE.getMetadataOrNullID(N->getVariables().get())); - Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev); Record.clear(); } -static void writeDILexicalBlock(const DILexicalBlock *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDILexicalBlock(const DILexicalBlock *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(N->getLine()); Record.push_back(N->getColumn()); - Stream.EmitRecord(bitc::METADATA_LEXICAL_BLOCK, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_LEXICAL_BLOCK, Record, Abbrev); Record.clear(); } -static void writeDILexicalBlockFile(const DILexicalBlockFile *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDILexicalBlockFile( + const DILexicalBlockFile *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(N->getDiscriminator()); - Stream.EmitRecord(bitc::METADATA_LEXICAL_BLOCK_FILE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_LEXICAL_BLOCK_FILE, Record, Abbrev); Record.clear(); } -static void writeDINamespace(const DINamespace *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDINamespace(const DINamespace *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(N->getLine()); - Stream.EmitRecord(bitc::METADATA_NAMESPACE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_NAMESPACE, Record, Abbrev); Record.clear(); } -static void writeDIMacro(const DIMacro *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIMacro(const DIMacro *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getMacinfoType()); Record.push_back(N->getLine()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getRawValue())); - Stream.EmitRecord(bitc::METADATA_MACRO, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_MACRO, Record, Abbrev); Record.clear(); } -static void writeDIMacroFile(const DIMacroFile *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIMacroFile(const DIMacroFile *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getMacinfoType()); Record.push_back(N->getLine()); Record.push_back(VE.getMetadataOrNullID(N->getFile())); Record.push_back(VE.getMetadataOrNullID(N->getElements().get())); - Stream.EmitRecord(bitc::METADATA_MACRO_FILE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_MACRO_FILE, Record, Abbrev); Record.clear(); } -static void writeDIModule(const DIModule *N, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIModule(const DIModule *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); for (auto &I : N->operands()) Record.push_back(VE.getMetadataOrNullID(I)); - Stream.EmitRecord(bitc::METADATA_MODULE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_MODULE, Record, Abbrev); Record.clear(); } -static void writeDITemplateTypeParameter(const DITemplateTypeParameter *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDITemplateTypeParameter( + const DITemplateTypeParameter *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getType())); - Stream.EmitRecord(bitc::METADATA_TEMPLATE_TYPE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_TEMPLATE_TYPE, Record, Abbrev); Record.clear(); } -static void writeDITemplateValueParameter(const DITemplateValueParameter *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDITemplateValueParameter( + const DITemplateValueParameter *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getTag()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getType())); Record.push_back(VE.getMetadataOrNullID(N->getValue())); - Stream.EmitRecord(bitc::METADATA_TEMPLATE_VALUE, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_TEMPLATE_VALUE, Record, Abbrev); Record.clear(); } -static void writeDIGlobalVariable(const DIGlobalVariable *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIGlobalVariable( + const DIGlobalVariable *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1261,15 +1485,13 @@ Record.push_back(VE.getMetadataOrNullID(N->getRawVariable())); Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration())); - Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev); Record.clear(); } -static void writeDILocalVariable(const DILocalVariable *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDILocalVariable( + const DILocalVariable *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1279,28 +1501,25 @@ Record.push_back(N->getArg()); Record.push_back(N->getFlags()); - Stream.EmitRecord(bitc::METADATA_LOCAL_VAR, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_LOCAL_VAR, Record, Abbrev); Record.clear(); } -static void writeDIExpression(const DIExpression *N, const ValueEnumerator &, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.reserve(N->getElements().size() + 1); Record.push_back(N->isDistinct()); Record.append(N->elements_begin(), N->elements_end()); - Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev); Record.clear(); } -static void writeDIObjCProperty(const DIObjCProperty *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIObjCProperty(const DIObjCProperty *N, + SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Record.push_back(VE.getMetadataOrNullID(N->getFile())); @@ -1310,15 +1529,13 @@ Record.push_back(N->getAttributes()); Record.push_back(VE.getMetadataOrNullID(N->getType())); - Stream.EmitRecord(bitc::METADATA_OBJC_PROPERTY, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_OBJC_PROPERTY, Record, Abbrev); Record.clear(); } -static void writeDIImportedEntity(const DIImportedEntity *N, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record, - unsigned Abbrev) { +void ModuleBitcodeWriter::writeDIImportedEntity( + const DIImportedEntity *N, SmallVectorImpl &Record, + unsigned Abbrev) { Record.push_back(N->isDistinct()); Record.push_back(N->getTag()); Record.push_back(VE.getMetadataOrNullID(N->getScope())); @@ -1326,56 +1543,54 @@ Record.push_back(N->getLine()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); - Stream.EmitRecord(bitc::METADATA_IMPORTED_ENTITY, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_IMPORTED_ENTITY, Record, Abbrev); Record.clear(); } -static unsigned createNamedMetadataAbbrev(BitstreamWriter &Stream) { +unsigned ModuleBitcodeWriter::createNamedMetadataAbbrev() { BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_NAME)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - return Stream.EmitAbbrev(Abbv); + return stream().EmitAbbrev(Abbv); } -static void writeNamedMetadata(const Module &M, const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record) { - if (M.named_metadata_empty()) +void ModuleBitcodeWriter::writeNamedMetadata( + SmallVectorImpl &Record) { + if (M->named_metadata_empty()) return; - unsigned Abbrev = createNamedMetadataAbbrev(Stream); - for (const NamedMDNode &NMD : M.named_metadata()) { + unsigned Abbrev = createNamedMetadataAbbrev(); + for (const NamedMDNode &NMD : M->named_metadata()) { // Write name. StringRef Str = NMD.getName(); Record.append(Str.bytes_begin(), Str.bytes_end()); - Stream.EmitRecord(bitc::METADATA_NAME, Record, Abbrev); + stream().EmitRecord(bitc::METADATA_NAME, Record, Abbrev); Record.clear(); // Write named metadata operands. for (const MDNode *N : NMD.operands()) Record.push_back(VE.getMetadataID(N)); - Stream.EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0); + stream().EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0); Record.clear(); } } -static unsigned createMetadataStringsAbbrev(BitstreamWriter &Stream) { +unsigned ModuleBitcodeWriter::createMetadataStringsAbbrev() { BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRINGS)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of strings Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // offset to chars Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - return Stream.EmitAbbrev(Abbv); + return stream().EmitAbbrev(Abbv); } /// Write out a record for MDString. /// /// All the metadata strings in a metadata block are emitted in a single /// record. The sizes and strings themselves are shoved into a blob. -static void writeMetadataStrings(ArrayRef Strings, - BitstreamWriter &Stream, - SmallVectorImpl &Record) { +void ModuleBitcodeWriter::writeMetadataStrings( + ArrayRef Strings, SmallVectorImpl &Record) { if (Strings.empty()) return; @@ -1400,14 +1615,12 @@ Blob.append(cast(MD)->getString()); // Emit the final record. - Stream.EmitRecordWithBlob(createMetadataStringsAbbrev(Stream), Record, Blob); + stream().EmitRecordWithBlob(createMetadataStringsAbbrev(), Record, Blob); Record.clear(); } -static void writeMetadataRecords(ArrayRef MDs, - const ValueEnumerator &VE, - BitstreamWriter &Stream, - SmallVectorImpl &Record) { +void ModuleBitcodeWriter::writeMetadataRecords( + ArrayRef MDs, SmallVectorImpl &Record) { if (MDs.empty()) return; @@ -1424,45 +1637,40 @@ llvm_unreachable("Invalid MDNode subclass"); #define HANDLE_MDNODE_LEAF(CLASS) \ case Metadata::CLASS##Kind: \ - write##CLASS(cast(N), VE, Stream, Record, CLASS##Abbrev); \ + write##CLASS(cast(N), Record, CLASS##Abbrev); \ continue; #include "llvm/IR/Metadata.def" } } - writeValueAsMetadata(cast(MD), VE, Stream, Record); + writeValueAsMetadata(cast(MD), Record); } } -static void writeModuleMetadata(const Module &M, - const ValueEnumerator &VE, - BitstreamWriter &Stream) { - if (!VE.hasMDs() && M.named_metadata_empty()) +void ModuleBitcodeWriter::writeModuleMetadata() { + if (!VE.hasMDs() && M->named_metadata_empty()) return; - Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + stream().EnterSubblock(bitc::METADATA_BLOCK_ID, 3); SmallVector Record; - writeMetadataStrings(VE.getMDStrings(), Stream, Record); - writeMetadataRecords(VE.getNonMDStrings(), VE, Stream, Record); - writeNamedMetadata(M, VE, Stream, Record); - Stream.ExitBlock(); + writeMetadataStrings(VE.getMDStrings(), Record); + writeMetadataRecords(VE.getNonMDStrings(), Record); + writeNamedMetadata(Record); + stream().ExitBlock(); } -static void writeFunctionMetadata(const Function &F, const ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeFunctionMetadata(const Function &F) { if (!VE.hasMDs()) return; - Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + stream().EnterSubblock(bitc::METADATA_BLOCK_ID, 3); SmallVector Record; - writeMetadataStrings(VE.getMDStrings(), Stream, Record); - writeMetadataRecords(VE.getNonMDStrings(), VE, Stream, Record); - Stream.ExitBlock(); + writeMetadataStrings(VE.getMDStrings(), Record); + writeMetadataRecords(VE.getNonMDStrings(), Record); + stream().ExitBlock(); } -static void WriteMetadataAttachment(const Function &F, - const ValueEnumerator &VE, - BitstreamWriter &Stream) { - Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3); +void ModuleBitcodeWriter::writeMetadataAttachment(const Function &F) { + stream().EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3); SmallVector Record; @@ -1475,7 +1683,7 @@ Record.push_back(I.first); Record.push_back(VE.getMetadataID(I.second)); } - Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0); + stream().EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0); Record.clear(); } @@ -1493,14 +1701,14 @@ Record.push_back(MDs[i].first); Record.push_back(VE.getMetadataID(MDs[i].second)); } - Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0); + stream().EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0); Record.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } -static void WriteModuleMetadataStore(const Module *M, BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeModuleMetadataStore() { SmallVector Record; // Write metadata kinds @@ -1510,21 +1718,21 @@ if (Names.empty()) return; - Stream.EnterSubblock(bitc::METADATA_KIND_BLOCK_ID, 3); + stream().EnterSubblock(bitc::METADATA_KIND_BLOCK_ID, 3); for (unsigned MDKindID = 0, e = Names.size(); MDKindID != e; ++MDKindID) { Record.push_back(MDKindID); StringRef KName = Names[MDKindID]; Record.append(KName.begin(), KName.end()); - Stream.EmitRecord(bitc::METADATA_KIND, Record, 0); + stream().EmitRecord(bitc::METADATA_KIND, Record, 0); Record.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } -static void WriteOperandBundleTags(const Module *M, BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeOperandBundleTags() { // Write metadata kinds // // OPERAND_BUNDLE_TAGS_BLOCK_ID : N x OPERAND_BUNDLE_TAG @@ -1537,18 +1745,18 @@ if (Tags.empty()) return; - Stream.EnterSubblock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID, 3); + stream().EnterSubblock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID, 3); SmallVector Record; for (auto Tag : Tags) { Record.append(Tag.begin(), Tag.end()); - Stream.EmitRecord(bitc::OPERAND_BUNDLE_TAG, Record, 0); + stream().EmitRecord(bitc::OPERAND_BUNDLE_TAG, Record, 0); Record.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { @@ -1558,12 +1766,11 @@ Vals.push_back((-V << 1) | 1); } -static void WriteConstants(unsigned FirstVal, unsigned LastVal, - const ValueEnumerator &VE, - BitstreamWriter &Stream, bool isGlobal) { +void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, + bool isGlobal) { if (FirstVal == LastVal) return; - Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 4); + stream().EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 4); unsigned AggregateAbbrev = 0; unsigned String8Abbrev = 0; @@ -1576,26 +1783,26 @@ Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_AGGREGATE)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(LastVal+1))); - AggregateAbbrev = Stream.EmitAbbrev(Abbv); + AggregateAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for CST_CODE_STRING. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - String8Abbrev = Stream.EmitAbbrev(Abbv); + String8Abbrev = stream().EmitAbbrev(Abbv); // Abbrev for CST_CODE_CSTRING. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); - CString7Abbrev = Stream.EmitAbbrev(Abbv); + CString7Abbrev = stream().EmitAbbrev(Abbv); // Abbrev for CST_CODE_CSTRING. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - CString6Abbrev = Stream.EmitAbbrev(Abbv); + CString6Abbrev = stream().EmitAbbrev(Abbv); } SmallVector Record; @@ -1608,8 +1815,8 @@ 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, + CONSTANTS_SETTYPE_ABBREV); Record.clear(); } @@ -1627,7 +1834,7 @@ const std::string &ConstraintStr = IA->getConstraintString(); Record.push_back(ConstraintStr.size()); Record.append(ConstraintStr.begin(), ConstraintStr.end()); - Stream.EmitRecord(bitc::CST_CODE_INLINEASM, Record); + stream().EmitRecord(bitc::CST_CODE_INLINEASM, Record); Record.clear(); continue; } @@ -1725,17 +1932,17 @@ default: if (Instruction::isCast(CE->getOpcode())) { Code = bitc::CST_CODE_CE_CAST; - Record.push_back(GetEncodedCastOpcode(CE->getOpcode())); + 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; } else { assert(CE->getNumOperands() == 2 && "Unknown constant expr!"); Code = bitc::CST_CODE_CE_BINOP; - Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode())); + Record.push_back(getEncodedBinaryOpcode(CE->getOpcode())); Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); - uint64_t Flags = GetOptimizationFlags(CE); + uint64_t Flags = getOptimizationFlags(CE); if (Flags != 0) Record.push_back(Flags); } @@ -1807,28 +2014,27 @@ #endif llvm_unreachable("Unknown constant!"); } - Stream.EmitRecord(Code, Record, AbbrevToUse); + stream().EmitRecord(Code, Record, AbbrevToUse); Record.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } -static void WriteModuleConstants(const ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeModuleConstants() { const ValueEnumerator::ValueList &Vals = VE.getValues(); // Find the first constant to emit, which is the first non-globalvalue value. // We know globalvalues have been emitted by WriteModuleInfo. for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (!isa(Vals[i].first)) { - WriteConstants(i, Vals.size(), VE, Stream, true); + writeConstants(i, Vals.size(), true); return; } } } -/// PushValueAndType - The file has to encode both the value and type id for +/// 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 /// field is not needed. @@ -1836,9 +2042,8 @@ /// This function adds V's value ID to Vals. If the value ID is higher than the /// instruction ID, then it is a forward reference, and it also includes the /// type ID. The value ID that is written is encoded relative to the InstID. -static bool PushValueAndType(const Value *V, unsigned InstID, - SmallVectorImpl &Vals, - ValueEnumerator &VE) { +bool ModuleBitcodeWriter::pushValueAndType(const Value *V, unsigned InstID, + SmallVectorImpl &Vals) { unsigned ValID = VE.getValueID(V); // Make encoding relative to the InstID. Vals.push_back(InstID - ValID); @@ -1849,8 +2054,8 @@ return false; } -static void WriteOperandBundles(BitstreamWriter &Stream, ImmutableCallSite CS, - unsigned InstID, ValueEnumerator &VE) { +void ModuleBitcodeWriter::writeOperandBundles(ImmutableCallSite CS, + unsigned InstID) { SmallVector Record; LLVMContext &C = CS.getInstruction()->getContext(); @@ -1859,34 +2064,32 @@ Record.push_back(C.getOperandBundleTagID(Bundle.getTagName())); for (auto &Input : Bundle.Inputs) - PushValueAndType(Input, InstID, Record, VE); + pushValueAndType(Input, InstID, Record); - Stream.EmitRecord(bitc::FUNC_CODE_OPERAND_BUNDLE, Record); + stream().EmitRecord(bitc::FUNC_CODE_OPERAND_BUNDLE, Record); Record.clear(); } } -/// pushValue - Like PushValueAndType, but where the type of the value is +/// pushValue - Like pushValueAndType, but where the type of the value is /// omitted (perhaps it was already encoded in an earlier operand). -static void pushValue(const Value *V, unsigned InstID, - SmallVectorImpl &Vals, - ValueEnumerator &VE) { +void ModuleBitcodeWriter::pushValue(const Value *V, unsigned InstID, + SmallVectorImpl &Vals) { unsigned ValID = VE.getValueID(V); Vals.push_back(InstID - ValID); } -static void pushValueSigned(const Value *V, unsigned InstID, - SmallVectorImpl &Vals, - ValueEnumerator &VE) { +void ModuleBitcodeWriter::pushValueSigned(const Value *V, unsigned InstID, + SmallVectorImpl &Vals) { unsigned ValID = VE.getValueID(V); int64_t diff = ((int32_t)InstID - (int32_t)ValID); emitSignedInt64(Vals, diff); } /// WriteInstruction - Emit an instruction to the specified stream. -static void WriteInstruction(const Instruction &I, unsigned InstID, - ValueEnumerator &VE, BitstreamWriter &Stream, - SmallVectorImpl &Vals) { +void ModuleBitcodeWriter::writeInstruction(const Instruction &I, + unsigned InstID, + SmallVectorImpl &Vals) { unsigned Code = 0; unsigned AbbrevToUse = 0; VE.setInstructionID(&I); @@ -1894,18 +2097,18 @@ default: if (Instruction::isCast(I.getOpcode())) { Code = bitc::FUNC_CODE_INST_CAST; - if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + if (!pushValueAndType(I.getOperand(0), InstID, Vals)) AbbrevToUse = FUNCTION_INST_CAST_ABBREV; Vals.push_back(VE.getTypeID(I.getType())); - Vals.push_back(GetEncodedCastOpcode(I.getOpcode())); + Vals.push_back(getEncodedCastOpcode(I.getOpcode())); } else { assert(isa(I) && "Unknown instruction!"); Code = bitc::FUNC_CODE_INST_BINOP; - if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + if (!pushValueAndType(I.getOperand(0), InstID, Vals)) AbbrevToUse = FUNCTION_INST_BINOP_ABBREV; - pushValue(I.getOperand(1), InstID, Vals, VE); - Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode())); - uint64_t Flags = GetOptimizationFlags(&I); + pushValue(I.getOperand(1), InstID, Vals); + Vals.push_back(getEncodedBinaryOpcode(I.getOpcode())); + uint64_t Flags = getOptimizationFlags(&I); if (Flags != 0) { if (AbbrevToUse == FUNCTION_INST_BINOP_ABBREV) AbbrevToUse = FUNCTION_INST_BINOP_FLAGS_ABBREV; @@ -1921,55 +2124,55 @@ Vals.push_back(GEPInst.isInBounds()); Vals.push_back(VE.getTypeID(GEPInst.getSourceElementType())); for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) - PushValueAndType(I.getOperand(i), InstID, Vals, VE); + pushValueAndType(I.getOperand(i), InstID, Vals); break; } case Instruction::ExtractValue: { Code = bitc::FUNC_CODE_INST_EXTRACTVAL; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); const ExtractValueInst *EVI = cast(&I); Vals.append(EVI->idx_begin(), EVI->idx_end()); break; } case Instruction::InsertValue: { Code = bitc::FUNC_CODE_INST_INSERTVAL; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - PushValueAndType(I.getOperand(1), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValueAndType(I.getOperand(1), InstID, Vals); const InsertValueInst *IVI = cast(&I); Vals.append(IVI->idx_begin(), IVI->idx_end()); break; } case Instruction::Select: Code = bitc::FUNC_CODE_INST_VSELECT; - PushValueAndType(I.getOperand(1), InstID, Vals, VE); - pushValue(I.getOperand(2), InstID, Vals, VE); - PushValueAndType(I.getOperand(0), InstID, Vals, VE); + pushValueAndType(I.getOperand(1), InstID, Vals); + pushValue(I.getOperand(2), InstID, Vals); + pushValueAndType(I.getOperand(0), InstID, Vals); break; case Instruction::ExtractElement: Code = bitc::FUNC_CODE_INST_EXTRACTELT; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - PushValueAndType(I.getOperand(1), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValueAndType(I.getOperand(1), InstID, Vals); break; case Instruction::InsertElement: Code = bitc::FUNC_CODE_INST_INSERTELT; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - pushValue(I.getOperand(1), InstID, Vals, VE); - PushValueAndType(I.getOperand(2), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValue(I.getOperand(1), InstID, Vals); + pushValueAndType(I.getOperand(2), InstID, Vals); break; case Instruction::ShuffleVector: Code = bitc::FUNC_CODE_INST_SHUFFLEVEC; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - pushValue(I.getOperand(1), InstID, Vals, VE); - pushValue(I.getOperand(2), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValue(I.getOperand(1), InstID, Vals); + pushValue(I.getOperand(2), InstID, Vals); break; case Instruction::ICmp: case Instruction::FCmp: { // compare returning Int1Ty or vector of Int1Ty Code = bitc::FUNC_CODE_INST_CMP2; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - pushValue(I.getOperand(1), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValue(I.getOperand(1), InstID, Vals); Vals.push_back(cast(I).getPredicate()); - uint64_t Flags = GetOptimizationFlags(&I); + uint64_t Flags = getOptimizationFlags(&I); if (Flags != 0) Vals.push_back(Flags); break; @@ -1982,11 +2185,11 @@ if (NumOperands == 0) AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV; else if (NumOperands == 1) { - if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + if (!pushValueAndType(I.getOperand(0), InstID, Vals)) AbbrevToUse = FUNCTION_INST_RET_VAL_ABBREV; } else { for (unsigned i = 0, e = NumOperands; i != e; ++i) - PushValueAndType(I.getOperand(i), InstID, Vals, VE); + pushValueAndType(I.getOperand(i), InstID, Vals); } } break; @@ -1997,7 +2200,7 @@ Vals.push_back(VE.getValueID(II.getSuccessor(0))); if (II.isConditional()) { Vals.push_back(VE.getValueID(II.getSuccessor(1))); - pushValue(II.getCondition(), InstID, Vals, VE); + pushValue(II.getCondition(), InstID, Vals); } } break; @@ -2006,7 +2209,7 @@ Code = bitc::FUNC_CODE_INST_SWITCH; const SwitchInst &SI = cast(I); Vals.push_back(VE.getTypeID(SI.getCondition()->getType())); - pushValue(SI.getCondition(), InstID, Vals, VE); + pushValue(SI.getCondition(), InstID, Vals); Vals.push_back(VE.getValueID(SI.getDefaultDest())); for (SwitchInst::ConstCaseIt Case : SI.cases()) { Vals.push_back(VE.getValueID(Case.getCaseValue())); @@ -2018,7 +2221,7 @@ Code = bitc::FUNC_CODE_INST_INDIRECTBR; Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // Encode the address operand as relative, but not the basic blocks. - pushValue(I.getOperand(0), InstID, Vals, VE); + pushValue(I.getOperand(0), InstID, Vals); for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) Vals.push_back(VE.getValueID(I.getOperand(i))); break; @@ -2029,7 +2232,7 @@ FunctionType *FTy = II->getFunctionType(); if (II->hasOperandBundles()) - WriteOperandBundles(Stream, II, InstID, VE); + writeOperandBundles(II, InstID); Code = bitc::FUNC_CODE_INST_INVOKE; @@ -2038,28 +2241,28 @@ Vals.push_back(VE.getValueID(II->getNormalDest())); Vals.push_back(VE.getValueID(II->getUnwindDest())); Vals.push_back(VE.getTypeID(FTy)); - PushValueAndType(Callee, InstID, Vals, VE); + pushValueAndType(Callee, InstID, Vals); // Emit value #'s for the fixed parameters. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) - pushValue(I.getOperand(i), InstID, Vals, VE); // fixed param. + pushValue(I.getOperand(i), InstID, Vals); // fixed param. // Emit type/value pairs for varargs params. if (FTy->isVarArg()) { for (unsigned i = FTy->getNumParams(), e = I.getNumOperands()-3; i != e; ++i) - PushValueAndType(I.getOperand(i), InstID, Vals, VE); // vararg + pushValueAndType(I.getOperand(i), InstID, Vals); // vararg } break; } case Instruction::Resume: Code = bitc::FUNC_CODE_INST_RESUME; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); break; case Instruction::CleanupRet: { Code = bitc::FUNC_CODE_INST_CLEANUPRET; const auto &CRI = cast(I); - pushValue(CRI.getCleanupPad(), InstID, Vals, VE); + pushValue(CRI.getCleanupPad(), InstID, Vals); if (CRI.hasUnwindDest()) Vals.push_back(VE.getValueID(CRI.getUnwindDest())); break; @@ -2067,7 +2270,7 @@ case Instruction::CatchRet: { Code = bitc::FUNC_CODE_INST_CATCHRET; const auto &CRI = cast(I); - pushValue(CRI.getCatchPad(), InstID, Vals, VE); + pushValue(CRI.getCatchPad(), InstID, Vals); Vals.push_back(VE.getValueID(CRI.getSuccessor())); break; } @@ -2076,19 +2279,19 @@ const auto &FuncletPad = cast(I); Code = isa(FuncletPad) ? bitc::FUNC_CODE_INST_CATCHPAD : bitc::FUNC_CODE_INST_CLEANUPPAD; - pushValue(FuncletPad.getParentPad(), InstID, Vals, VE); + pushValue(FuncletPad.getParentPad(), InstID, Vals); unsigned NumArgOperands = FuncletPad.getNumArgOperands(); Vals.push_back(NumArgOperands); for (unsigned Op = 0; Op != NumArgOperands; ++Op) - PushValueAndType(FuncletPad.getArgOperand(Op), InstID, Vals, VE); + pushValueAndType(FuncletPad.getArgOperand(Op), InstID, Vals); break; } case Instruction::CatchSwitch: { Code = bitc::FUNC_CODE_INST_CATCHSWITCH; const auto &CatchSwitch = cast(I); - pushValue(CatchSwitch.getParentPad(), InstID, Vals, VE); + pushValue(CatchSwitch.getParentPad(), InstID, Vals); unsigned NumHandlers = CatchSwitch.getNumHandlers(); Vals.push_back(NumHandlers); @@ -2113,11 +2316,11 @@ 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); + pushValueSigned(PN.getIncomingValue(i), InstID, Vals64); Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i))); } // Emit a Vals64 vector and exit. - Stream.EmitRecord(Code, Vals64, AbbrevToUse); + stream().EmitRecord(Code, Vals64, AbbrevToUse); Vals64.clear(); return; } @@ -2133,7 +2336,7 @@ Vals.push_back(LandingPadInst::Catch); else Vals.push_back(LandingPadInst::Filter); - PushValueAndType(LP.getClause(I), InstID, Vals, VE); + pushValueAndType(LP.getClause(I), InstID, Vals); } break; } @@ -2158,18 +2361,18 @@ case Instruction::Load: if (cast(I).isAtomic()) { Code = bitc::FUNC_CODE_INST_LOADATOMIC; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); + pushValueAndType(I.getOperand(0), InstID, Vals); } else { Code = bitc::FUNC_CODE_INST_LOAD; - if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr + if (!pushValueAndType(I.getOperand(0), InstID, Vals)) // ptr AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; } Vals.push_back(VE.getTypeID(I.getType())); Vals.push_back(Log2_32(cast(I).getAlignment())+1); Vals.push_back(cast(I).isVolatile()); if (cast(I).isAtomic()) { - Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); - Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope())); + Vals.push_back(getEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(getEncodedSynchScope(cast(I).getSynchScope())); } break; case Instruction::Store: @@ -2177,57 +2380,57 @@ Code = bitc::FUNC_CODE_INST_STOREATOMIC; else Code = bitc::FUNC_CODE_INST_STORE; - PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr - PushValueAndType(I.getOperand(0), InstID, Vals, VE); // valty + val + pushValueAndType(I.getOperand(1), InstID, Vals); // ptrty + ptr + pushValueAndType(I.getOperand(0), InstID, Vals); // valty + val Vals.push_back(Log2_32(cast(I).getAlignment())+1); Vals.push_back(cast(I).isVolatile()); if (cast(I).isAtomic()) { - Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); - Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope())); + Vals.push_back(getEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(getEncodedSynchScope(cast(I).getSynchScope())); } break; case Instruction::AtomicCmpXchg: Code = bitc::FUNC_CODE_INST_CMPXCHG; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr - PushValueAndType(I.getOperand(1), InstID, Vals, VE); // cmp. - pushValue(I.getOperand(2), InstID, Vals, VE); // newval. + pushValueAndType(I.getOperand(0), InstID, Vals); // ptrty + ptr + pushValueAndType(I.getOperand(1), InstID, Vals); // cmp. + pushValue(I.getOperand(2), InstID, Vals); // newval. Vals.push_back(cast(I).isVolatile()); - Vals.push_back(GetEncodedOrdering( - cast(I).getSuccessOrdering())); - Vals.push_back(GetEncodedSynchScope( - cast(I).getSynchScope())); - Vals.push_back(GetEncodedOrdering( - cast(I).getFailureOrdering())); + Vals.push_back( + getEncodedOrdering(cast(I).getSuccessOrdering())); + Vals.push_back( + getEncodedSynchScope(cast(I).getSynchScope())); + Vals.push_back( + getEncodedOrdering(cast(I).getFailureOrdering())); Vals.push_back(cast(I).isWeak()); break; case Instruction::AtomicRMW: Code = bitc::FUNC_CODE_INST_ATOMICRMW; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr - pushValue(I.getOperand(1), InstID, Vals, VE); // val. - Vals.push_back(GetEncodedRMWOperation( - cast(I).getOperation())); + pushValueAndType(I.getOperand(0), InstID, Vals); // ptrty + ptr + pushValue(I.getOperand(1), InstID, Vals); // val. + Vals.push_back( + getEncodedRMWOperation(cast(I).getOperation())); Vals.push_back(cast(I).isVolatile()); - Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); - Vals.push_back(GetEncodedSynchScope( - cast(I).getSynchScope())); + Vals.push_back(getEncodedOrdering(cast(I).getOrdering())); + Vals.push_back( + getEncodedSynchScope(cast(I).getSynchScope())); break; case Instruction::Fence: Code = bitc::FUNC_CODE_INST_FENCE; - Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); - Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope())); + Vals.push_back(getEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(getEncodedSynchScope(cast(I).getSynchScope())); break; case Instruction::Call: { const CallInst &CI = cast(I); FunctionType *FTy = CI.getFunctionType(); if (CI.hasOperandBundles()) - WriteOperandBundles(Stream, &CI, InstID, VE); + writeOperandBundles(&CI, InstID); Code = bitc::FUNC_CODE_INST_CALL; Vals.push_back(VE.getAttributeID(CI.getAttributes())); - unsigned Flags = GetOptimizationFlags(&I); + unsigned Flags = getOptimizationFlags(&I); Vals.push_back(CI.getCallingConv() << bitc::CALL_CCONV | unsigned(CI.isTailCall()) << bitc::CALL_TAIL | unsigned(CI.isMustTailCall()) << bitc::CALL_MUSTTAIL | @@ -2238,7 +2441,7 @@ Vals.push_back(Flags); Vals.push_back(VE.getTypeID(FTy)); - PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee + pushValueAndType(CI.getCalledValue(), InstID, Vals); // Callee // Emit value #'s for the fixed parameters. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { @@ -2246,65 +2449,62 @@ if (FTy->getParamType(i)->isLabelTy()) Vals.push_back(VE.getValueID(CI.getArgOperand(i))); else - pushValue(CI.getArgOperand(i), InstID, Vals, VE); // fixed param. + pushValue(CI.getArgOperand(i), InstID, Vals); // fixed param. } // Emit type/value pairs for varargs params. if (FTy->isVarArg()) { for (unsigned i = FTy->getNumParams(), e = CI.getNumArgOperands(); i != e; ++i) - PushValueAndType(CI.getArgOperand(i), InstID, Vals, VE); // varargs + pushValueAndType(CI.getArgOperand(i), InstID, Vals); // varargs } break; } case Instruction::VAArg: Code = bitc::FUNC_CODE_INST_VAARG; Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty - pushValue(I.getOperand(0), InstID, Vals, VE); // valist. + pushValue(I.getOperand(0), InstID, Vals); // valist. Vals.push_back(VE.getTypeID(I.getType())); // restype. break; } - Stream.EmitRecord(Code, Vals, AbbrevToUse); + stream().EmitRecord(Code, Vals, AbbrevToUse); Vals.clear(); } -/// Emit names for globals/functions etc. The VSTOffsetPlaceholder, -/// BitcodeStartBit and ModuleSummaryIndex are only passed for the module-level -/// VST, where we are including a function bitcode index and need to -/// backpatch the VST forward declaration record. -static void WriteValueSymbolTable( - const ValueSymbolTable &VST, const ValueEnumerator &VE, - BitstreamWriter &Stream, uint64_t VSTOffsetPlaceholder = 0, - uint64_t BitcodeStartBit = 0, - DenseMap *FunctionToBitcodeIndex = nullptr) { +/// Emit names for globals/functions etc. \p IsModuleLevel is true when +/// we are writing the module-level VST, where we are including a function +/// bitcode index and need to backpatch the VST forward declaration record. +void ModuleBitcodeWriter::writeValueSymbolTable( + const ValueSymbolTable &VST, bool IsModuleLevel, + DenseMap *FunctionToBitcodeIndex) { if (VST.empty()) { - // WriteValueSymbolTableForwardDecl should have returned early as + // writeValueSymbolTableForwardDecl should have returned early as // well. Ensure this handling remains in sync by asserting that // the placeholder offset is not set. - assert(VSTOffsetPlaceholder == 0); + assert(!IsModuleLevel || !hasVSTOffsetPlaceholder()); return; } - if (VSTOffsetPlaceholder > 0) { + if (IsModuleLevel && hasVSTOffsetPlaceholder()) { // Get the offset of the VST we are writing, and backpatch it into // the VST forward declaration record. - uint64_t VSTOffset = Stream.GetCurrentBitNo(); + uint64_t VSTOffset = stream().GetCurrentBitNo(); // The BitcodeStartBit was the stream offset of the actual bitcode // (e.g. excluding any initial darwin header). - VSTOffset -= BitcodeStartBit; + VSTOffset -= bitcodeStartBit(); assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned"); - Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32); + stream().BackpatchWord(getVSTOffsetPlaceholder(), VSTOffset / 32); } - Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4); + stream().EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4); // For the module-level VST, add abbrev Ids for the VST_CODE_FNENTRY // records, which are not used in the per-function VSTs. unsigned FnEntry8BitAbbrev; unsigned FnEntry7BitAbbrev; unsigned FnEntry6BitAbbrev; - if (VSTOffsetPlaceholder > 0) { + if (IsModuleLevel && hasVSTOffsetPlaceholder()) { // 8-bit fixed-width VST_CODE_FNENTRY function strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY)); @@ -2312,7 +2512,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - FnEntry8BitAbbrev = Stream.EmitAbbrev(Abbv); + FnEntry8BitAbbrev = stream().EmitAbbrev(Abbv); // 7-bit fixed width VST_CODE_FNENTRY function strings. Abbv = new BitCodeAbbrev(); @@ -2321,7 +2521,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); - FnEntry7BitAbbrev = Stream.EmitAbbrev(Abbv); + FnEntry7BitAbbrev = stream().EmitAbbrev(Abbv); // 6-bit char6 VST_CODE_FNENTRY function strings. Abbv = new BitCodeAbbrev(); @@ -2330,7 +2530,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - FnEntry6BitAbbrev = Stream.EmitAbbrev(Abbv); + FnEntry6BitAbbrev = stream().EmitAbbrev(Abbv); } // FIXME: Set up the abbrev, we know how many values there are! @@ -2367,11 +2567,11 @@ // have a VSTOffsetPlaceholder. The function-level VST should not // contain any Function symbols. assert(FunctionToBitcodeIndex); - assert(VSTOffsetPlaceholder > 0); + assert(hasVSTOffsetPlaceholder()); // Save the word offset of the function (from the start of the // actual bitcode written to the stream). - uint64_t BitcodeIndex = (*FunctionToBitcodeIndex)[F] - BitcodeStartBit; + uint64_t BitcodeIndex = (*FunctionToBitcodeIndex)[F] - bitcodeStartBit(); assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned"); NameVals.push_back(BitcodeIndex / 32); @@ -2393,74 +2593,68 @@ NameVals.push_back((unsigned char)P); // Emit the finished record. - Stream.EmitRecord(Code, NameVals, AbbrevToUse); + stream().EmitRecord(Code, NameVals, AbbrevToUse); NameVals.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } /// Emit function names and summary offsets for the combined index /// used by ThinLTO. -static void WriteCombinedValueSymbolTable( - const ModuleSummaryIndex &Index, BitstreamWriter &Stream, - std::map &GUIDToValueIdMap, - uint64_t VSTOffsetPlaceholder) { - assert(VSTOffsetPlaceholder > 0 && "Expected non-zero VSTOffsetPlaceholder"); +void IndexBitcodeWriter::writeCombinedValueSymbolTable() { + assert(hasVSTOffsetPlaceholder() && "Expected non-zero VSTOffsetPlaceholder"); // Get the offset of the VST we are writing, and backpatch it into // the VST forward declaration record. - uint64_t VSTOffset = Stream.GetCurrentBitNo(); + uint64_t VSTOffset = stream().GetCurrentBitNo(); assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned"); - Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32); + stream().BackpatchWord(getVSTOffsetPlaceholder(), VSTOffset / 32); - Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4); + stream().EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4); BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_GVDEFENTRY)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // sumoffset Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // guid - unsigned DefEntryAbbrev = Stream.EmitAbbrev(Abbv); + unsigned DefEntryAbbrev = stream().EmitAbbrev(Abbv); Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_ENTRY)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // refguid - unsigned EntryAbbrev = Stream.EmitAbbrev(Abbv); + unsigned EntryAbbrev = stream().EmitAbbrev(Abbv); SmallVector NameVals; - for (const auto &FII : Index) { + for (const auto &FII : *Index) { GlobalValue::GUID FuncGUID = FII.first; - const auto &VMI = GUIDToValueIdMap.find(FuncGUID); - assert(VMI != GUIDToValueIdMap.end()); + unsigned ValueId = popValueId(FuncGUID); for (const auto &FI : FII.second) { // VST_CODE_COMBINED_GVDEFENTRY: [valueid, sumoffset, guid] - NameVals.push_back(VMI->second); + NameVals.push_back(ValueId); NameVals.push_back(FI->bitcodeIndex()); NameVals.push_back(FuncGUID); // Emit the finished record. - Stream.EmitRecord(bitc::VST_CODE_COMBINED_GVDEFENTRY, NameVals, - DefEntryAbbrev); + stream().EmitRecord(bitc::VST_CODE_COMBINED_GVDEFENTRY, NameVals, + DefEntryAbbrev); NameVals.clear(); } - GUIDToValueIdMap.erase(VMI); } - for (const auto &GVI : GUIDToValueIdMap) { + for (const auto &GVI : valueIds()) { // VST_CODE_COMBINED_ENTRY: [valueid, refguid] NameVals.push_back(GVI.second); NameVals.push_back(GVI.first); // Emit the finished record. - Stream.EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals, EntryAbbrev); + stream().EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals, EntryAbbrev); NameVals.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } -static void WriteUseList(ValueEnumerator &VE, UseListOrder &&Order, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeUseList(UseListOrder &&Order) { assert(Order.Shuffle.size() >= 2 && "Shuffle too small"); unsigned Code; if (isa(Order.V)) @@ -2470,11 +2664,10 @@ SmallVector Record(Order.Shuffle.begin(), Order.Shuffle.end()); Record.push_back(VE.getValueID(Order.V)); - Stream.EmitRecord(Code, Record); + stream().EmitRecord(Code, Record); } -static void WriteUseListBlock(const Function *F, ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeUseListBlock(const Function *F) { assert(VE.shouldPreserveUseListOrder() && "Expected to be preserving use-list order"); @@ -2485,24 +2678,23 @@ // Nothing to do. return; - Stream.EnterSubblock(bitc::USELIST_BLOCK_ID, 3); + stream().EnterSubblock(bitc::USELIST_BLOCK_ID, 3); while (hasMore()) { - WriteUseList(VE, std::move(VE.UseListOrders.back()), Stream); + writeUseList(std::move(VE.UseListOrders.back())); VE.UseListOrders.pop_back(); } - Stream.ExitBlock(); + stream().ExitBlock(); } /// Emit a function body to the module stream. -static void -WriteFunction(const Function &F, const Module *M, ValueEnumerator &VE, - BitstreamWriter &Stream, - DenseMap &FunctionToBitcodeIndex) { +void ModuleBitcodeWriter::writeFunction( + const Function &F, + DenseMap &FunctionToBitcodeIndex) { // Save the bitcode index of the start of this function block for recording // in the VST. - FunctionToBitcodeIndex[&F] = Stream.GetCurrentBitNo(); + FunctionToBitcodeIndex[&F] = stream().GetCurrentBitNo(); - Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4); + stream().EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4); VE.incorporateFunction(F); SmallVector Vals; @@ -2510,16 +2702,16 @@ // Emit the number of basic blocks, so the reader can create them ahead of // time. Vals.push_back(VE.getBasicBlocks().size()); - Stream.EmitRecord(bitc::FUNC_CODE_DECLAREBLOCKS, Vals); + stream().EmitRecord(bitc::FUNC_CODE_DECLAREBLOCKS, Vals); Vals.clear(); // If there are function-local constants, emit them now. unsigned CstStart, CstEnd; VE.getFunctionConstantRange(CstStart, CstEnd); - WriteConstants(CstStart, CstEnd, VE, Stream, false); + writeConstants(CstStart, CstEnd, false); // If there is function-local metadata, emit it now. - writeFunctionMetadata(F, VE, Stream); + writeFunctionMetadata(F); // Keep a running idea of what the instruction ID is. unsigned InstID = CstEnd; @@ -2531,7 +2723,7 @@ for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - WriteInstruction(*I, InstID, VE, Stream, Vals); + writeInstruction(*I, InstID, Vals); if (!I->getType()->isVoidTy()) ++InstID; @@ -2546,7 +2738,7 @@ if (DL == LastDL) { // Just repeat the same debug loc as last time. - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); + stream().EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); continue; } @@ -2554,29 +2746,29 @@ Vals.push_back(DL->getColumn()); Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); + stream().EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); Vals.clear(); LastDL = DL; } // Emit names for all the instructions etc. - WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream); + writeValueSymbolTable(F.getValueSymbolTable()); if (NeedsMetadataAttachment) - WriteMetadataAttachment(F, VE, Stream); + writeMetadataAttachment(F); if (VE.shouldPreserveUseListOrder()) - WriteUseListBlock(&F, VE, Stream); + writeUseListBlock(&F); VE.purgeFunction(); - Stream.ExitBlock(); + stream().ExitBlock(); } // Emit blockinfo, which defines the standard abbreviations etc. -static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { +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); + stream().EnterBlockInfoBlock(2); { // 8-bit fixed-width VST_CODE_ENTRY/VST_CODE_BBENTRY strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -2584,8 +2776,8 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_ENTRY_8_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != + VST_ENTRY_8_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } @@ -2595,8 +2787,8 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); - if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_ENTRY_7_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != + VST_ENTRY_7_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // 6-bit char6 VST_CODE_ENTRY strings. @@ -2605,8 +2797,8 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_ENTRY_6_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != + VST_ENTRY_6_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // 6-bit char6 VST_CODE_BBENTRY strings. @@ -2615,8 +2807,8 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_BBENTRY_6_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, Abbv) != + VST_BBENTRY_6_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } @@ -2627,8 +2819,8 @@ 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) + if (stream().EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != + CONSTANTS_SETTYPE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } @@ -2636,8 +2828,8 @@ BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_INTEGER_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != + CONSTANTS_INTEGER_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } @@ -2649,15 +2841,15 @@ VE.computeBitsRequiredForTypeIndicies())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id - if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_CE_CAST_Abbrev) + 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)); - if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_NULL_Abbrev) + if (stream().EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != + CONSTANTS_NULL_Abbrev) llvm_unreachable("Unexpected abbrev ordering!"); } @@ -2671,8 +2863,8 @@ 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) + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_LOAD_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_BINOP abbrev for FUNCTION_BLOCK. @@ -2681,8 +2873,8 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_BINOP_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_BINOP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK. @@ -2692,8 +2884,8 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_BINOP_FLAGS_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_CAST abbrev for FUNCTION_BLOCK. @@ -2703,31 +2895,31 @@ 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) + 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(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_RET_VOID_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_RET_VOID_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_RET abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_RET_VAL_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_RET_VAL_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_UNREACHABLE abbrev for FUNCTION_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE)); - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_UNREACHABLE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { @@ -2738,19 +2930,18 @@ Log2_32_Ceil(VE.getTypes().size() + 1))); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + if (stream().EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_GEP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } - Stream.ExitBlock(); + stream().ExitBlock(); } /// Write the module path strings, currently only used when generating /// a combined index file. -static void WriteModStrings(const ModuleSummaryIndex &I, - BitstreamWriter &Stream) { - Stream.EnterSubblock(bitc::MODULE_STRTAB_BLOCK_ID, 3); +void IndexBitcodeWriter::writeModStrings() { + stream().EnterSubblock(bitc::MODULE_STRTAB_BLOCK_ID, 3); // TODO: See which abbrev sizes we actually need to emit @@ -2760,7 +2951,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - unsigned Abbrev8Bit = Stream.EmitAbbrev(Abbv); + unsigned Abbrev8Bit = stream().EmitAbbrev(Abbv); // 7-bit fixed width MST_ENTRY strings. Abbv = new BitCodeAbbrev(); @@ -2768,7 +2959,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); - unsigned Abbrev7Bit = Stream.EmitAbbrev(Abbv); + unsigned Abbrev7Bit = stream().EmitAbbrev(Abbv); // 6-bit char6 MST_ENTRY strings. Abbv = new BitCodeAbbrev(); @@ -2776,7 +2967,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - unsigned Abbrev6Bit = Stream.EmitAbbrev(Abbv); + unsigned Abbrev6Bit = stream().EmitAbbrev(Abbv); // Module Hash, 160 bits SHA1. Optionally, emitted after each MST_CODE_ENTRY. Abbv = new BitCodeAbbrev(); @@ -2786,10 +2977,10 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - unsigned AbbrevHash = Stream.EmitAbbrev(Abbv); + unsigned AbbrevHash = stream().EmitAbbrev(Abbv); SmallVector Vals; - for (const auto &MPSE : I.modulePaths()) { + for (const auto &MPSE : Index->modulePaths()) { StringEncoding Bits = getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size()); unsigned AbbrevToUse = Abbrev8Bit; @@ -2804,7 +2995,7 @@ Vals.push_back((unsigned char)P); // Emit the finished record. - Stream.EmitRecord(bitc::MST_CODE_ENTRY, Vals, AbbrevToUse); + stream().EmitRecord(bitc::MST_CODE_ENTRY, Vals, AbbrevToUse); Vals.clear(); // Emit an optional hash for the module now @@ -2817,19 +3008,19 @@ } if (!AllZero) { // Emit the hash record. - Stream.EmitRecord(bitc::MST_CODE_HASH, Vals, AbbrevHash); + stream().EmitRecord(bitc::MST_CODE_HASH, Vals, AbbrevHash); } Vals.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } // Helper to emit a single function summary record. -static void WritePerModuleFunctionSummaryRecord( +void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord( SmallVector &NameVals, GlobalValueInfo *Info, - unsigned ValueID, const ValueEnumerator &VE, unsigned FSCallsAbbrev, - unsigned FSCallsProfileAbbrev, BitstreamWriter &Stream, const Function &F) { + unsigned ValueID, unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev, + const Function &F) { NameVals.push_back(ValueID); FunctionSummary *FS = cast(Info->summary()); @@ -2854,45 +3045,39 @@ (HasProfileData ? bitc::FS_PERMODULE_PROFILE : bitc::FS_PERMODULE); // Emit the finished record. - Stream.EmitRecord(Code, NameVals, FSAbbrev); + stream().EmitRecord(Code, NameVals, FSAbbrev); NameVals.clear(); } // Collect the global value references in the given variable's initializer, // and emit them in a summary record. -static void WriteModuleLevelReferences(const GlobalVariable &V, - const ModuleSummaryIndex &Index, - const ValueEnumerator &VE, - SmallVector &NameVals, - unsigned FSModRefsAbbrev, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writeModuleLevelReferences( + const GlobalVariable &V, SmallVector &NameVals, + unsigned FSModRefsAbbrev) { // Only interested in recording variable defs in the summary. if (V.isDeclaration()) return; NameVals.push_back(VE.getValueID(&V)); NameVals.push_back(getEncodedLinkage(V.getLinkage())); - auto *Info = Index.getGlobalValueInfo(V); + auto *Info = Index->getGlobalValueInfo(V); GlobalVarSummary *VS = cast(Info->summary()); for (auto Ref : VS->refs()) NameVals.push_back(VE.getValueID(Ref.getValue())); - Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals, - FSModRefsAbbrev); + stream().EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals, + FSModRefsAbbrev); NameVals.clear(); } /// Emit the per-module summary section alongside the rest of /// the module's bitcode. -static void WritePerModuleGlobalValueSummary(const Module *M, - const ModuleSummaryIndex &Index, - const ValueEnumerator &VE, - BitstreamWriter &Stream) { +void ModuleBitcodeWriter::writePerModuleGlobalValueSummary() { if (M->empty()) return; - if (Index.begin() == Index.end()) + if (Index->begin() == Index->end()) return; - Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3); + stream().EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3); // Abbrev for FS_PERMODULE. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -2904,7 +3089,7 @@ // numrefs x valueid, n x (valueid, callsitecount) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - unsigned FSCallsAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSCallsAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for FS_PERMODULE_PROFILE. Abbv = new BitCodeAbbrev(); @@ -2916,7 +3101,7 @@ // numrefs x valueid, n x (valueid, callsitecount, profilecount) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - unsigned FSCallsProfileAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSCallsProfileAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for FS_PERMODULE_GLOBALVAR_INIT_REFS. Abbv = new BitCodeAbbrev(); @@ -2925,7 +3110,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); // valueids Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSModRefsAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for FS_ALIAS. Abbv = new BitCodeAbbrev(); @@ -2933,7 +3118,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid - unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSAliasAbbrev = stream().EmitAbbrev(Abbv); SmallVector NameVals; // Iterate over the list of functions instead of the Index to @@ -2946,17 +3131,17 @@ if (!F.hasName()) report_fatal_error("Unexpected anonymous function when writing summary"); - auto *Info = Index.getGlobalValueInfo(F); - WritePerModuleFunctionSummaryRecord( + auto *Info = Index->getGlobalValueInfo(F); + writePerModuleFunctionSummaryRecord( NameVals, Info, - VE.getValueID(M->getValueSymbolTable().lookup(F.getName())), VE, - FSCallsAbbrev, FSCallsProfileAbbrev, Stream, F); + VE.getValueID(M->getValueSymbolTable().lookup(F.getName())), + FSCallsAbbrev, FSCallsProfileAbbrev, F); } // Capture references from GlobalVariable initializers, which are outside // of a function scope. for (const GlobalVariable &G : M->globals()) - WriteModuleLevelReferences(G, Index, VE, NameVals, FSModRefsAbbrev, Stream); + writeModuleLevelReferences(G, NameVals, FSModRefsAbbrev); for (const GlobalAlias &A : M->aliases()) { auto *Aliasee = A.getBaseObject(); @@ -2968,19 +3153,16 @@ NameVals.push_back(AliasId); NameVals.push_back(getEncodedLinkage(A.getLinkage())); NameVals.push_back(AliaseeId); - Stream.EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev); + stream().EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev); NameVals.clear(); } - Stream.ExitBlock(); + stream().ExitBlock(); } /// Emit the combined summary section into the combined index file. -static void WriteCombinedGlobalValueSummary( - const ModuleSummaryIndex &Index, BitstreamWriter &Stream, - std::map &GUIDToValueIdMap, - unsigned GlobalValueId) { - Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3); +void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { + stream().EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3); // Abbrev for FS_COMBINED. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -2992,7 +3174,7 @@ // numrefs x valueid, n x (valueid, callsitecount) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - unsigned FSCallsAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSCallsAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for FS_COMBINED_PROFILE. Abbv = new BitCodeAbbrev(); @@ -3004,7 +3186,7 @@ // numrefs x valueid, n x (valueid, callsitecount, profilecount) Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - unsigned FSCallsProfileAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSCallsProfileAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for FS_COMBINED_GLOBALVAR_INIT_REFS. Abbv = new BitCodeAbbrev(); @@ -3013,7 +3195,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); // valueids Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); - unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSModRefsAbbrev = stream().EmitAbbrev(Abbv); // Abbrev for FS_COMBINED_ALIAS. Abbv = new BitCodeAbbrev(); @@ -3021,7 +3203,7 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // modid Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // offset - unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FSAliasAbbrev = stream().EmitAbbrev(Abbv); // The aliases are emitted as a post-pass, and will point to the summary // offset id of the aliasee. For this purpose we need to be able to get back @@ -3030,7 +3212,7 @@ DenseMap SummaryToOffsetMap; SmallVector NameVals; - for (const auto &FII : Index) { + for (const auto &FII : *Index) { for (auto &FI : FII.second) { GlobalValueSummary *S = FI->summary(); assert(S); @@ -3042,53 +3224,35 @@ } if (auto *VS = dyn_cast(S)) { - NameVals.push_back(Index.getModuleId(VS->modulePath())); + NameVals.push_back(Index->getModuleId(VS->modulePath())); NameVals.push_back(getEncodedLinkage(VS->linkage())); for (auto &RI : VS->refs()) { - const auto &VMI = GUIDToValueIdMap.find(RI.getGUID()); - unsigned RefId; - // If this GUID doesn't have an entry, assign one. - if (VMI == GUIDToValueIdMap.end()) { - GUIDToValueIdMap[RI.getGUID()] = ++GlobalValueId; - RefId = GlobalValueId; - } else { - RefId = VMI->second; - } - NameVals.push_back(RefId); + NameVals.push_back(getValueId(RI.getGUID())); } // Record the starting offset of this summary entry for use // in the VST entry. Add the current code size since the // reader will invoke readRecord after the abbrev id read. - FI->setBitcodeIndex(Stream.GetCurrentBitNo() + - Stream.GetAbbrevIDWidth()); + FI->setBitcodeIndex(stream().GetCurrentBitNo() + + stream().GetAbbrevIDWidth()); // Store temporarily the offset in the map for a possible alias. SummaryToOffsetMap[S] = FI->bitcodeIndex(); // Emit the finished record. - Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals, - FSModRefsAbbrev); + stream().EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals, + FSModRefsAbbrev); NameVals.clear(); continue; } auto *FS = cast(S); - NameVals.push_back(Index.getModuleId(FS->modulePath())); + NameVals.push_back(Index->getModuleId(FS->modulePath())); NameVals.push_back(getEncodedLinkage(FS->linkage())); NameVals.push_back(FS->instCount()); NameVals.push_back(FS->refs().size()); for (auto &RI : FS->refs()) { - const auto &VMI = GUIDToValueIdMap.find(RI.getGUID()); - unsigned RefId; - // If this GUID doesn't have an entry, assign one. - if (VMI == GUIDToValueIdMap.end()) { - GUIDToValueIdMap[RI.getGUID()] = ++GlobalValueId; - RefId = GlobalValueId; - } else { - RefId = VMI->second; - } - NameVals.push_back(RefId); + NameVals.push_back(getValueId(RI.getGUID())); } bool HasProfileData = false; @@ -3099,12 +3263,11 @@ } for (auto &EI : FS->calls()) { - const auto &VMI = GUIDToValueIdMap.find(EI.first.getGUID()); - // If this GUID doesn't have an entry, it doesn't have a function + // If this GUID doesn't have a value id, it doesn't have a function // summary and we don't need to record any calls to it. - if (VMI == GUIDToValueIdMap.end()) + if (!hasValueId(EI.first.getGUID())) continue; - NameVals.push_back(VMI->second); + NameVals.push_back(getValueId(EI.first.getGUID())); assert(EI.second.CallsiteCount > 0 && "Expected at least one callsite"); NameVals.push_back(EI.second.CallsiteCount); if (HasProfileData) @@ -3114,7 +3277,8 @@ // Record the starting offset of this summary entry for use // in the VST entry. Add the current code size since the // reader will invoke readRecord after the abbrev id read. - FI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth()); + FI->setBitcodeIndex(stream().GetCurrentBitNo() + + stream().GetAbbrevIDWidth()); // Store temporarily the offset in the map for a possible alias. SummaryToOffsetMap[S] = FI->bitcodeIndex(); @@ -3124,14 +3288,14 @@ (HasProfileData ? bitc::FS_COMBINED_PROFILE : bitc::FS_COMBINED); // Emit the finished record. - Stream.EmitRecord(Code, NameVals, FSAbbrev); + stream().EmitRecord(Code, NameVals, FSAbbrev); NameVals.clear(); } } for (auto GVI : Aliases) { AliasSummary *AS = cast(GVI->summary()); - NameVals.push_back(Index.getModuleId(AS->modulePath())); + NameVals.push_back(Index->getModuleId(AS->modulePath())); NameVals.push_back(getEncodedLinkage(AS->linkage())); auto AliaseeOffset = SummaryToOffsetMap[&AS->getAliasee()]; assert(AliaseeOffset); @@ -3140,48 +3304,45 @@ // Record the starting offset of this summary entry for use // in the VST entry. Add the current code size since the // reader will invoke readRecord after the abbrev id read. - GVI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth()); + GVI->setBitcodeIndex(stream().GetCurrentBitNo() + + stream().GetAbbrevIDWidth()); // Emit the finished record. - Stream.EmitRecord(bitc::FS_COMBINED_ALIAS, NameVals, FSAliasAbbrev); + stream().EmitRecord(bitc::FS_COMBINED_ALIAS, NameVals, FSAliasAbbrev); NameVals.clear(); } - Stream.ExitBlock(); + 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); +void ModuleBitcodeWriter::writeIdentificationBlock() { + 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); + auto StringAbbrev = stream().EmitAbbrev(Abbv); + writeStringRecord(bitc::IDENTIFICATION_CODE_STRING, + "LLVM" LLVM_VERSION_STRING, StringAbbrev); // Write the epoch version Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::IDENTIFICATION_CODE_EPOCH)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - auto EpochAbbrev = Stream.EmitAbbrev(Abbv); + auto EpochAbbrev = stream().EmitAbbrev(Abbv); SmallVector Vals = {bitc::BITCODE_CURRENT_EPOCH}; - Stream.EmitRecord(bitc::IDENTIFICATION_CODE_EPOCH, Vals, EpochAbbrev); - Stream.ExitBlock(); + stream().EmitRecord(bitc::IDENTIFICATION_CODE_EPOCH, Vals, EpochAbbrev); + stream().ExitBlock(); } -static void writeModuleHash(BitstreamWriter &Stream, - SmallVectorImpl &Buffer, - size_t BlockStartPos) { +void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) { // Emit the module's hash. // MODULE_CODE_HASH: [5*i32] SHA1 Hasher; - Hasher.update(ArrayRef((uint8_t *)&Buffer[BlockStartPos], - Buffer.size() - BlockStartPos)); + Hasher.update(ArrayRef((uint8_t *)&(buffer())[BlockStartPos], + buffer().size() - BlockStartPos)); auto Hash = Hasher.result(); SmallVector Vals; auto LShift = [&](unsigned char Val, unsigned Amount) @@ -3194,82 +3355,96 @@ } // Emit the finished record. - Stream.EmitRecord(bitc::MODULE_CODE_HASH, Vals); + stream().EmitRecord(bitc::MODULE_CODE_HASH, Vals); +} + +void BitcodeWriter::write() { + // Emit the file header first. + writeBitcodeHeader(); + + writeBlocks(); } -/// WriteModule - Emit the specified module to the bitstream. -static void WriteModule(const Module *M, BitstreamWriter &Stream, - bool ShouldPreserveUseListOrder, - uint64_t BitcodeStartBit, - const ModuleSummaryIndex *Index, bool GenerateHash, - SmallVectorImpl &Buffer) { - Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); - size_t BlockStartPos = Buffer.size(); +void ModuleBitcodeWriter::writeBlocks() { + writeIdentificationBlock(); + writeModule(); +} + +void IndexBitcodeWriter::writeBlocks() { + // Index contains only a single outer (module) block. + writeIndex(); +} + +void ModuleBitcodeWriter::writeModule() { + stream().EnterSubblock(bitc::MODULE_BLOCK_ID, 3); + size_t BlockStartPos = buffer().size(); SmallVector Vals; unsigned CurVersion = 1; Vals.push_back(CurVersion); - Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); - - // Analyze the module, enumerating globals, functions, etc. - ValueEnumerator VE(*M, ShouldPreserveUseListOrder); + stream().EmitRecord(bitc::MODULE_CODE_VERSION, Vals); // Emit blockinfo, which defines the standard abbreviations etc. - WriteBlockInfo(VE, Stream); + writeBlockInfo(); // Emit information about attribute groups. - WriteAttributeGroupTable(VE, Stream); + writeAttributeGroupTable(); // Emit information about parameter attributes. - WriteAttributeTable(VE, Stream); + writeAttributeTable(); // Emit information describing all of the types in the module. - WriteTypeTable(VE, Stream); + writeTypeTable(); - writeComdats(VE, Stream); + writeComdats(); // Emit top-level description of module, including target triple, inline asm, // descriptors for global variables, and function prototype info. - uint64_t VSTOffsetPlaceholder = WriteModuleInfo(M, VE, Stream); + writeModuleInfo(); // Emit constants. - WriteModuleConstants(VE, Stream); + writeModuleConstants(); // Emit metadata. - writeModuleMetadata(*M, VE, Stream); + writeModuleMetadata(); // Emit metadata. - WriteModuleMetadataStore(M, Stream); + writeModuleMetadataStore(); // Emit module-level use-lists. if (VE.shouldPreserveUseListOrder()) - WriteUseListBlock(nullptr, VE, Stream); + writeUseListBlock(nullptr); - WriteOperandBundleTags(M, Stream); + writeOperandBundleTags(); // Emit function bodies. DenseMap FunctionToBitcodeIndex; for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) if (!F->isDeclaration()) - WriteFunction(*F, M, VE, Stream, FunctionToBitcodeIndex); + writeFunction(*F, FunctionToBitcodeIndex); // Need to write after the above call to WriteFunction which populates // the summary information in the index. if (Index) - WritePerModuleGlobalValueSummary(M, *Index, VE, Stream); + writePerModuleGlobalValueSummary(); - WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream, - VSTOffsetPlaceholder, BitcodeStartBit, - &FunctionToBitcodeIndex); + writeValueSymbolTable(M->getValueSymbolTable(), + /* IsModuleLevel */ true, &FunctionToBitcodeIndex); if (GenerateHash) { - writeModuleHash(Stream, Buffer, BlockStartPos); + writeModuleHash(BlockStartPos); } - Stream.ExitBlock(); + stream().ExitBlock(); } -/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a +static void writeInt32ToBuffer(uint32_t Value, SmallVectorImpl &Buffer, + uint32_t &Position) { + support::endian::write32le(&Buffer[Position], Value); + Position += 4; +} + +/// If generating a bc file on darwin, we have to emit a /// header and trailer to make it compatible with the system archiver. To do /// this we emit the following header, and then emit a trailer that pads the /// file out to be a multiple of 16 bytes. @@ -3282,14 +3457,7 @@ /// uint32_t CPUType; // CPU specifier. /// ... potentially more later ... /// }; - -static void WriteInt32ToBuffer(uint32_t Value, SmallVectorImpl &Buffer, - uint32_t &Position) { - support::endian::write32le(&Buffer[Position], Value); - Position += 4; -} - -static void EmitDarwinBCHeaderAndTrailer(SmallVectorImpl &Buffer, +static void emitDarwinBCHeaderAndTrailer(SmallVectorImpl &Buffer, const Triple &TT) { unsigned CPUType = ~0U; @@ -3324,11 +3492,11 @@ // Write the magic and version. unsigned Position = 0; - WriteInt32ToBuffer(0x0B17C0DE , Buffer, Position); - WriteInt32ToBuffer(0 , Buffer, Position); // Version. - WriteInt32ToBuffer(BCOffset , Buffer, Position); - WriteInt32ToBuffer(BCSize , Buffer, Position); - WriteInt32ToBuffer(CPUType , Buffer, Position); + writeInt32ToBuffer(0x0B17C0DE, Buffer, Position); + writeInt32ToBuffer(0, Buffer, Position); // Version. + writeInt32ToBuffer(BCOffset, Buffer, Position); + writeInt32ToBuffer(BCSize, Buffer, Position); + writeInt32ToBuffer(CPUType, Buffer, Position); // If the file is not a multiple of 16 bytes, insert dummy padding. while (Buffer.size() & 15) @@ -3336,14 +3504,14 @@ } /// Helper to write the header common to all bitcode files. -static void WriteBitcodeHeader(BitstreamWriter &Stream) { +void BitcodeWriter::writeBitcodeHeader() { // Emit the file header. - Stream.Emit((unsigned)'B', 8); - Stream.Emit((unsigned)'C', 8); - Stream.Emit(0x0, 4); - Stream.Emit(0xC, 4); - Stream.Emit(0xE, 4); - Stream.Emit(0xD, 4); + stream().Emit((unsigned)'B', 8); + stream().Emit((unsigned)'C', 8); + stream().Emit(0x0, 4); + stream().Emit(0xC, 4); + stream().Emit(0xE, 4); + stream().Emit(0xD, 4); } /// WriteBitcodeToFile - Write the specified module to the specified output @@ -3362,76 +3530,50 @@ Buffer.insert(Buffer.begin(), BWH_HeaderSize, 0); // Emit the module into the buffer. - { - BitstreamWriter Stream(Buffer); - // Save the start bit of the actual bitcode, in case there is space - // saved at the start for the darwin header above. The reader stream - // will start at the bitcode, and we need the offset of the VST - // to line up. - uint64_t BitcodeStartBit = Stream.GetCurrentBitNo(); - - // Emit the file header. - WriteBitcodeHeader(Stream); - - WriteIdentificationBlock(M, Stream); - - // Emit the module. - WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit, Index, - GenerateHash, Buffer); - } + ModuleBitcodeWriter ModuleWriter(M, &Buffer, ShouldPreserveUseListOrder, + Index, GenerateHash); + ModuleWriter.write(); if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) - EmitDarwinBCHeaderAndTrailer(Buffer, TT); + emitDarwinBCHeaderAndTrailer(Buffer, TT); // Write the generated bitstream to "Out". Out.write((char*)&Buffer.front(), Buffer.size()); } -// Write the specified module summary index to the given raw output stream, -// where it will be written in a new bitcode block. This is used when -// writing the combined index file for ThinLTO. -void llvm::WriteIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out) { - SmallVector Buffer; - Buffer.reserve(256 * 1024); - - BitstreamWriter Stream(Buffer); - - // Emit the bitcode header. - WriteBitcodeHeader(Stream); - - Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); +void IndexBitcodeWriter::writeIndex() { + stream().EnterSubblock(bitc::MODULE_BLOCK_ID, 3); SmallVector Vals; unsigned CurVersion = 1; Vals.push_back(CurVersion); - Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); + stream().EmitRecord(bitc::MODULE_CODE_VERSION, Vals); - // If we have a VST, write the VSTOFFSET record placeholder and record - // its offset. - uint64_t VSTOffsetPlaceholder = WriteValueSymbolTableForwardDecl(Stream); + // If we have a VST, write the VSTOFFSET record placeholder. + writeValueSymbolTableForwardDecl(); // Write the module paths in the combined index. - WriteModStrings(Index, Stream); - - // Assign unique value ids to all functions in the index for use - // in writing out the call graph edges. Save the mapping from GUID - // to the new global value id to use when writing those edges, which - // are currently saved in the index in terms of GUID. - std::map GUIDToValueIdMap; - unsigned GlobalValueId = 0; - for (auto &II : Index) - GUIDToValueIdMap[II.first] = ++GlobalValueId; + writeModStrings(); // Write the summary combined index records. - WriteCombinedGlobalValueSummary(Index, Stream, GUIDToValueIdMap, - GlobalValueId); + writeCombinedGlobalValueSummary(); // Need a special VST writer for the combined index (we don't have a // real VST and real values when this is invoked). - WriteCombinedValueSymbolTable(Index, Stream, GUIDToValueIdMap, - VSTOffsetPlaceholder); + writeCombinedValueSymbolTable(); + + stream().ExitBlock(); +} + +// Write the specified module summary index to the given raw output stream, +// where it will be written in a new bitcode block. This is used when +// writing the combined index file for ThinLTO. +void llvm::WriteIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out) { + SmallVector Buffer; + Buffer.reserve(256 * 1024); - Stream.ExitBlock(); + IndexBitcodeWriter IndexWriter(&Buffer, &Index); + IndexWriter.write(); Out.write((char *)&Buffer.front(), Buffer.size()); }