diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-27 23:34:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-10-23 18:26:01 +0000 |
commit | 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch) | |
tree | 6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | |
parent | 6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff) | |
parent | ac9a064cb179f3425b310fa2847f8764ac970a4d (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 459 |
1 files changed, 329 insertions, 130 deletions
diff --git a/contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index a5fc267b1883..324dcbca8137 100644 --- a/contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/contrib/llvm-project/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -33,6 +33,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Comdat.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/ConstantRangeList.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" @@ -99,6 +100,9 @@ namespace llvm { extern FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold; } +extern bool WriteNewDbgInfoFormatToBitcode; +extern llvm::cl::opt<bool> UseNewDbgInfoFormat; + namespace { /// These are manifest constants used by the bitcode writer. They do not need to @@ -128,6 +132,7 @@ enum { FUNCTION_INST_RET_VAL_ABBREV, FUNCTION_INST_UNREACHABLE_ABBREV, FUNCTION_INST_GEP_ABBREV, + FUNCTION_DEBUG_RECORD_VALUE_ABBREV, }; /// Abstract class to manage the bitcode writing, subclassed for each bitcode @@ -199,7 +204,7 @@ public: for (const auto &GUIDSummaryLists : *Index) // Examine all summaries for this GUID. for (auto &Summary : GUIDSummaryLists.second.SummaryList) - if (auto FS = dyn_cast<FunctionSummary>(Summary.get())) + if (auto FS = dyn_cast<FunctionSummary>(Summary.get())) { // For each call in the function summary, see if the call // is to a GUID (which means it is for an indirect call, // otherwise we would have a Value for it). If so, synthesize @@ -207,6 +212,15 @@ public: for (auto &CallEdge : FS->calls()) if (!CallEdge.first.haveGVs() || !CallEdge.first.getValue()) assignValueId(CallEdge.first.getGUID()); + + // For each referenced variables in the function summary, see if the + // variable is represented by a GUID (as opposed to a symbol to + // declarations or definitions in the module). If so, synthesize a + // value id. + for (auto &RefEdge : FS->refs()) + if (!RefEdge.haveGVs() || !RefEdge.getValue()) + assignValueId(RefEdge.getGUID()); + } } protected: @@ -247,9 +261,6 @@ private: /// Class to manage the bitcode writing for a module. class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { - /// Pointer to the buffer allocated by caller for bitcode writing. - const SmallVectorImpl<char> &Buffer; - /// True if a module hash record should be written. bool GenerateHash; @@ -265,14 +276,13 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { public: /// Constructs a ModuleBitcodeWriter object for the given Module, /// writing to the provided \p Buffer. - ModuleBitcodeWriter(const Module &M, SmallVectorImpl<char> &Buffer, - StringTableBuilder &StrtabBuilder, + ModuleBitcodeWriter(const Module &M, StringTableBuilder &StrtabBuilder, BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, const ModuleSummaryIndex *Index, bool GenerateHash, ModuleHash *ModHash = nullptr) : ModuleBitcodeWriterBase(M, StrtabBuilder, Stream, ShouldPreserveUseListOrder, Index), - Buffer(Buffer), GenerateHash(GenerateHash), ModHash(ModHash), + GenerateHash(GenerateHash), ModHash(ModHash), BitcodeStartBit(Stream.GetCurrentBitNo()) {} /// Emit the current module to the bitstream. @@ -401,7 +411,7 @@ private: writeFunction(const Function &F, DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex); void writeBlockInfo(); - void writeModuleHash(size_t BlockStartPos); + void writeModuleHash(StringRef View); unsigned getEncodedSyncScopeID(SyncScope::ID SSID) { return unsigned(SSID); @@ -415,6 +425,11 @@ class IndexBitcodeWriter : public BitcodeWriterBase { /// The combined index to write to bitcode. const ModuleSummaryIndex &Index; + /// When writing combined summaries, provides the set of global value + /// summaries for which the value (function, function alias, etc) should be + /// imported as a declaration. + const GVSummaryPtrSet *DecSummaries = nullptr; + /// When writing a subset of the index for distributed backends, client /// provides a map of modules to the corresponding GUIDs/summaries to write. const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex; @@ -423,10 +438,14 @@ class IndexBitcodeWriter : public BitcodeWriterBase { /// index and a value id generated by this class to use in references. std::map<GlobalValue::GUID, unsigned> GUIDToValueIdMap; - // The sorted stack id indices actually used in the summary entries being - // written, which will be a subset of those in the full index in the case of - // distributed indexes. - std::vector<unsigned> StackIdIndices; + // The stack ids used by this index, which will be a subset of those in + // the full index in the case of distributed indexes. + std::vector<uint64_t> StackIds; + + // Keep a map of the stack id indices used by records being written for this + // index to the index of the corresponding stack id in the above StackIds + // vector. Ensures we write each referenced stack id once. + DenseMap<unsigned, unsigned> StackIdIndicesToIndex; /// Tracks the last value id recorded in the GUIDToValueMap. unsigned GlobalValueId = 0; @@ -439,12 +458,30 @@ public: /// Constructs a IndexBitcodeWriter object for the given combined index, /// writing to the provided \p Buffer. When writing a subset of the index /// for a distributed backend, provide a \p ModuleToSummariesForIndex map. + /// If provided, \p DecSummaries specifies the set of summaries for which + /// the corresponding functions or aliased functions should be imported as a + /// declaration (but not definition) for each module. IndexBitcodeWriter(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder, const ModuleSummaryIndex &Index, + const GVSummaryPtrSet *DecSummaries = nullptr, const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex = nullptr) : BitcodeWriterBase(Stream, StrtabBuilder), Index(Index), + DecSummaries(DecSummaries), ModuleToSummariesForIndex(ModuleToSummariesForIndex) { + + // See if the StackIdIndex was already added to the StackId map and + // vector. If not, record it. + auto RecordStackIdReference = [&](unsigned StackIdIndex) { + // If the StackIdIndex is not yet in the map, the below insert ensures + // that it will point to the new StackIds vector entry we push to just + // below. + auto Inserted = + StackIdIndicesToIndex.insert({StackIdIndex, StackIds.size()}); + if (Inserted.second) + StackIds.push_back(Index.getStackIdAtIndex(StackIdIndex)); + }; + // Assign unique value ids to all summaries to be written, 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 @@ -475,17 +512,13 @@ public: continue; } for (auto Idx : CI.StackIdIndices) - StackIdIndices.push_back(Idx); + RecordStackIdReference(Idx); } for (auto &AI : FS->allocs()) for (auto &MIB : AI.MIBs) for (auto Idx : MIB.StackIdIndices) - StackIdIndices.push_back(Idx); + RecordStackIdReference(Idx); }); - llvm::sort(StackIdIndices); - StackIdIndices.erase( - std::unique(StackIdIndices.begin(), StackIdIndices.end()), - StackIdIndices.end()); } /// The below iterator returns the GUID and associated summary. @@ -694,6 +727,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_HOT; case Attribute::ElementType: return bitc::ATTR_KIND_ELEMENTTYPE; + case Attribute::HybridPatchable: + return bitc::ATTR_KIND_HYBRID_PATCHABLE; case Attribute::InlineHint: return bitc::ATTR_KIND_INLINE_HINT; case Attribute::InReg: @@ -806,6 +841,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_SANITIZE_THREAD; case Attribute::SanitizeMemory: return bitc::ATTR_KIND_SANITIZE_MEMORY; + case Attribute::SanitizeNumericalStability: + return bitc::ATTR_KIND_SANITIZE_NUMERICAL_STABILITY; case Attribute::SpeculativeLoadHardening: return bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING; case Attribute::SwiftError: @@ -844,6 +881,10 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_CORO_ONLY_DESTROY_WHEN_COMPLETE; case Attribute::DeadOnUnwind: return bitc::ATTR_KIND_DEAD_ON_UNWIND; + case Attribute::Range: + return bitc::ATTR_KIND_RANGE; + case Attribute::Initializes: + return bitc::ATTR_KIND_INITIALIZES; case Attribute::EndAttrKinds: llvm_unreachable("Can not encode end-attribute kinds marker."); case Attribute::None: @@ -856,6 +897,40 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { llvm_unreachable("Trying to encode unknown attribute"); } +static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) { + if ((int64_t)V >= 0) + Vals.push_back(V << 1); + else + Vals.push_back((-V << 1) | 1); +} + +static void emitWideAPInt(SmallVectorImpl<uint64_t> &Vals, const APInt &A) { + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NumWords = A.getActiveWords(); + const uint64_t *RawData = A.getRawData(); + for (unsigned i = 0; i < NumWords; i++) + emitSignedInt64(Vals, RawData[i]); +} + +static void emitConstantRange(SmallVectorImpl<uint64_t> &Record, + const ConstantRange &CR, bool EmitBitWidth) { + unsigned BitWidth = CR.getBitWidth(); + if (EmitBitWidth) + Record.push_back(BitWidth); + if (BitWidth > 64) { + Record.push_back(CR.getLower().getActiveWords() | + (uint64_t(CR.getUpper().getActiveWords()) << 32)); + emitWideAPInt(Record, CR.getLower()); + emitWideAPInt(Record, CR.getUpper()); + } else { + emitSignedInt64(Record, CR.getLower().getSExtValue()); + emitSignedInt64(Record, CR.getUpper().getSExtValue()); + } +} + void ModuleBitcodeWriter::writeAttributeGroupTable() { const std::vector<ValueEnumerator::IndexAndAttrSet> &AttrGrps = VE.getAttributeGroups(); @@ -889,13 +964,26 @@ void ModuleBitcodeWriter::writeAttributeGroupTable() { Record.append(Val.begin(), Val.end()); Record.push_back(0); } - } else { - assert(Attr.isTypeAttribute()); + } else if (Attr.isTypeAttribute()) { Type *Ty = Attr.getValueAsType(); Record.push_back(Ty ? 6 : 5); Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); if (Ty) Record.push_back(VE.getTypeID(Attr.getValueAsType())); + } else if (Attr.isConstantRangeAttribute()) { + Record.push_back(7); + Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); + emitConstantRange(Record, Attr.getValueAsConstantRange(), + /*EmitBitWidth=*/true); + } else { + assert(Attr.isConstantRangeListAttribute()); + Record.push_back(8); + Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); + ArrayRef<ConstantRange> Val = Attr.getValueAsConstantRangeList(); + Record.push_back(Val.size()); + Record.push_back(Val[0].getBitWidth()); + for (auto &CR : Val) + emitConstantRange(Record, CR, /*EmitBitWidth=*/false); } } @@ -934,7 +1022,7 @@ void ModuleBitcodeWriter::writeTypeTable() { Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */); SmallVector<uint64_t, 64> TypeVals; - uint64_t NumBits = VE.computeBitsRequiredForTypeIndicies(); + uint64_t NumBits = VE.computeBitsRequiredForTypeIndices(); // Abbrev for TYPE_CODE_OPAQUE_POINTER. auto Abbv = std::make_shared<BitCodeAbbrev>(); @@ -1150,7 +1238,8 @@ static uint64_t getEncodedFFlags(FunctionSummary::FFlags Flags) { // Decode the flags for GlobalValue in the summary. See getDecodedGVSummaryFlags // in BitcodeReader.cpp. -static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) { +static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags, + bool ImportAsDecl = false) { uint64_t RawFlags = 0; RawFlags |= Flags.NotEligibleToImport; // bool @@ -1165,6 +1254,9 @@ static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) { RawFlags |= (Flags.Visibility << 8); // 2 bits + unsigned ImportType = Flags.ImportType | ImportAsDecl; + RawFlags |= (ImportType << 10); // 1 bit + return RawFlags; } @@ -1597,6 +1689,18 @@ static uint64_t getOptimizationFlags(const Value *V) { } else if (const auto *NNI = dyn_cast<PossiblyNonNegInst>(V)) { if (NNI->hasNonNeg()) Flags |= 1 << bitc::PNNI_NON_NEG; + } else if (const auto *TI = dyn_cast<TruncInst>(V)) { + if (TI->hasNoSignedWrap()) + Flags |= 1 << bitc::TIO_NO_SIGNED_WRAP; + if (TI->hasNoUnsignedWrap()) + Flags |= 1 << bitc::TIO_NO_UNSIGNED_WRAP; + } else if (const auto *GEP = dyn_cast<GEPOperator>(V)) { + if (GEP->isInBounds()) + Flags |= 1 << bitc::GEP_INBOUNDS; + if (GEP->hasNoUnsignedSignedWrap()) + Flags |= 1 << bitc::GEP_NUSW; + if (GEP->hasNoUnsignedWrap()) + Flags |= 1 << bitc::GEP_NUW; } return Flags; @@ -1615,8 +1719,8 @@ void ModuleBitcodeWriter::writeValueAsMetadata( void ModuleBitcodeWriter::writeMDTuple(const MDTuple *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) { - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - Metadata *MD = N->getOperand(i); + for (const MDOperand &MDO : N->operands()) { + Metadata *MD = MDO; assert(!(MD && isa<LocalAsMetadata>(MD)) && "Unexpected function-local metadata"); Record.push_back(VE.getMetadataOrNullID(MD)); @@ -1716,24 +1820,6 @@ void ModuleBitcodeWriter::writeDIGenericSubrange( Record.clear(); } -static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) { - if ((int64_t)V >= 0) - Vals.push_back(V << 1); - else - Vals.push_back((-V << 1) | 1); -} - -static void emitWideAPInt(SmallVectorImpl<uint64_t> &Vals, const APInt &A) { - // We have an arbitrary precision integer value to write whose - // bit width is > 64. However, in canonical unsigned integer - // format it is likely that the high bits are going to be zero. - // So, we only write the number of active words. - unsigned NumWords = A.getActiveWords(); - const uint64_t *RawData = A.getRawData(); - for (unsigned i = 0; i < NumWords; i++) - emitSignedInt64(Vals, RawData[i]); -} - void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) { @@ -1804,6 +1890,11 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N, Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); + if (auto PtrAuthData = N->getPtrAuthData()) + Record.push_back(PtrAuthData->RawData); + else + Record.push_back(0); + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } @@ -2624,7 +2715,7 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, } } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { Code = bitc::CST_CODE_FLOAT; - Type *Ty = CFP->getType(); + Type *Ty = CFP->getType()->getScalarType(); if (Ty->isHalfTy() || Ty->isBFloatTy() || Ty->isFloatTy() || Ty->isDoubleTy()) { Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); @@ -2721,11 +2812,11 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Code = bitc::CST_CODE_CE_GEP; const auto *GO = cast<GEPOperator>(C); Record.push_back(VE.getTypeID(GO->getSourceElementType())); - if (std::optional<unsigned> Idx = GO->getInRangeIndex()) { - Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX; - Record.push_back((*Idx << 1) | GO->isInBounds()); - } else if (GO->isInBounds()) - Code = bitc::CST_CODE_CE_INBOUNDS_GEP; + Record.push_back(getOptimizationFlags(GO)); + if (std::optional<ConstantRange> Range = GO->getInRange()) { + Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE; + emitConstantRange(Record, *Range, /*EmitBitWidth=*/true); + } for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); Record.push_back(VE.getValueID(C->getOperand(i))); @@ -2761,14 +2852,6 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(VE.getValueID(C->getOperand(1))); Record.push_back(VE.getValueID(CE->getShuffleMaskForBitcode())); break; - case Instruction::ICmp: - case Instruction::FCmp: - Code = bitc::CST_CODE_CE_CMP; - Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); - Record.push_back(VE.getValueID(C->getOperand(0))); - Record.push_back(VE.getValueID(C->getOperand(1))); - Record.push_back(CE->getPredicate()); - break; } } else if (const BlockAddress *BA = dyn_cast<BlockAddress>(C)) { Code = bitc::CST_CODE_BLOCKADDRESS; @@ -2783,6 +2866,12 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Code = bitc::CST_CODE_NO_CFI_VALUE; Record.push_back(VE.getTypeID(NC->getGlobalValue()->getType())); Record.push_back(VE.getValueID(NC->getGlobalValue())); + } else if (const auto *CPA = dyn_cast<ConstantPtrAuth>(C)) { + Code = bitc::CST_CODE_PTRAUTH; + Record.push_back(VE.getValueID(CPA->getPointer())); + Record.push_back(VE.getValueID(CPA->getKey())); + Record.push_back(VE.getValueID(CPA->getDiscriminator())); + Record.push_back(VE.getValueID(CPA->getAddrDiscriminator())); } else { #ifndef NDEBUG C->dump(); @@ -2914,7 +3003,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I, Code = bitc::FUNC_CODE_INST_GEP; AbbrevToUse = FUNCTION_INST_GEP_ABBREV; auto &GEPInst = cast<GetElementPtrInst>(I); - Vals.push_back(GEPInst.isInBounds()); + Vals.push_back(getOptimizationFlags(&I)); Vals.push_back(VE.getTypeID(GEPInst.getSourceElementType())); for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) pushValueAndType(I.getOperand(i), InstID, Vals); @@ -3491,25 +3580,96 @@ void ModuleBitcodeWriter::writeFunction( NeedsMetadataAttachment |= I.hasMetadataOtherThanDebugLoc(); // If the instruction has a debug location, emit it. - DILocation *DL = I.getDebugLoc(); - if (!DL) - continue; - - if (DL == LastDL) { - // Just repeat the same debug loc as last time. - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); - continue; + if (DILocation *DL = I.getDebugLoc()) { + if (DL == LastDL) { + // Just repeat the same debug loc as last time. + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); + } else { + Vals.push_back(DL->getLine()); + Vals.push_back(DL->getColumn()); + Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); + Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); + Vals.push_back(DL->isImplicitCode()); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); + Vals.clear(); + LastDL = DL; + } } - Vals.push_back(DL->getLine()); - Vals.push_back(DL->getColumn()); - Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); - Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); - Vals.push_back(DL->isImplicitCode()); - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); - Vals.clear(); - - LastDL = DL; + // If the instruction has DbgRecords attached to it, emit them. Note that + // they come after the instruction so that it's easy to attach them again + // when reading the bitcode, even though conceptually the debug locations + // start "before" the instruction. + if (I.hasDbgRecords() && WriteNewDbgInfoFormatToBitcode) { + /// Try to push the value only (unwrapped), otherwise push the + /// metadata wrapped value. Returns true if the value was pushed + /// without the ValueAsMetadata wrapper. + auto PushValueOrMetadata = [&Vals, InstID, + this](Metadata *RawLocation) { + assert(RawLocation && + "RawLocation unexpectedly null in DbgVariableRecord"); + if (ValueAsMetadata *VAM = dyn_cast<ValueAsMetadata>(RawLocation)) { + SmallVector<unsigned, 2> ValAndType; + // If the value is a fwd-ref the type is also pushed. We don't + // want the type, so fwd-refs are kept wrapped (pushValueAndType + // returns false if the value is pushed without type). + if (!pushValueAndType(VAM->getValue(), InstID, ValAndType)) { + Vals.push_back(ValAndType[0]); + return true; + } + } + // The metadata is a DIArgList, or ValueAsMetadata wrapping a + // fwd-ref. Push the metadata ID. + Vals.push_back(VE.getMetadataID(RawLocation)); + return false; + }; + + // Write out non-instruction debug information attached to this + // instruction. Write it after the instruction so that it's easy to + // re-attach to the instruction reading the records in. + for (DbgRecord &DR : I.DebugMarker->getDbgRecordRange()) { + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + Vals.push_back(VE.getMetadataID(&*DLR->getDebugLoc())); + Vals.push_back(VE.getMetadataID(DLR->getLabel())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_LABEL, Vals); + Vals.clear(); + continue; + } + + // First 3 fields are common to all kinds: + // DILocation, DILocalVariable, DIExpression + // dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE) + // ..., LocationMetadata + // dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE - abbrev'd) + // ..., Value + // dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE) + // ..., LocationMetadata + // dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN) + // ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); + Vals.push_back(VE.getMetadataID(&*DVR.getDebugLoc())); + Vals.push_back(VE.getMetadataID(DVR.getVariable())); + Vals.push_back(VE.getMetadataID(DVR.getExpression())); + if (DVR.isDbgValue()) { + if (PushValueOrMetadata(DVR.getRawLocation())) + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE, Vals, + FUNCTION_DEBUG_RECORD_VALUE_ABBREV); + else + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_VALUE, Vals); + } else if (DVR.isDbgDeclare()) { + Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals); + } else { + assert(DVR.isDbgAssign() && "Unexpected DbgRecord kind"); + Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); + Vals.push_back(VE.getMetadataID(DVR.getAssignID())); + Vals.push_back(VE.getMetadataID(DVR.getAddressExpression())); + Vals.push_back(VE.getMetadataID(DVR.getRawAddress())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN, Vals); + } + Vals.clear(); + } + } } if (BlockAddress *BA = BlockAddress::lookup(&BB)) { @@ -3603,7 +3763,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { auto Abbv = std::make_shared<BitCodeAbbrev>(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != CONSTANTS_SETTYPE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); @@ -3623,7 +3783,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) != @@ -3645,7 +3805,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != @@ -3697,7 +3857,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != FUNCTION_INST_CAST_ABBREV) @@ -3708,7 +3868,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty - VE.computeBitsRequiredForTypeIndicies())); + VE.computeBitsRequiredForTypeIndices())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // flags if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != @@ -3741,7 +3901,7 @@ void ModuleBitcodeWriter::writeBlockInfo() { { auto Abbv = std::make_shared<BitCodeAbbrev>(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_GEP)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty Log2_32_Ceil(VE.getTypes().size() + 1))); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -3750,7 +3910,17 @@ void ModuleBitcodeWriter::writeBlockInfo() { FUNCTION_INST_GEP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } - + { + auto Abbv = std::make_shared<BitCodeAbbrev>(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // dbgloc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // var + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // expr + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // val + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_DEBUG_RECORD_VALUE_ABBREV) + llvm_unreachable("Unexpected abbrev ordering! 1"); + } Stream.ExitBlock(); } @@ -4021,10 +4191,9 @@ static void writeFunctionHeapProfileRecords( // Per module alloc versions should always have a single entry of // value 0. assert(!PerModule || (AI.Versions.size() == 1 && AI.Versions[0] == 0)); - if (!PerModule) { - Record.push_back(AI.MIBs.size()); + Record.push_back(AI.MIBs.size()); + if (!PerModule) Record.push_back(AI.Versions.size()); - } for (auto &MIB : AI.MIBs) { Record.push_back((uint8_t)MIB.AllocType); Record.push_back(MIB.StackIdIndices.size()); @@ -4035,6 +4204,11 @@ static void writeFunctionHeapProfileRecords( for (auto V : AI.Versions) Record.push_back(V); } + assert(AI.TotalSizes.empty() || AI.TotalSizes.size() == AI.MIBs.size()); + if (!AI.TotalSizes.empty()) { + for (auto Size : AI.TotalSizes) + Record.push_back(Size); + } Stream.EmitRecord(PerModule ? bitc::FS_PERMODULE_ALLOC_INFO : bitc::FS_COMBINED_ALLOC_INFO, Record, AllocAbbrev); @@ -4071,7 +4245,7 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord( NameVals.push_back(SpecialRefCnts.second); // worefcnt for (auto &RI : FS->refs()) - NameVals.push_back(VE.getValueID(RI.getValue())); + NameVals.push_back(getValueId(RI)); const bool UseRelBFRecord = WriteRelBFToSummary && !F.hasProfileData() && @@ -4264,7 +4438,9 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() { Abbv = std::make_shared<BitCodeAbbrev>(); Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE_ALLOC_INFO)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // nummib // n x (alloc type, numstackids, numstackids x stackidindex) + // optional: nummib x total size Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned AllocAbbrev = Stream.EmitAbbrev(std::move(Abbv)); @@ -4344,18 +4520,15 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { ArrayRef<uint64_t>{GVI.second, GVI.first}); } - if (!StackIdIndices.empty()) { + // Write the stack ids used by this index, which will be a subset of those in + // the full index in the case of distributed indexes. + if (!StackIds.empty()) { auto StackIdAbbv = std::make_shared<BitCodeAbbrev>(); StackIdAbbv->Add(BitCodeAbbrevOp(bitc::FS_STACK_IDS)); // numids x stackid StackIdAbbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); StackIdAbbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned StackIdAbbvId = Stream.EmitAbbrev(std::move(StackIdAbbv)); - // Write the stack ids used by this index, which will be a subset of those in - // the full index in the case of distributed indexes. - std::vector<uint64_t> StackIds; - for (auto &I : StackIdIndices) - StackIds.push_back(Index.getStackIdAtIndex(I)); Stream.EmitRecord(bitc::FS_STACK_IDS, StackIds, StackIdAbbvId); } @@ -4411,10 +4584,17 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // numver // nummib x (alloc type, numstackids, numstackids x stackidindex), // numver x version + // optional: nummib x total size Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned AllocAbbrev = Stream.EmitAbbrev(std::move(Abbv)); + auto shouldImportValueAsDecl = [&](GlobalValueSummary *GVS) -> bool { + if (DecSummaries == nullptr) + return false; + return DecSummaries->count(GVS); + }; + // The aliases are emitted as a post-pass, and will point to the value // id of the aliasee. Save them in a vector for post-processing. SmallVector<AliasSummary *, 64> Aliases; @@ -4504,7 +4684,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { writeFunctionHeapProfileRecords( Stream, FS, CallsiteAbbrev, AllocAbbrev, /*PerModule*/ false, - /*GetValueId*/ [&](const ValueInfo &VI) -> unsigned { + /*GetValueId*/ + [&](const ValueInfo &VI) -> unsigned { std::optional<unsigned> ValueID = GetValueId(VI); // This can happen in shared index files for distributed ThinLTO if // the callee function summary is not included. Record 0 which we @@ -4514,18 +4695,20 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { return 0; return *ValueID; }, - /*GetStackIndex*/ [&](unsigned I) { - // Get the corresponding index into the list of StackIdIndices - // actually being written for this combined index (which may be a - // subset in the case of distributed indexes). - auto Lower = llvm::lower_bound(StackIdIndices, I); - return std::distance(StackIdIndices.begin(), Lower); + /*GetStackIndex*/ + [&](unsigned I) { + // Get the corresponding index into the list of StackIds actually + // being written for this combined index (which may be a subset in + // the case of distributed indexes). + assert(StackIdIndicesToIndex.contains(I)); + return StackIdIndicesToIndex[I]; }); NameVals.push_back(*ValueId); assert(ModuleIdMap.count(FS->modulePath())); NameVals.push_back(ModuleIdMap[FS->modulePath()]); - NameVals.push_back(getEncodedGVSummaryFlags(FS->flags())); + NameVals.push_back( + getEncodedGVSummaryFlags(FS->flags(), shouldImportValueAsDecl(FS))); NameVals.push_back(FS->instCount()); NameVals.push_back(getEncodedFFlags(FS->fflags())); NameVals.push_back(FS->entryCount()); @@ -4574,7 +4757,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { NameVals.push_back(AliasValueId); assert(ModuleIdMap.count(AS->modulePath())); NameVals.push_back(ModuleIdMap[AS->modulePath()]); - NameVals.push_back(getEncodedGVSummaryFlags(AS->flags())); + NameVals.push_back( + getEncodedGVSummaryFlags(AS->flags(), shouldImportValueAsDecl(AS))); auto AliaseeValueId = SummaryToValueIdMap[&AS->getAliasee()]; assert(AliaseeValueId); NameVals.push_back(AliaseeValueId); @@ -4659,13 +4843,13 @@ static void writeIdentificationBlock(BitstreamWriter &Stream) { Stream.ExitBlock(); } -void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) { +void ModuleBitcodeWriter::writeModuleHash(StringRef View) { // Emit the module's hash. // MODULE_CODE_HASH: [5*i32] if (GenerateHash) { uint32_t Vals[5]; - Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos], - Buffer.size() - BlockStartPos)); + Hasher.update(ArrayRef<uint8_t>( + reinterpret_cast<const uint8_t *>(View.data()), View.size())); std::array<uint8_t, 20> Hash = Hasher.result(); for (int Pos = 0; Pos < 20; Pos += 4) { Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos); @@ -4684,7 +4868,9 @@ void ModuleBitcodeWriter::write() { writeIdentificationBlock(Stream); Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); - size_t BlockStartPos = Buffer.size(); + // We will want to write the module hash at this point. Block any flushing so + // we can have access to the whole underlying data later. + Stream.markAndBlockFlushing(); writeModuleVersion(); @@ -4735,7 +4921,7 @@ void ModuleBitcodeWriter::write() { writeGlobalValueSymbolTable(FunctionToBitcodeIndex); - writeModuleHash(BlockStartPos); + writeModuleHash(Stream.getMarkedBufferAndResumeFlushing()); Stream.ExitBlock(); } @@ -4816,8 +5002,13 @@ static void writeBitcodeHeader(BitstreamWriter &Stream) { Stream.Emit(0xD, 4); } -BitcodeWriter::BitcodeWriter(SmallVectorImpl<char> &Buffer, raw_fd_stream *FS) - : Buffer(Buffer), Stream(new BitstreamWriter(Buffer, FS, FlushThreshold)) { +BitcodeWriter::BitcodeWriter(SmallVectorImpl<char> &Buffer) + : Stream(new BitstreamWriter(Buffer)) { + writeBitcodeHeader(*Stream); +} + +BitcodeWriter::BitcodeWriter(raw_ostream &FS) + : Stream(new BitstreamWriter(FS, FlushThreshold)) { writeBitcodeHeader(*Stream); } @@ -4900,7 +5091,7 @@ void BitcodeWriter::writeModule(const Module &M, assert(M.isMaterialized()); Mods.push_back(const_cast<Module *>(&M)); - ModuleBitcodeWriter ModuleWriter(M, Buffer, StrtabBuilder, *Stream, + ModuleBitcodeWriter ModuleWriter(M, StrtabBuilder, *Stream, ShouldPreserveUseListOrder, Index, GenerateHash, ModHash); ModuleWriter.write(); @@ -4908,8 +5099,9 @@ void BitcodeWriter::writeModule(const Module &M, void BitcodeWriter::writeIndex( const ModuleSummaryIndex *Index, - const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex) { - IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index, + const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex, + const GVSummaryPtrSet *DecSummaries) { + IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index, DecSummaries, ModuleToSummariesForIndex); IndexWriter.write(); } @@ -4919,27 +5111,29 @@ void llvm::WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder, const ModuleSummaryIndex *Index, bool GenerateHash, ModuleHash *ModHash) { - SmallVector<char, 0> Buffer; - Buffer.reserve(256*1024); - - // If this is darwin or another generic macho target, reserve space for the - // header. + auto Write = [&](BitcodeWriter &Writer) { + Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash, + ModHash); + Writer.writeSymtab(); + Writer.writeStrtab(); + }; Triple TT(M.getTargetTriple()); - if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) + if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) { + // If this is darwin or another generic macho target, reserve space for the + // header. Note that the header is computed *after* the output is known, so + // we currently explicitly use a buffer, write to it, and then subsequently + // flush to Out. + SmallVector<char, 0> Buffer; + Buffer.reserve(256 * 1024); Buffer.insert(Buffer.begin(), BWH_HeaderSize, 0); - - BitcodeWriter Writer(Buffer, dyn_cast<raw_fd_stream>(&Out)); - Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash, - ModHash); - Writer.writeSymtab(); - Writer.writeStrtab(); - - if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) + BitcodeWriter Writer(Buffer); + Write(Writer); emitDarwinBCHeaderAndTrailer(Buffer, TT); - - // Write the generated bitstream to "Out". - if (!Buffer.empty()) - Out.write((char *)&Buffer.front(), Buffer.size()); + Out.write(Buffer.data(), Buffer.size()); + } else { + BitcodeWriter Writer(Out); + Write(Writer); + } } void IndexBitcodeWriter::write() { @@ -4962,12 +5156,13 @@ void IndexBitcodeWriter::write() { // index for a distributed backend, provide a \p ModuleToSummariesForIndex map. void llvm::writeIndexToFile( const ModuleSummaryIndex &Index, raw_ostream &Out, - const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex) { + const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex, + const GVSummaryPtrSet *DecSummaries) { SmallVector<char, 0> Buffer; Buffer.reserve(256 * 1024); BitcodeWriter Writer(Buffer); - Writer.writeIndex(&Index, ModuleToSummariesForIndex); + Writer.writeIndex(&Index, ModuleToSummariesForIndex, DecSummaries); Writer.writeStrtab(); Out.write((char *)&Buffer.front(), Buffer.size()); @@ -5147,6 +5342,8 @@ static const char *getSectionNameForBitcode(const Triple &T) { llvm_unreachable("GOFF is not yet implemented"); break; case Triple::SPIRV: + if (T.getVendor() == Triple::AMD) + return ".llvmbc"; llvm_unreachable("SPIRV is not yet implemented"); break; case Triple::XCOFF: @@ -5172,6 +5369,8 @@ static const char *getSectionNameForCommandline(const Triple &T) { llvm_unreachable("GOFF is not yet implemented"); break; case Triple::SPIRV: + if (T.getVendor() == Triple::AMD) + return ".llvmcmd"; llvm_unreachable("SPIRV is not yet implemented"); break; case Triple::XCOFF: |