diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter')
32 files changed, 1932 insertions, 1245 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp index f6ef85a5b78f..b634b24377fe 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -46,12 +46,12 @@ void ARMException::beginFunction(const MachineFunction *MF) { if (MoveType == AsmPrinter::CFI_M_Debug) { if (!hasEmittedCFISections) { if (Asm->needsOnlyDebugCFIMoves()) - Asm->OutStreamer->EmitCFISections(false, true); + Asm->OutStreamer->emitCFISections(false, true); hasEmittedCFISections = true; } shouldEmitCFI = true; - Asm->OutStreamer->EmitCFIStartProc(false); + Asm->OutStreamer->emitCFIStartProc(false); } } @@ -75,7 +75,7 @@ void ARMException::endFunction(const MachineFunction *MF) { // Emit references to personality. if (Per) { MCSymbol *PerSym = Asm->getSymbol(Per); - Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); + Asm->OutStreamer->emitSymbolAttribute(PerSym, MCSA_Global); ATS.emitPersonality(PerSym); } @@ -109,10 +109,10 @@ void ARMException::emitTypeInfos(unsigned TTypeEncoding, for (const GlobalValue *GV : reverse(TypeInfos)) { if (VerboseAsm) Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); - Asm->EmitTTypeReference(GV, TTypeEncoding); + Asm->emitTTypeReference(GV, TTypeEncoding); } - Asm->OutStreamer->EmitLabel(TTBaseLabel); + Asm->OutStreamer->emitLabel(TTBaseLabel); // Emit the Exception Specifications. if (VerboseAsm && !FilterIds.empty()) { @@ -129,7 +129,7 @@ void ARMException::emitTypeInfos(unsigned TTypeEncoding, Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); } - Asm->EmitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]), + Asm->emitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]), TTypeEncoding); } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp index b1b7921ea976..dea0227f7578 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -271,7 +271,7 @@ void AccelTableWriter::emitOffsets(const MCSymbol *Base) const { continue; PrevHash = HashValue; Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i)); - Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t)); + Asm->emitLabelDifference(Hash->Sym, Base, sizeof(uint32_t)); } } } @@ -337,7 +337,7 @@ void AppleAccelTableWriter::emitData() const { PrevHash != Hash->HashValue) Asm->emitInt32(0); // Remember to emit the label for our offset. - Asm->OutStreamer->EmitLabel(Hash->Sym); + Asm->OutStreamer->emitLabel(Hash->Sym); Asm->OutStreamer->AddComment(Hash->Name.getString()); Asm->emitDwarfStringOffset(Hash->Name); Asm->OutStreamer->AddComment("Num DIEs"); @@ -368,9 +368,9 @@ void Dwarf5AccelTableWriter<DataT>::Header::emit( AsmPrinter *Asm = Ctx.Asm; Asm->OutStreamer->AddComment("Header: unit length"); - Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart, + Asm->emitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart, sizeof(uint32_t)); - Asm->OutStreamer->EmitLabel(Ctx.ContributionStart); + Asm->OutStreamer->emitLabel(Ctx.ContributionStart); Asm->OutStreamer->AddComment("Header: version"); Asm->emitInt16(Version); Asm->OutStreamer->AddComment("Header: padding"); @@ -386,12 +386,12 @@ void Dwarf5AccelTableWriter<DataT>::Header::emit( Asm->OutStreamer->AddComment("Header: name count"); Asm->emitInt32(NameCount); Asm->OutStreamer->AddComment("Header: abbreviation table size"); - Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t)); + Asm->emitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t)); Asm->OutStreamer->AddComment("Header: augmentation string size"); assert(AugmentationStringSize % 4 == 0); Asm->emitInt32(AugmentationStringSize); Asm->OutStreamer->AddComment("Header: augmentation string"); - Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize}); + Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize}); } template <typename DataT> @@ -453,23 +453,23 @@ void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const { template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const { - Asm->OutStreamer->EmitLabel(AbbrevStart); + Asm->OutStreamer->emitLabel(AbbrevStart); for (const auto &Abbrev : Abbreviations) { Asm->OutStreamer->AddComment("Abbrev code"); assert(Abbrev.first != 0); - Asm->EmitULEB128(Abbrev.first); + Asm->emitULEB128(Abbrev.first); Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first)); - Asm->EmitULEB128(Abbrev.first); + Asm->emitULEB128(Abbrev.first); for (const auto &AttrEnc : Abbrev.second) { - Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); - Asm->EmitULEB128(AttrEnc.Form, + Asm->emitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); + Asm->emitULEB128(AttrEnc.Form, dwarf::FormEncodingString(AttrEnc.Form).data()); } - Asm->EmitULEB128(0, "End of abbrev"); - Asm->EmitULEB128(0, "End of abbrev"); + Asm->emitULEB128(0, "End of abbrev"); + Asm->emitULEB128(0, "End of abbrev"); } - Asm->EmitULEB128(0, "End of abbrev list"); - Asm->OutStreamer->EmitLabel(AbbrevEnd); + Asm->emitULEB128(0, "End of abbrev list"); + Asm->OutStreamer->emitLabel(AbbrevEnd); } template <typename DataT> @@ -478,13 +478,13 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const { assert(AbbrevIt != Abbreviations.end() && "Why wasn't this abbrev generated?"); - Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code"); + Asm->emitULEB128(AbbrevIt->first, "Abbreviation code"); for (const auto &AttrEnc : AbbrevIt->second) { Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index)); switch (AttrEnc.Index) { case dwarf::DW_IDX_compile_unit: { DIEInteger ID(getCUIndexForEntry(Entry)); - ID.EmitValue(Asm, AttrEnc.Form); + ID.emitValue(Asm, AttrEnc.Form); break; } case dwarf::DW_IDX_die_offset: @@ -498,11 +498,11 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const { } template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const { - Asm->OutStreamer->EmitLabel(EntryPool); + Asm->OutStreamer->emitLabel(EntryPool); for (auto &Bucket : Contents.getBuckets()) { for (auto *Hash : Bucket) { // Remember to emit the label for our offset. - Asm->OutStreamer->EmitLabel(Hash->Sym); + Asm->OutStreamer->emitLabel(Hash->Sym); for (const auto *Value : Hash->Values) emitEntry(*static_cast<const DataT *>(Value)); Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString()); @@ -537,8 +537,8 @@ template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const { emitOffsets(EntryPool); emitAbbrevs(); emitData(); - Asm->OutStreamer->EmitValueToAlignment(4, 0); - Asm->OutStreamer->EmitLabel(ContributionEnd); + Asm->OutStreamer->emitValueToAlignment(4, 0); + Asm->OutStreamer->emitLabel(ContributionEnd); } void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp index f11c7de5ed8a..883aaf5aefc4 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp @@ -30,9 +30,9 @@ MCSymbol *AddressPool::emitHeader(AsmPrinter &Asm, MCSection *Section) { MCSymbol *EndLabel = Asm.createTempSymbol(Prefix + "end"); Asm.OutStreamer->AddComment("Length of contribution"); - Asm.EmitLabelDifference(EndLabel, BeginLabel, + Asm.emitLabelDifference(EndLabel, BeginLabel, 4); // TODO: Support DWARF64 format. - Asm.OutStreamer->EmitLabel(BeginLabel); + Asm.OutStreamer->emitLabel(BeginLabel); Asm.OutStreamer->AddComment("DWARF version number"); Asm.emitInt16(Asm.getDwarfVersion()); Asm.OutStreamer->AddComment("Address size"); @@ -58,7 +58,7 @@ void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) { // Define the symbol that marks the start of the contribution. // It is referenced via DW_AT_addr_base. - Asm.OutStreamer->EmitLabel(AddressTableBaseSym); + Asm.OutStreamer->emitLabel(AddressTableBaseSym); // Order the address pool entries by ID SmallVector<const MCExpr *, 64> Entries(Pool.size()); @@ -70,8 +70,8 @@ void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) { : MCSymbolRefExpr::create(I.first, Asm.OutContext); for (const MCExpr *Entry : Entries) - Asm.OutStreamer->EmitValue(Entry, Asm.getDataLayout().getPointerSize()); + Asm.OutStreamer->emitValue(Entry, Asm.getDataLayout().getPointerSize()); if (EndLabel) - Asm.OutStreamer->EmitLabel(EndLabel); + Asm.OutStreamer->emitLabel(EndLabel); } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 20cd9da31fbd..f8f7b74baf91 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -31,16 +31,13 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -55,7 +52,6 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include "llvm/CodeGen/MachineSizeOpts.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -81,7 +77,6 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" -#include "llvm/IR/RemarkStreamer.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/MC/MCAsmInfo.h" @@ -106,6 +101,7 @@ #include "llvm/Pass.h" #include "llvm/Remarks/Remark.h" #include "llvm/Remarks/RemarkFormat.h" +#include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Remarks/RemarkStringTable.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -161,11 +157,11 @@ static gcp_map_type &getGCMap(void *&P) { /// getGVAlignment - Return the alignment to use for the specified global /// value. This rounds up to the preferred alignment if possible and legal. -Align AsmPrinter::getGVAlignment(const GlobalValue *GV, const DataLayout &DL, +Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL, Align InAlign) { Align Alignment; if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) - Alignment = Align(DL.getPreferredAlignment(GVar)); + Alignment = DL.getPreferredAlign(GVar); // If InAlign is specified, round it to it. if (InAlign > Alignment) @@ -231,7 +227,7 @@ const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const { } void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { - S.EmitInstruction(Inst, getSubtargetInfo()); + S.emitInstruction(Inst, getSubtargetInfo()); } void AsmPrinter::emitInitialRawDwarfLocDirective(const MachineFunction &MF) { @@ -248,11 +244,8 @@ const MCSection *AsmPrinter::getCurrentSection() const { void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired<MachineModuleInfoWrapperPass>(); AU.addRequired<MachineOptimizationRemarkEmitterPass>(); AU.addRequired<GCModuleInfo>(); - AU.addRequired<LazyMachineBlockFrequencyInfoPass>(); - AU.addRequired<ProfileSummaryInfoWrapperPass>(); } bool AsmPrinter::doInitialization(Module &M) { @@ -277,16 +270,16 @@ bool AsmPrinter::doInitialization(Module &M) { // use the directive, where it would need the same conditionalization // anyway. const Triple &Target = TM.getTargetTriple(); - OutStreamer->EmitVersionForTarget(Target, M.getSDKVersion()); + OutStreamer->emitVersionForTarget(Target, M.getSDKVersion()); // Allow the target to emit any magic that it wants at the start of the file. - EmitStartOfAsmFile(M); + emitStartOfAsmFile(M); // Very minimal debug info. It is ignored if we emit actual debug info. If we // don't, this at least helps the user find where a global came from. if (MAI->hasSingleParameterDotFile()) { // .file "foo.c" - OutStreamer->EmitFileDirective( + OutStreamer->emitFileDirective( llvm::sys::path::filename(M.getSourceFileName())); } @@ -305,21 +298,21 @@ bool AsmPrinter::doInitialization(Module &M) { TM.getTargetFeatureString())); OutStreamer->AddComment("Start of file scope inline assembly"); OutStreamer->AddBlankLine(); - EmitInlineAsm(M.getModuleInlineAsm()+"\n", + emitInlineAsm(M.getModuleInlineAsm() + "\n", OutContext.getSubtargetCopy(*STI), TM.Options.MCOptions); OutStreamer->AddComment("End of file scope inline assembly"); OutStreamer->AddBlankLine(); } if (MAI->doesSupportDebugInformation()) { - bool EmitCodeView = MMI->getModule()->getCodeViewFlag(); + bool EmitCodeView = M.getCodeViewFlag(); if (EmitCodeView && TM.getTargetTriple().isOSWindows()) { Handlers.emplace_back(std::make_unique<CodeViewDebug>(this), DbgTimerName, DbgTimerDescription, CodeViewLineTablesGroupName, CodeViewLineTablesGroupDescription); } - if (!EmitCodeView || MMI->getModule()->getDwarfVersion()) { + if (!EmitCodeView || M.getDwarfVersion()) { DD = new DwarfDebug(this, &M); DD->beginModule(); Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName, @@ -382,8 +375,7 @@ bool AsmPrinter::doInitialization(Module &M) { DWARFGroupDescription); // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2). - if (mdconst::extract_or_null<ConstantInt>( - MMI->getModule()->getModuleFlag("cfguard"))) + if (mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard"))) Handlers.emplace_back(std::make_unique<WinCFGuard>(this), CFGuardName, CFGuardDescription, DWARFGroupName, DWARFGroupDescription); @@ -397,7 +389,7 @@ static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) { return GV->canBeOmittedFromSymbolTable(); } -void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { +void AsmPrinter::emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { GlobalValue::LinkageTypes Linkage = GV->getLinkage(); switch (Linkage) { case GlobalValue::CommonLinkage: @@ -407,35 +399,31 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { case GlobalValue::WeakODRLinkage: if (MAI->hasWeakDefDirective()) { // .globl _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); if (!canBeHidden(GV, *MAI)) // .weak_definition _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefinition); else - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); - } else if (MAI->hasLinkOnceDirective()) { + OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); + } else if (MAI->avoidWeakIfComdat() && GV->hasComdat()) { // .globl _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); //NOTE: linkonce is handled by the section the symbol was assigned to. } else { // .weak _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak); } return; case GlobalValue::ExternalLinkage: - // If external, declare as a global symbol: .globl _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); return; case GlobalValue::PrivateLinkage: - return; case GlobalValue::InternalLinkage: - if (MAI->hasDotLGloblDirective()) - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_LGlobal); return; - case GlobalValue::AppendingLinkage: - case GlobalValue::AvailableExternallyLinkage: case GlobalValue::ExternalWeakLinkage: + case GlobalValue::AvailableExternallyLinkage: + case GlobalValue::AppendingLinkage: llvm_unreachable("Should never emit this"); } llvm_unreachable("Unknown linkage type!"); @@ -450,8 +438,27 @@ MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const { return TM.getSymbol(GV); } +MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { + // On ELF, use .Lfoo$local if GV is a non-interposable GlobalObject with an + // exact definion (intersection of GlobalValue::hasExactDefinition() and + // !isInterposable()). These linkages include: external, appending, internal, + // private. It may be profitable to use a local alias for external. The + // assembler would otherwise be conservative and assume a global default + // visibility symbol can be interposable, even if the code generator already + // assumed it. + if (TM.getTargetTriple().isOSBinFormatELF() && GV.canBenefitFromLocalAlias()) { + const Module &M = *GV.getParent(); + if (TM.getRelocationModel() != Reloc::Static && + M.getPIELevel() == PIELevel::Default) + if (GV.isDSOLocal() || (TM.getTargetTriple().isX86() && + GV.getParent()->noSemanticInterposition())) + return getSymbolWithGlobalValueBase(&GV, "$local"); + } + return TM.getSymbol(&GV); +} + /// EmitGlobalVariable - Emit the specified global variable to the .s file. -void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { +void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal(); assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) && "No emulated TLS variables in the common section"); @@ -463,7 +470,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (GV->hasInitializer()) { // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GV)) + if (emitSpecialLLVMGlobal(GV)) return; // Skip the emission of global equivalents. The symbol can be emitted later @@ -486,7 +493,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // getOrCreateEmuTLSControlSym only creates the symbol with name and default // attributes. // GV's or GVSym's attributes will be used for the EmittedSym. - EmitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration()); + emitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration()); if (!GV->hasInitializer()) // External globals require no extra code. return; @@ -497,7 +504,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { "' is already defined"); if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer->EmitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject); + OutStreamer->emitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject); SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); @@ -522,7 +529,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // .comm _foo, 42, 4 const bool SupportsAlignment = getObjFileLowering().getCommDirectiveSupportsAlignment(); - OutStreamer->EmitCommonSymbol(GVSym, Size, + OutStreamer->emitCommonSymbol(GVSym, Size, SupportsAlignment ? Alignment.value() : 0); return; } @@ -536,9 +543,9 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { TheSection->isVirtualSection()) { if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined. - EmitLinkage(GV, GVSym); + emitLinkage(GV, GVSym); // .zerofill __DATA, __bss, _foo, 400, 5 - OutStreamer->EmitZerofill(TheSection, GVSym, Size, Alignment.value()); + OutStreamer->emitZerofill(TheSection, GVSym, Size, Alignment.value()); return; } @@ -557,16 +564,16 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Prefer to simply fall back to .local / .comm in this case. if (MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) { // .lcomm _foo, 42 - OutStreamer->EmitLocalCommonSymbol(GVSym, Size, Alignment.value()); + OutStreamer->emitLocalCommonSymbol(GVSym, Size, Alignment.value()); return; } // .local _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Local); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Local); // .comm _foo, 42, 4 const bool SupportsAlignment = getObjFileLowering().getCommDirectiveSupportsAlignment(); - OutStreamer->EmitCommonSymbol(GVSym, Size, + OutStreamer->emitCommonSymbol(GVSym, Size, SupportsAlignment ? Alignment.value() : 0); return; } @@ -588,14 +595,14 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (GVKind.isThreadBSS()) { TheSection = getObjFileLowering().getTLSBSSSection(); - OutStreamer->EmitTBSSSymbol(TheSection, MangSym, Size, Alignment.value()); + OutStreamer->emitTBSSSymbol(TheSection, MangSym, Size, Alignment.value()); } else if (GVKind.isThreadData()) { OutStreamer->SwitchSection(TheSection); - EmitAlignment(Alignment, GV); - OutStreamer->EmitLabel(MangSym); + emitAlignment(Alignment, GV); + OutStreamer->emitLabel(MangSym); - EmitGlobalConstant(GV->getParent()->getDataLayout(), + emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); } @@ -606,18 +613,18 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer->SwitchSection(TLVSect); // Emit the linkage here. - EmitLinkage(GV, GVSym); - OutStreamer->EmitLabel(GVSym); + emitLinkage(GV, GVSym); + OutStreamer->emitLabel(GVSym); // Three pointers in size: // - __tlv_bootstrap - used to make sure support exists // - spare pointer, used when mapped by the runtime // - pointer to mangled symbol above with initializer unsigned PtrSize = DL.getPointerTypeSize(GV->getType()); - OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"), + OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"), PtrSize); - OutStreamer->EmitIntValue(0, PtrSize); - OutStreamer->EmitSymbolValue(MangSym, PtrSize); + OutStreamer->emitIntValue(0, PtrSize); + OutStreamer->emitSymbolValue(MangSym, PtrSize); OutStreamer->AddBlankLine(); return; @@ -627,12 +634,15 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer->SwitchSection(TheSection); - EmitLinkage(GV, EmittedInitSym); - EmitAlignment(Alignment, GV); + emitLinkage(GV, EmittedInitSym); + emitAlignment(Alignment, GV); - OutStreamer->EmitLabel(EmittedInitSym); + OutStreamer->emitLabel(EmittedInitSym); + MCSymbol *LocalAlias = getSymbolPreferLocal(*GV); + if (LocalAlias != EmittedInitSym) + OutStreamer->emitLabel(LocalAlias); - EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); + emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); if (MAI->hasDotTypeDotSizeDirective()) // .size foo, 42 @@ -646,13 +656,15 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { /// /// \p Value - The value to emit. /// \p Size - The size of the integer (in bytes) to emit. -void AsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const { - OutStreamer->EmitValue(Value, Size); +void AsmPrinter::emitDebugValue(const MCExpr *Value, unsigned Size) const { + OutStreamer->emitValue(Value, Size); } +void AsmPrinter::emitFunctionHeaderComment() {} + /// EmitFunctionHeader - This method emits the header for the current /// function. -void AsmPrinter::EmitFunctionHeader() { +void AsmPrinter::emitFunctionHeader() { const Function &F = MF->getFunction(); if (isVerbose()) @@ -661,29 +673,32 @@ void AsmPrinter::EmitFunctionHeader() { << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; // Print out constants referenced by the function - EmitConstantPool(); + emitConstantPool(); // Print the 'header' of function. - OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(&F, TM)); - EmitVisibility(CurrentFnSym, F.getVisibility()); + MF->setSection(getObjFileLowering().SectionForGlobal(&F, TM)); + OutStreamer->SwitchSection(MF->getSection()); - if (MAI->needsFunctionDescriptors() && - F.getLinkage() != GlobalValue::InternalLinkage) - EmitLinkage(&F, CurrentFnDescSym); + if (!MAI->hasVisibilityOnlyWithLinkage()) + emitVisibility(CurrentFnSym, F.getVisibility()); - EmitLinkage(&F, CurrentFnSym); + if (MAI->needsFunctionDescriptors()) + emitLinkage(&F, CurrentFnDescSym); + + emitLinkage(&F, CurrentFnSym); if (MAI->hasFunctionAlignment()) - EmitAlignment(MF->getAlignment(), &F); + emitAlignment(MF->getAlignment(), &F); if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); + OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); if (F.hasFnAttribute(Attribute::Cold)) - OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_Cold); + OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_Cold); if (isVerbose()) { F.printAsOperand(OutStreamer->GetCommentOS(), /*PrintType=*/false, F.getParent()); + emitFunctionHeaderComment(); OutStreamer->GetCommentOS() << '\n'; } @@ -695,14 +710,14 @@ void AsmPrinter::EmitFunctionHeader() { // and use the .alt_entry attribute to mark the function's real entry point // as an alternative entry point to the prefix-data symbol. MCSymbol *PrefixSym = OutContext.createLinkerPrivateTempSymbol(); - OutStreamer->EmitLabel(PrefixSym); + OutStreamer->emitLabel(PrefixSym); - EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); + emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); // Emit an .alt_entry directive for the actual function symbol. - OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_AltEntry); + OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_AltEntry); } else { - EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); + emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); } } @@ -719,7 +734,7 @@ void AsmPrinter::EmitFunctionHeader() { if (PatchableFunctionPrefix) { CurrentPatchableFunctionEntrySym = OutContext.createLinkerPrivateTempSymbol(); - OutStreamer->EmitLabel(CurrentPatchableFunctionEntrySym); + OutStreamer->emitLabel(CurrentPatchableFunctionEntrySym); emitNops(PatchableFunctionPrefix); } else if (PatchableFunctionEntry) { // May be reassigned when emitting the body, to reference the label after @@ -728,32 +743,24 @@ void AsmPrinter::EmitFunctionHeader() { } // Emit the function descriptor. This is a virtual function to allow targets - // to emit their specific function descriptor. + // to emit their specific function descriptor. Right now it is only used by + // the AIX target. The PowerPC 64-bit V1 ELF target also uses function + // descriptors and should be converted to use this hook as well. if (MAI->needsFunctionDescriptors()) - EmitFunctionDescriptor(); + emitFunctionDescriptor(); // Emit the CurrentFnSym. This is a virtual function to allow targets to do // their wild and crazy things as required. - EmitFunctionEntryLabel(); - - // If the function had address-taken blocks that got deleted, then we have - // references to the dangling symbols. Emit them at the start of the function - // so that we don't get references to undefined symbols. - std::vector<MCSymbol*> DeadBlockSyms; - MMI->takeDeletedSymbolsForFunction(&F, DeadBlockSyms); - for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) { - OutStreamer->AddComment("Address taken block that was later removed"); - OutStreamer->EmitLabel(DeadBlockSyms[i]); - } + emitFunctionEntryLabel(); if (CurrentFnBegin) { if (MAI->useAssignmentForEHBegin()) { MCSymbol *CurPos = OutContext.createTempSymbol(); - OutStreamer->EmitLabel(CurPos); - OutStreamer->EmitAssignment(CurrentFnBegin, + OutStreamer->emitLabel(CurPos); + OutStreamer->emitAssignment(CurrentFnBegin, MCSymbolRefExpr::create(CurPos, OutContext)); } else { - OutStreamer->EmitLabel(CurrentFnBegin); + OutStreamer->emitLabel(CurrentFnBegin); } } @@ -766,12 +773,12 @@ void AsmPrinter::EmitFunctionHeader() { // Emit the prologue data. if (F.hasPrologueData()) - EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); + emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the /// function. This can be overridden by targets as required to do custom stuff. -void AsmPrinter::EmitFunctionEntryLabel() { +void AsmPrinter::emitFunctionEntryLabel() { CurrentFnSym->redefineIfPossible(); // The function label could have already been emitted if two symbols end up @@ -783,7 +790,13 @@ void AsmPrinter::EmitFunctionEntryLabel() { report_fatal_error("'" + Twine(CurrentFnSym->getName()) + "' label emitted multiple times to assembly file"); - return OutStreamer->EmitLabel(CurrentFnSym); + OutStreamer->emitLabel(CurrentFnSym); + + if (TM.getTargetTriple().isOSBinFormatELF()) { + MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction()); + if (Sym != CurrentFnSym) + OutStreamer->emitLabel(Sym); + } } /// emitComments - Pretty-print comments for instructions. @@ -863,7 +876,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { OS << " <- "; // The second operand is only an offset if it's an immediate. - bool MemLoc = MI->getOperand(0).isReg() && MI->getOperand(1).isImm(); + bool MemLoc = MI->isIndirectDebugValue(); int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0; const DIExpression *Expr = MI->getDebugExpression(); if (Expr->getNumElements()) { @@ -882,11 +895,11 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } // Register or immediate value. Register 0 means undef. - if (MI->getOperand(0).isFPImm()) { - APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF()); - if (MI->getOperand(0).getFPImm()->getType()->isFloatTy()) { + if (MI->getDebugOperand(0).isFPImm()) { + APFloat APF = APFloat(MI->getDebugOperand(0).getFPImm()->getValueAPF()); + if (MI->getDebugOperand(0).getFPImm()->getType()->isFloatTy()) { OS << (double)APF.convertToFloat(); - } else if (MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) { + } else if (MI->getDebugOperand(0).getFPImm()->getType()->isDoubleTy()) { OS << APF.convertToDouble(); } else { // There is no good way to print long double. Convert a copy to @@ -896,23 +909,23 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { &ignored); OS << "(long double) " << APF.convertToDouble(); } - } else if (MI->getOperand(0).isImm()) { - OS << MI->getOperand(0).getImm(); - } else if (MI->getOperand(0).isCImm()) { - MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); - } else if (MI->getOperand(0).isTargetIndex()) { - auto Op = MI->getOperand(0); + } else if (MI->getDebugOperand(0).isImm()) { + OS << MI->getDebugOperand(0).getImm(); + } else if (MI->getDebugOperand(0).isCImm()) { + MI->getDebugOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); + } else if (MI->getDebugOperand(0).isTargetIndex()) { + auto Op = MI->getDebugOperand(0); OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; return true; } else { - unsigned Reg; - if (MI->getOperand(0).isReg()) { - Reg = MI->getOperand(0).getReg(); + Register Reg; + if (MI->getDebugOperand(0).isReg()) { + Reg = MI->getDebugOperand(0).getReg(); } else { - assert(MI->getOperand(0).isFI() && "Unknown operand type"); + assert(MI->getDebugOperand(0).isFI() && "Unknown operand type"); const TargetFrameLowering *TFI = AP.MF->getSubtarget().getFrameLowering(); - Offset += TFI->getFrameIndexReference(*AP.MF, - MI->getOperand(0).getIndex(), Reg); + Offset += TFI->getFrameIndexReference( + *AP.MF, MI->getDebugOperand(0).getIndex(), Reg); MemLoc = true; } if (Reg == 0) { @@ -1006,7 +1019,7 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) { int FrameOffset = MI.getOperand(1).getImm(); // Emit a symbol assignment. - OutStreamer->EmitAssignment(FrameAllocSym, + OutStreamer->emitAssignment(FrameAllocSym, MCConstantExpr::create(FrameOffset, OutContext)); } @@ -1029,15 +1042,15 @@ void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) { const MCSymbol *FunctionSymbol = getFunctionBegin(); uint64_t StackSize = FrameInfo.getStackSize(); - OutStreamer->EmitSymbolValue(FunctionSymbol, TM.getProgramPointerSize()); - OutStreamer->EmitULEB128IntValue(StackSize); + OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize()); + OutStreamer->emitULEB128IntValue(StackSize); OutStreamer->PopSection(); } -static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF, - MachineModuleInfo *MMI) { - if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI->hasDebugInfo()) +static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF) { + MachineModuleInfo &MMI = MF.getMMI(); + if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI.hasDebugInfo()) return true; // We might emit an EH table that uses function begin and end labels even if @@ -1050,11 +1063,11 @@ static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF, /// EmitFunctionBody - This method emits the body and trailer for a /// function. -void AsmPrinter::EmitFunctionBody() { - EmitFunctionHeader(); +void AsmPrinter::emitFunctionBody() { + emitFunctionHeader(); // Emit target-specific gunk before the function body. - EmitFunctionBodyStart(); + emitFunctionBodyStart(); bool ShouldPrintDebugScopes = MMI->hasDebugInfo(); @@ -1079,9 +1092,10 @@ void AsmPrinter::EmitFunctionBody() { // Print out code for the function. bool HasAnyRealCode = false; int NumInstsInFunction = 0; + for (auto &MBB : *MF) { // Print a label for the basic block. - EmitBasicBlockStart(MBB); + emitBasicBlockStart(MBB); for (auto &MI : MBB) { // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && @@ -1092,7 +1106,7 @@ void AsmPrinter::EmitFunctionBody() { // If there is a pre-instruction symbol, emit a label for it here. if (MCSymbol *S = MI.getPreInstrSymbol()) - OutStreamer->EmitLabel(S); + OutStreamer->emitLabel(S); if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { @@ -1116,22 +1130,22 @@ void AsmPrinter::EmitFunctionBody() { case TargetOpcode::ANNOTATION_LABEL: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: - OutStreamer->EmitLabel(MI.getOperand(0).getMCSymbol()); + OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol()); break; case TargetOpcode::INLINEASM: case TargetOpcode::INLINEASM_BR: - EmitInlineAsm(&MI); + emitInlineAsm(&MI); break; case TargetOpcode::DBG_VALUE: if (isVerbose()) { if (!emitDebugValueComment(&MI, *this)) - EmitInstruction(&MI); + emitInstruction(&MI); } break; case TargetOpcode::DBG_LABEL: if (isVerbose()) { if (!emitDebugLabelComment(&MI, *this)) - EmitInstruction(&MI); + emitInstruction(&MI); } break; case TargetOpcode::IMPLICIT_DEF: @@ -1141,13 +1155,13 @@ void AsmPrinter::EmitFunctionBody() { if (isVerbose()) emitKill(&MI, *this); break; default: - EmitInstruction(&MI); + emitInstruction(&MI); break; } // If there is a post-instruction symbol, emit a label for it here. if (MCSymbol *S = MI.getPostInstrSymbol()) - OutStreamer->EmitLabel(S); + OutStreamer->emitLabel(S); if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { @@ -1159,7 +1173,44 @@ void AsmPrinter::EmitFunctionBody() { } } - EmitBasicBlockEnd(MBB); + // We need a temporary symbol for the end of this basic block, if either we + // have BBLabels enabled and we want to emit size directive for the BBs, or + // if this basic blocks marks the end of a section (except the section + // containing the entry basic block as the end symbol for that section is + // CurrentFnEnd). + MCSymbol *CurrentBBEnd = nullptr; + if ((MAI->hasDotTypeDotSizeDirective() && MF->hasBBLabels()) || + (MBB.isEndSection() && !MBB.sameSection(&MF->front()))) { + CurrentBBEnd = OutContext.createTempSymbol(); + OutStreamer->emitLabel(CurrentBBEnd); + } + + // Helper for emitting the size directive associated with a basic block + // symbol. + auto emitELFSizeDirective = [&](MCSymbol *SymForSize) { + assert(CurrentBBEnd && "Basicblock end symbol not set!"); + const MCExpr *SizeExp = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(CurrentBBEnd, OutContext), + MCSymbolRefExpr::create(SymForSize, OutContext), OutContext); + OutStreamer->emitELFSize(SymForSize, SizeExp); + }; + + // Emit size directive for the size of each basic block, if BBLabels is + // enabled. + if (MAI->hasDotTypeDotSizeDirective() && MF->hasBBLabels()) + emitELFSizeDirective(MBB.getSymbol()); + + // Emit size directive for the size of each basic block section once we + // get to the end of that section. + if (MBB.isEndSection()) { + if (!MBB.sameSection(&MF->front())) { + if (MAI->hasDotTypeDotSizeDirective()) + emitELFSizeDirective(CurrentSectionBeginSym); + MBBSectionRanges[MBB.getSectionIDNum()] = + MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd}; + } + } + emitBasicBlockEnd(MBB); } EmittedInsts += NumInstsInFunction; @@ -1192,6 +1243,9 @@ void AsmPrinter::EmitFunctionBody() { } } + // Switch to the original section in case basic block sections was used. + OutStreamer->SwitchSection(MF->getSection()); + const Function &F = MF->getFunction(); for (const auto &BB : F) { if (!BB.hasAddressTaken()) @@ -1200,17 +1254,17 @@ void AsmPrinter::EmitFunctionBody() { if (Sym->isDefined()) continue; OutStreamer->AddComment("Address of block that was removed by CodeGen"); - OutStreamer->EmitLabel(Sym); + OutStreamer->emitLabel(Sym); } // Emit target-specific gunk after the function body. - EmitFunctionBodyEnd(); + emitFunctionBodyEnd(); - if (needFuncLabelsForEHOrDebugInfo(*MF, MMI) || + if (needFuncLabelsForEHOrDebugInfo(*MF) || MAI->hasDotTypeDotSizeDirective()) { // Create a symbol for the end of function. CurrentFnEnd = createTempSymbol("func_end"); - OutStreamer->EmitLabel(CurrentFnEnd); + OutStreamer->emitLabel(CurrentFnEnd); } // If the target wants a .size directive for the size of the function, emit @@ -1230,8 +1284,11 @@ void AsmPrinter::EmitFunctionBody() { HI.Handler->markFunctionEnd(); } + MBBSectionRanges[MF->front().getSectionIDNum()] = + MBBSectionRange{CurrentFnBegin, CurrentFnEnd}; + // Print out jump tables referenced by the function. - EmitJumpTableInfo(); + emitJumpTableInfo(); // Emit post-function debug and/or EH information. for (const HandlerInfo &HI : Handlers) { @@ -1327,7 +1384,7 @@ void AsmPrinter::emitGlobalGOTEquivs() { GlobalGOTEquivs.clear(); for (auto *GV : FailedCandidates) - EmitGlobalVariable(GV); + emitGlobalVariable(GV); } void AsmPrinter::emitGlobalIndirectSymbol(Module &M, @@ -1335,9 +1392,9 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, MCSymbol *Name = getSymbol(&GIS); if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_Global); + OutStreamer->emitSymbolAttribute(Name, MCSA_Global); else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_WeakReference); + OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference); else assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage"); @@ -1354,19 +1411,22 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, // Set the symbol type to function if the alias has a function type. // This affects codegen when the aliasee is not a function. if (IsFunction) - OutStreamer->EmitSymbolAttribute(Name, isa<GlobalIFunc>(GIS) + OutStreamer->emitSymbolAttribute(Name, isa<GlobalIFunc>(GIS) ? MCSA_ELF_TypeIndFunction : MCSA_ELF_TypeFunction); - EmitVisibility(Name, GIS.getVisibility()); + emitVisibility(Name, GIS.getVisibility()); const MCExpr *Expr = lowerConstant(GIS.getIndirectSymbol()); if (isa<GlobalAlias>(&GIS) && MAI->hasAltEntry() && isa<MCBinaryExpr>(Expr)) - OutStreamer->EmitSymbolAttribute(Name, MCSA_AltEntry); + OutStreamer->emitSymbolAttribute(Name, MCSA_AltEntry); // Emit the directives as assignments aka .set: - OutStreamer->EmitAssignment(Name, Expr); + OutStreamer->emitAssignment(Name, Expr); + MCSymbol *LocalAlias = getSymbolPreferLocal(GIS); + if (LocalAlias != Name) + OutStreamer->emitAssignment(LocalAlias, Expr); if (auto *GA = dyn_cast<GlobalAlias>(&GIS)) { // If the aliasee does not correspond to a symbol in the output, i.e. the @@ -1384,7 +1444,7 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, } } -void AsmPrinter::emitRemarksSection(RemarkStreamer &RS) { +void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { if (!RS.needsSection()) return; @@ -1409,7 +1469,7 @@ void AsmPrinter::emitRemarksSection(RemarkStreamer &RS) { OutContext.getObjectFileInfo()->getRemarksSection(); OutStreamer->SwitchSection(RemarksSection); - OutStreamer->EmitBinaryData(OS.str()); + OutStreamer->emitBinaryData(OS.str()); } bool AsmPrinter::doFinalization(Module &M) { @@ -1426,31 +1486,51 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. for (const auto &G : M.globals()) - EmitGlobalVariable(&G); + emitGlobalVariable(&G); // Emit remaining GOT equivalent globals. emitGlobalGOTEquivs(); - // Emit visibility info for declarations + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + // Emit linkage(XCOFF) and visibility info for declarations for (const Function &F : M) { if (!F.isDeclarationForLinker()) continue; - GlobalValue::VisibilityTypes V = F.getVisibility(); - if (V == GlobalValue::DefaultVisibility) - continue; MCSymbol *Name = getSymbol(&F); - EmitVisibility(Name, V, false); + // Function getSymbol gives us the function descriptor symbol for XCOFF. + + if (!TM.getTargetTriple().isOSBinFormatXCOFF()) { + GlobalValue::VisibilityTypes V = F.getVisibility(); + if (V == GlobalValue::DefaultVisibility) + continue; + + emitVisibility(Name, V, false); + continue; + } + + if (F.isIntrinsic()) + continue; + + // Handle the XCOFF case. + // Variable `Name` is the function descriptor symbol (see above). Get the + // function entry point symbol. + MCSymbol *FnEntryPointSym = TLOF.getFunctionEntryPointSymbol(&F, TM); + if (cast<MCSymbolXCOFF>(FnEntryPointSym)->hasRepresentedCsectSet()) + // Emit linkage for the function entry point. + emitLinkage(&F, FnEntryPointSym); + + // Emit linkage for the function descriptor. + emitLinkage(&F, Name); } // Emit the remarks section contents. // FIXME: Figure out when is the safest time to emit this section. It should // not come after debug info. - if (RemarkStreamer *RS = M.getContext().getRemarkStreamer()) + if (remarks::RemarkStreamer *RS = M.getContext().getMainRemarkStreamer()) emitRemarksSection(*RS); - const TargetLoweringObjectFile &TLOF = getObjFileLowering(); - TLOF.emitModuleMetadata(*OutStreamer, M); if (TM.getTargetTriple().isOSBinFormatELF()) { @@ -1462,10 +1542,10 @@ bool AsmPrinter::doFinalization(Module &M) { OutStreamer->SwitchSection(TLOF.getDataSection()); const DataLayout &DL = M.getDataLayout(); - EmitAlignment(Align(DL.getPointerSize())); + emitAlignment(Align(DL.getPointerSize())); for (const auto &Stub : Stubs) { - OutStreamer->EmitLabel(Stub.first); - OutStreamer->EmitSymbolValue(Stub.second.getPointer(), + OutStreamer->emitLabel(Stub.first); + OutStreamer->emitSymbolValue(Stub.second.getPointer(), DL.getPointerSize()); } } @@ -1489,10 +1569,10 @@ bool AsmPrinter::doFinalization(Module &M) { COFF::IMAGE_SCN_LNK_COMDAT, SectionKind::getReadOnly(), Stub.first->getName(), COFF::IMAGE_COMDAT_SELECT_ANY)); - EmitAlignment(Align(DL.getPointerSize())); - OutStreamer->EmitSymbolAttribute(Stub.first, MCSA_Global); - OutStreamer->EmitLabel(Stub.first); - OutStreamer->EmitSymbolValue(Stub.second.getPointer(), + emitAlignment(Align(DL.getPointerSize())); + OutStreamer->emitSymbolAttribute(Stub.first, MCSA_Global); + OutStreamer->emitLabel(Stub.first); + OutStreamer->emitSymbolValue(Stub.second.getPointer(), DL.getPointerSize()); } } @@ -1518,7 +1598,7 @@ bool AsmPrinter::doFinalization(Module &M) { for (const auto &GO : M.global_objects()) { if (!GO.hasExternalWeakLinkage()) continue; - OutStreamer->EmitSymbolAttribute(getSymbol(&GO), MCSA_WeakReference); + OutStreamer->emitSymbolAttribute(getSymbol(&GO), MCSA_WeakReference); } } @@ -1549,25 +1629,25 @@ bool AsmPrinter::doFinalization(Module &M) { MP->finishAssembly(M, *MI, *this); // Emit llvm.ident metadata in an '.ident' directive. - EmitModuleIdents(M); + emitModuleIdents(M); // Emit bytes for llvm.commandline metadata. - EmitModuleCommandLines(M); + emitModuleCommandLines(M); // Emit __morestack address if needed for indirect calls. if (MMI->usesMorestackAddr()) { - unsigned Align = 1; + Align Alignment(1); MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant( getDataLayout(), SectionKind::getReadOnly(), - /*C=*/nullptr, Align); + /*C=*/nullptr, Alignment); OutStreamer->SwitchSection(ReadOnlySection); MCSymbol *AddrSymbol = OutContext.getOrCreateSymbol(StringRef("__morestack_addr")); - OutStreamer->EmitLabel(AddrSymbol); + OutStreamer->emitLabel(AddrSymbol); unsigned PtrSize = MAI->getCodePointerSize(); - OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("__morestack"), + OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("__morestack"), PtrSize); } @@ -1599,7 +1679,7 @@ bool AsmPrinter::doFinalization(Module &M) { OS.flush(); if (!Flags.empty()) { OutStreamer->SwitchSection(TLOF.getDrectveSection()); - OutStreamer->EmitBytes(Flags); + OutStreamer->emitBytes(Flags); } Flags.clear(); } @@ -1625,7 +1705,7 @@ bool AsmPrinter::doFinalization(Module &M) { if (!Flags.empty()) { OutStreamer->SwitchSection(TLOF.getDrectveSection()); - OutStreamer->EmitBytes(Flags); + OutStreamer->emitBytes(Flags); } Flags.clear(); } @@ -1635,12 +1715,12 @@ bool AsmPrinter::doFinalization(Module &M) { if (TM.Options.EmitAddrsig) { // Emit address-significance attributes for all globals. - OutStreamer->EmitAddrsig(); + OutStreamer->emitAddrsig(); for (const GlobalValue &GV : M.global_values()) if (!GV.use_empty() && !GV.isThreadLocal() && !GV.hasDLLImportStorageClass() && !GV.getName().startswith("llvm.") && !GV.hasAtLeastLocalUnnamedAddr()) - OutStreamer->EmitAddrsigSym(getSymbol(&GV)); + OutStreamer->emitAddrsigSym(getSymbol(&GV)); } // Emit symbol partition specifications (ELF only). @@ -1651,11 +1731,12 @@ bool AsmPrinter::doFinalization(Module &M) { GV.getVisibility() != GlobalValue::DefaultVisibility) continue; - OutStreamer->SwitchSection(OutContext.getELFSection( - ".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, "", ++UniqueID)); - OutStreamer->EmitBytes(GV.getPartition()); - OutStreamer->EmitZeros(1); - OutStreamer->EmitValue( + OutStreamer->SwitchSection( + OutContext.getELFSection(".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, + "", ++UniqueID, nullptr)); + OutStreamer->emitBytes(GV.getPartition()); + OutStreamer->emitZeros(1); + OutStreamer->emitValue( MCSymbolRefExpr::create(getSymbol(&GV), OutContext), MAI->getCodePointerSize()); } @@ -1663,7 +1744,7 @@ bool AsmPrinter::doFinalization(Module &M) { // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. - EmitEndOfAsmFile(M); + emitEndOfAsmFile(M); MMI = nullptr; @@ -1686,30 +1767,31 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { const Function &F = MF.getFunction(); // Get the function symbol. - if (MAI->needsFunctionDescriptors()) { - assert(TM.getTargetTriple().isOSAIX() && "Function descriptor is only" - " supported on AIX."); + if (!MAI->needsFunctionDescriptors()) { + CurrentFnSym = getSymbol(&MF.getFunction()); + } else { + assert(TM.getTargetTriple().isOSAIX() && + "Only AIX uses the function descriptor hooks."); + // AIX is unique here in that the name of the symbol emitted for the + // function body does not have the same name as the source function's + // C-linkage name. assert(CurrentFnDescSym && "The function descriptor symbol needs to be" - " initalized first."); + " initalized first."); // Get the function entry point symbol. - CurrentFnSym = - OutContext.getOrCreateSymbol("." + CurrentFnDescSym->getName()); - - MCSectionXCOFF *FnEntryPointSec = - cast<MCSectionXCOFF>(getObjFileLowering().SectionForGlobal(&F, TM)); - // Set the containing csect. - cast<MCSymbolXCOFF>(CurrentFnSym)->setContainingCsect(FnEntryPointSec); - } else { - CurrentFnSym = getSymbol(&MF.getFunction()); + CurrentFnSym = getObjFileLowering().getFunctionEntryPointSymbol(&F, TM); } CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; + CurrentSectionBeginSym = nullptr; + MBBSectionRanges.clear(); CurExceptionSym = nullptr; bool NeedsLocalForSize = MAI->needsLocalForSize(); if (F.hasFnAttribute("patchable-function-entry") || - needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize || + F.hasFnAttribute("function-instrument") || + F.hasFnAttribute("xray-instruction-threshold") || + needFuncLabelsForEHOrDebugInfo(MF) || NeedsLocalForSize || MF.getTarget().Options.EmitStackSizeSection) { CurrentFnBegin = createTempSymbol("func_begin"); if (NeedsLocalForSize) @@ -1717,13 +1799,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { } ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); - PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(); - MBFI = (PSI && PSI->hasProfileSummary()) ? - // ORE conditionally computes MBFI. If available, use it, otherwise - // request it. - (ORE->getBFI() ? ORE->getBFI() : - &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()) : - nullptr; } namespace { @@ -1731,10 +1806,10 @@ namespace { // Keep track the alignment, constpool entries per Section. struct SectionCPs { MCSection *S; - unsigned Alignment; + Align Alignment; SmallVector<unsigned, 4> CPEs; - SectionCPs(MCSection *s, unsigned a) : S(s), Alignment(a) {} + SectionCPs(MCSection *s, Align a) : S(s), Alignment(a) {} }; } // end anonymous namespace @@ -1743,7 +1818,7 @@ namespace { /// representations of the constants in the constant pool MCP. This is /// used to print out constants which have been "spilled to memory" by /// the code generator. -void AsmPrinter::EmitConstantPool() { +void AsmPrinter::emitConstantPool() { const MachineConstantPool *MCP = MF->getConstantPool(); const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); if (CP.empty()) return; @@ -1753,7 +1828,7 @@ void AsmPrinter::EmitConstantPool() { SmallVector<SectionCPs, 4> CPSections; for (unsigned i = 0, e = CP.size(); i != e; ++i) { const MachineConstantPoolEntry &CPE = CP[i]; - unsigned Align = CPE.getAlignment(); + Align Alignment = CPE.getAlign(); SectionKind Kind = CPE.getSectionKind(&getDataLayout()); @@ -1761,8 +1836,8 @@ void AsmPrinter::EmitConstantPool() { if (!CPE.isMachineConstantPoolEntry()) C = CPE.Val.ConstVal; - MCSection *S = getObjFileLowering().getSectionForConstant(getDataLayout(), - Kind, C, Align); + MCSection *S = getObjFileLowering().getSectionForConstant( + getDataLayout(), Kind, C, Alignment); // The number of sections are small, just do a linear search from the // last section to the first. @@ -1776,11 +1851,11 @@ void AsmPrinter::EmitConstantPool() { } if (!Found) { SecIdx = CPSections.size(); - CPSections.push_back(SectionCPs(S, Align)); + CPSections.push_back(SectionCPs(S, Alignment)); } - if (Align > CPSections[SecIdx].Alignment) - CPSections[SecIdx].Alignment = Align; + if (Alignment > CPSections[SecIdx].Alignment) + CPSections[SecIdx].Alignment = Alignment; CPSections[SecIdx].CPEs.push_back(i); } @@ -1794,14 +1869,9 @@ void AsmPrinter::EmitConstantPool() { if (!Sym->isUndefined()) continue; - if (TM.getTargetTriple().isOSBinFormatXCOFF()) { - cast<MCSymbolXCOFF>(Sym)->setContainingCsect( - cast<MCSectionXCOFF>(CPSections[i].S)); - } - if (CurSection != CPSections[i].S) { OutStreamer->SwitchSection(CPSections[i].S); - EmitAlignment(Align(CPSections[i].Alignment)); + emitAlignment(Align(CPSections[i].Alignment)); CurSection = CPSections[i].S; Offset = 0; } @@ -1809,25 +1879,24 @@ void AsmPrinter::EmitConstantPool() { MachineConstantPoolEntry CPE = CP[CPI]; // Emit inter-object padding for alignment. - unsigned AlignMask = CPE.getAlignment() - 1; - unsigned NewOffset = (Offset + AlignMask) & ~AlignMask; - OutStreamer->EmitZeros(NewOffset - Offset); + unsigned NewOffset = alignTo(Offset, CPE.getAlign()); + OutStreamer->emitZeros(NewOffset - Offset); Type *Ty = CPE.getType(); Offset = NewOffset + getDataLayout().getTypeAllocSize(Ty); - OutStreamer->EmitLabel(Sym); + OutStreamer->emitLabel(Sym); if (CPE.isMachineConstantPoolEntry()) - EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); + emitMachineConstantPoolValue(CPE.Val.MachineCPVal); else - EmitGlobalConstant(getDataLayout(), CPE.Val.ConstVal); + emitGlobalConstant(getDataLayout(), CPE.Val.ConstVal); } } } -/// EmitJumpTableInfo - Print assembly representations of the jump tables used -/// by the current function to the current output stream. -void AsmPrinter::EmitJumpTableInfo() { +// Print assembly representations of the jump tables used by the current +// function. +void AsmPrinter::emitJumpTableInfo() { const DataLayout &DL = MF->getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); if (!MJTI) return; @@ -1848,12 +1917,12 @@ void AsmPrinter::EmitJumpTableInfo() { OutStreamer->SwitchSection(ReadOnlySection); } - EmitAlignment(Align(MJTI->getEntryAlignment(DL))); + emitAlignment(Align(MJTI->getEntryAlignment(DL))); // Jump tables in code sections are marked with a data_region directive // where that's supported. if (!JTInDiffSection) - OutStreamer->EmitDataRegion(MCDR_DataRegionJT32); + OutStreamer->emitDataRegion(MCDR_DataRegionJT32); for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; @@ -1876,7 +1945,7 @@ void AsmPrinter::EmitJumpTableInfo() { // .set LJTSet, LBB32-base const MCExpr *LHS = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); - OutStreamer->EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), + OutStreamer->emitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), MCBinaryExpr::createSub(LHS, Base, OutContext)); } @@ -1890,25 +1959,21 @@ void AsmPrinter::EmitJumpTableInfo() { // FIXME: This doesn't have to have any specific name, just any randomly // named and numbered local label started with 'l' would work. Simplify // GetJTISymbol. - OutStreamer->EmitLabel(GetJTISymbol(JTI, true)); + OutStreamer->emitLabel(GetJTISymbol(JTI, true)); MCSymbol* JTISymbol = GetJTISymbol(JTI); - if (TM.getTargetTriple().isOSBinFormatXCOFF()) { - cast<MCSymbolXCOFF>(JTISymbol)->setContainingCsect( - cast<MCSectionXCOFF>(TLOF.getSectionForJumpTable(F, TM))); - } - OutStreamer->EmitLabel(JTISymbol); + OutStreamer->emitLabel(JTISymbol); for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) - EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); + emitJumpTableEntry(MJTI, JTBBs[ii], JTI); } if (!JTInDiffSection) - OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); + OutStreamer->emitDataRegion(MCDR_DataRegionEnd); } /// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the /// current stream. -void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, +void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned UID) const { assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block"); @@ -1930,7 +1995,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, // with a relocation as gp-relative, e.g.: // .gprel32 LBB123 MCSymbol *MBBSym = MBB->getSymbol(); - OutStreamer->EmitGPRel32Value(MCSymbolRefExpr::create(MBBSym, OutContext)); + OutStreamer->emitGPRel32Value(MCSymbolRefExpr::create(MBBSym, OutContext)); return; } @@ -1939,7 +2004,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, // with a relocation as gp-relative, e.g.: // .gpdword LBB123 MCSymbol *MBBSym = MBB->getSymbol(); - OutStreamer->EmitGPRel64Value(MCSymbolRefExpr::create(MBBSym, OutContext)); + OutStreamer->emitGPRel64Value(MCSymbolRefExpr::create(MBBSym, OutContext)); return; } @@ -1967,16 +2032,16 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, assert(Value && "Unknown entry kind!"); unsigned EntrySize = MJTI->getEntrySize(getDataLayout()); - OutStreamer->EmitValue(Value, EntrySize); + OutStreamer->emitValue(Value, EntrySize); } /// EmitSpecialLLVMGlobal - Check to see if the specified global is a /// special global used by LLVM. If so, emit it and return true, otherwise /// do nothing and return false. -bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { +bool AsmPrinter::emitSpecialLLVMGlobal(const GlobalVariable *GV) { if (GV->getName() == "llvm.used") { if (MAI->hasNoDeadStrip()) // No need to emit this at all. - EmitLLVMUsedList(cast<ConstantArray>(GV->getInitializer())); + emitLLVMUsedList(cast<ConstantArray>(GV->getInitializer())); return true; } @@ -1990,14 +2055,14 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { assert(GV->hasInitializer() && "Not a special LLVM global!"); if (GV->getName() == "llvm.global_ctors") { - EmitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), + emitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), /* isCtor */ true); return true; } if (GV->getName() == "llvm.global_dtors") { - EmitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), + emitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), /* isCtor */ false); return true; @@ -2008,13 +2073,13 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { /// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each /// global in the specified llvm.used list. -void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) { +void AsmPrinter::emitLLVMUsedList(const ConstantArray *InitList) { // Should be an array of 'i8*'. for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { const GlobalValue *GV = dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts()); if (GV) - OutStreamer->EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip); + OutStreamer->emitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip); } } @@ -2032,27 +2097,16 @@ struct Structor { /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. -void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, +void AsmPrinter::emitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor) { // Should be an array of '{ i32, void ()*, i8* }' structs. The first value is the // init priority. if (!isa<ConstantArray>(List)) return; - // Sanity check the structors list. - const ConstantArray *InitList = dyn_cast<ConstantArray>(List); - if (!InitList) return; // Not an array! - StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType()); - if (!ETy || ETy->getNumElements() != 3 || - !isa<IntegerType>(ETy->getTypeAtIndex(0U)) || - !isa<PointerType>(ETy->getTypeAtIndex(1U)) || - !isa<PointerType>(ETy->getTypeAtIndex(2U))) - return; // Not (int, ptr, ptr). - // Gather the structors in a form that's convenient for sorting by priority. SmallVector<Structor, 8> Structors; - for (Value *O : InitList->operands()) { - ConstantStruct *CS = dyn_cast<ConstantStruct>(O); - if (!CS) continue; // Malformed. + for (Value *O : cast<ConstantArray>(List)->operands()) { + auto *CS = cast<ConstantStruct>(O); if (CS->getOperand(1)->isNullValue()) break; // Found a null terminator, skip the rest. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); @@ -2090,12 +2144,12 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, : Obj.getStaticDtorSection(S.Priority, KeySym)); OutStreamer->SwitchSection(OutputSection); if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection()) - EmitAlignment(Align); - EmitXXStructor(DL, S.Func); + emitAlignment(Align); + emitXXStructor(DL, S.Func); } } -void AsmPrinter::EmitModuleIdents(Module &M) { +void AsmPrinter::emitModuleIdents(Module &M) { if (!MAI->hasIdentDirective()) return; @@ -2105,12 +2159,12 @@ void AsmPrinter::EmitModuleIdents(Module &M) { assert(N->getNumOperands() == 1 && "llvm.ident metadata entry can have only one operand"); const MDString *S = cast<MDString>(N->getOperand(0)); - OutStreamer->EmitIdent(S->getString()); + OutStreamer->emitIdent(S->getString()); } } } -void AsmPrinter::EmitModuleCommandLines(Module &M) { +void AsmPrinter::emitModuleCommandLines(Module &M) { MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines(); if (!CommandLine) return; @@ -2121,14 +2175,14 @@ void AsmPrinter::EmitModuleCommandLines(Module &M) { OutStreamer->PushSection(); OutStreamer->SwitchSection(CommandLine); - OutStreamer->EmitZeros(1); + OutStreamer->emitZeros(1); for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { const MDNode *N = NMD->getOperand(i); assert(N->getNumOperands() == 1 && "llvm.commandline metadata entry can have only one operand"); const MDString *S = cast<MDString>(N->getOperand(0)); - OutStreamer->EmitBytes(S->getString()); - OutStreamer->EmitZeros(1); + OutStreamer->emitBytes(S->getString()); + OutStreamer->emitZeros(1); } OutStreamer->PopSection(); } @@ -2139,29 +2193,23 @@ void AsmPrinter::EmitModuleCommandLines(Module &M) { /// Emit a byte directive and value. /// -void AsmPrinter::emitInt8(int Value) const { - OutStreamer->EmitIntValue(Value, 1); -} +void AsmPrinter::emitInt8(int Value) const { OutStreamer->emitInt8(Value); } /// Emit a short directive and value. -void AsmPrinter::emitInt16(int Value) const { - OutStreamer->EmitIntValue(Value, 2); -} +void AsmPrinter::emitInt16(int Value) const { OutStreamer->emitInt16(Value); } /// Emit a long directive and value. -void AsmPrinter::emitInt32(int Value) const { - OutStreamer->EmitIntValue(Value, 4); -} +void AsmPrinter::emitInt32(int Value) const { OutStreamer->emitInt32(Value); } /// Emit a long long directive and value. void AsmPrinter::emitInt64(uint64_t Value) const { - OutStreamer->EmitIntValue(Value, 8); + OutStreamer->emitInt64(Value); } /// Emit something like ".long Hi-Lo" where the size in bytes of the directive /// is specified by Size and Hi/Lo specify the labels. This implicitly uses /// .set if it avoids relocations. -void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, +void AsmPrinter::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const { OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size); } @@ -2169,13 +2217,13 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, /// EmitLabelPlusOffset - Emit something like ".long Label+Offset" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. -void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, +void AsmPrinter::emitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, unsigned Size, bool IsSectionRelative) const { if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) { OutStreamer->EmitCOFFSecRel32(Label, Offset); if (Size > 4) - OutStreamer->EmitZeros(Size - 4); + OutStreamer->emitZeros(Size - 4); return; } @@ -2185,7 +2233,7 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, Expr = MCBinaryExpr::createAdd( Expr, MCConstantExpr::create(Offset, OutContext), OutContext); - OutStreamer->EmitValue(Expr, Size); + OutStreamer->emitValue(Expr, Size); } //===----------------------------------------------------------------------===// @@ -2194,17 +2242,17 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // two boundary. If a global value is specified, and if that global has // an explicit alignment requested, it will override the alignment request // if required for correctness. -void AsmPrinter::EmitAlignment(Align Alignment, const GlobalObject *GV) const { +void AsmPrinter::emitAlignment(Align Alignment, const GlobalObject *GV) const { if (GV) Alignment = getGVAlignment(GV, GV->getParent()->getDataLayout(), Alignment); - if (Alignment == Align::None()) + if (Alignment == Align(1)) return; // 1-byte aligned: no need to emit alignment. if (getCurrentSection()->getKind().isText()) - OutStreamer->EmitCodeAlignment(Alignment.value()); + OutStreamer->emitCodeAlignment(Alignment.value()); else - OutStreamer->EmitValueToAlignment(Alignment.value()); + OutStreamer->emitValueToAlignment(Alignment.value()); } //===----------------------------------------------------------------------===// @@ -2232,23 +2280,22 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { } switch (CE->getOpcode()) { - default: + default: { // If the code isn't optimized, there may be outstanding folding // opportunities. Attempt to fold the expression using DataLayout as a // last resort before giving up. - if (Constant *C = ConstantFoldConstant(CE, getDataLayout())) - if (C != CE) - return lowerConstant(C); + Constant *C = ConstantFoldConstant(CE, getDataLayout()); + if (C != CE) + return lowerConstant(C); // Otherwise report the problem to the user. - { - std::string S; - raw_string_ostream OS(S); - OS << "Unsupported expression in static initializer: "; - CE->printAsOperand(OS, /*PrintType=*/false, - !MF ? nullptr : MF->getFunction().getParent()); - report_fatal_error(OS.str()); - } + std::string S; + raw_string_ostream OS(S); + OS << "Unsupported expression in static initializer: "; + CE->printAsOperand(OS, /*PrintType=*/false, + !MF ? nullptr : MF->getFunction().getParent()); + report_fatal_error(OS.str()); + } case Instruction::GetElementPtr: { // Generate a symbolic expression for the byte address APInt OffsetAI(getDataLayout().getPointerTypeSizeInBits(CE->getType()), 0); @@ -2434,7 +2481,7 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL, // If this can be emitted with .ascii/.asciz, emit it as such. if (CDS->isString()) - return AP.OutStreamer->EmitBytes(CDS->getAsString()); + return AP.OutStreamer->emitBytes(CDS->getAsString()); // Otherwise, emit the values in successive locations. unsigned ElementByteSize = CDS->getElementByteSize(); @@ -2443,7 +2490,7 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL, if (AP.isVerbose()) AP.OutStreamer->GetCommentOS() << format("0x%" PRIx64 "\n", CDS->getElementAsInteger(i)); - AP.OutStreamer->EmitIntValue(CDS->getElementAsInteger(i), + AP.OutStreamer->emitIntValue(CDS->getElementAsInteger(i), ElementByteSize); } } else { @@ -2453,11 +2500,11 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL, } unsigned Size = DL.getTypeAllocSize(CDS->getType()); - unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) * - CDS->getNumElements(); + unsigned EmittedSize = + DL.getTypeAllocSize(CDS->getElementType()) * CDS->getNumElements(); assert(EmittedSize <= Size && "Size cannot be less than EmittedSize!"); if (unsigned Padding = Size - EmittedSize) - AP.OutStreamer->EmitZeros(Padding); + AP.OutStreamer->emitZeros(Padding); } static void emitGlobalConstantArray(const DataLayout &DL, @@ -2488,7 +2535,7 @@ static void emitGlobalConstantVector(const DataLayout &DL, unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) * CV->getType()->getNumElements(); if (unsigned Padding = Size - EmittedSize) - AP.OutStreamer->EmitZeros(Padding); + AP.OutStreamer->emitZeros(Padding); } static void emitGlobalConstantStruct(const DataLayout &DL, @@ -2513,7 +2560,7 @@ static void emitGlobalConstantStruct(const DataLayout &DL, // Insert padding - this may include padding to increase the size of the // current field up to the ABI size (if the struct is not packed) as well // as padding to ensure that the next field starts at the right offset. - AP.OutStreamer->EmitZeros(PadSize); + AP.OutStreamer->emitZeros(PadSize); } assert(SizeSoFar == Layout->getSizeInBytes() && "Layout of constant struct may be incorrect!"); @@ -2545,22 +2592,22 @@ static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP) { int Chunk = API.getNumWords() - 1; if (TrailingBytes) - AP.OutStreamer->EmitIntValue(p[Chunk--], TrailingBytes); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk--], TrailingBytes); for (; Chunk >= 0; --Chunk) - AP.OutStreamer->EmitIntValue(p[Chunk], sizeof(uint64_t)); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], sizeof(uint64_t)); } else { unsigned Chunk; for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk) - AP.OutStreamer->EmitIntValue(p[Chunk], sizeof(uint64_t)); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], sizeof(uint64_t)); if (TrailingBytes) - AP.OutStreamer->EmitIntValue(p[Chunk], TrailingBytes); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], TrailingBytes); } // Emit the tail padding for the long double. const DataLayout &DL = AP.getDataLayout(); - AP.OutStreamer->EmitZeros(DL.getTypeAllocSize(ET) - DL.getTypeStoreSize(ET)); + AP.OutStreamer->emitZeros(DL.getTypeAllocSize(ET) - DL.getTypeStoreSize(ET)); } static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) { @@ -2591,9 +2638,10 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { // [chunk1][chunk2] ... [chunkN]. // The most significant chunk is chunkN and it should be emitted first. // However, due to the alignment issue chunkN contains useless bits. - // Realign the chunks so that they contain only useless information: + // Realign the chunks so that they contain only useful information: // ExtraBits 0 1 (BitWidth / 64) - 1 // chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN] + ExtraBitsSize = alignTo(ExtraBitsSize, 8); ExtraBits = Realigned.getRawData()[0] & (((uint64_t)-1) >> (64 - ExtraBitsSize)); Realigned.lshrInPlace(ExtraBitsSize); @@ -2607,19 +2655,19 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { const uint64_t *RawData = Realigned.getRawData(); for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { uint64_t Val = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i]; - AP.OutStreamer->EmitIntValue(Val, 8); + AP.OutStreamer->emitIntValue(Val, 8); } if (ExtraBitsSize) { // Emit the extra bits after the 64-bits chunks. // Emit a directive that fills the expected size. - uint64_t Size = AP.getDataLayout().getTypeAllocSize(CI->getType()); + uint64_t Size = AP.getDataLayout().getTypeStoreSize(CI->getType()); Size -= (BitWidth / 64) * 8; assert(Size && Size * 8 >= ExtraBitsSize && (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) == ExtraBits && "Directive too small for extra bits."); - AP.OutStreamer->EmitIntValue(ExtraBits, Size); + AP.OutStreamer->emitIntValue(ExtraBits, Size); } } @@ -2726,30 +2774,32 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, BaseCV = dyn_cast<Constant>(CV->user_back()); if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) - return AP.OutStreamer->EmitZeros(Size); + return AP.OutStreamer->emitZeros(Size); if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - switch (Size) { - case 1: - case 2: - case 4: - case 8: + const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType()); + + if (StoreSize < 8) { if (AP.isVerbose()) AP.OutStreamer->GetCommentOS() << format("0x%" PRIx64 "\n", CI->getZExtValue()); - AP.OutStreamer->EmitIntValue(CI->getZExtValue(), Size); - return; - default: + AP.OutStreamer->emitIntValue(CI->getZExtValue(), StoreSize); + } else { emitGlobalConstantLargeInt(CI, AP); - return; } + + // Emit tail padding if needed + if (Size != StoreSize) + AP.OutStreamer->emitZeros(Size - StoreSize); + + return; } if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) return emitGlobalConstantFP(CFP, AP); if (isa<ConstantPointerNull>(CV)) { - AP.OutStreamer->EmitIntValue(0, Size); + AP.OutStreamer->emitIntValue(0, Size); return; } @@ -2773,7 +2823,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, // to emit the value in chunks. Try to constant fold the value and emit it // that way. Constant *New = ConstantFoldConstant(CE, DL); - if (New && New != CE) + if (New != CE) return emitGlobalConstantImpl(DL, New, AP); } } @@ -2791,22 +2841,22 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, if (AP.getObjFileLowering().supportIndirectSymViaGOTPCRel()) handleIndirectSymViaGOTPCRel(AP, &ME, BaseCV, Offset); - AP.OutStreamer->EmitValue(ME, Size); + AP.OutStreamer->emitValue(ME, Size); } /// EmitGlobalConstant - Print a general LLVM constant to the .s file. -void AsmPrinter::EmitGlobalConstant(const DataLayout &DL, const Constant *CV) { +void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV) { uint64_t Size = DL.getTypeAllocSize(CV->getType()); if (Size) emitGlobalConstantImpl(DL, CV, *this); else if (MAI->hasSubsectionsViaSymbols()) { // If the global has zero size, emit a single byte so that two labels don't // look like they are at the same location. - OutStreamer->EmitIntValue(0, 1); + OutStreamer->emitIntValue(0, 1); } } -void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { +void AsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { // Target doesn't support this yet! llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); } @@ -2850,12 +2900,13 @@ MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { const DataLayout &DL = MF->getDataLayout(); SectionKind Kind = CPE.getSectionKind(&DL); const Constant *C = CPE.Val.ConstVal; - unsigned Align = CPE.Alignment; + Align Alignment = CPE.Alignment; if (const MCSectionCOFF *S = dyn_cast<MCSectionCOFF>( - getObjFileLowering().getSectionForConstant(DL, Kind, C, Align))) { + getObjFileLowering().getSectionForConstant(DL, Kind, C, + Alignment))) { if (MCSymbol *Sym = S->getCOMDATSymbol()) { if (Sym->isUndefined()) - OutStreamer->EmitSymbolAttribute(Sym, MCSA_Global); + OutStreamer->emitSymbolAttribute(Sym, MCSA_Global); return Sym; } } @@ -2957,10 +3008,10 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); } -/// EmitBasicBlockStart - This method prints the label for the specified +/// emitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. -void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { +void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) { // End the previous funclet and start a new one. if (MBB.isEHFuncletEntry()) { for (const HandlerInfo &HI : Handlers) { @@ -2971,8 +3022,8 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { // Emit an alignment directive for this block, if needed. const Align Alignment = MBB.getAlignment(); - if (Alignment != Align::None()) - EmitAlignment(Alignment); + if (Alignment != Align(1)) + emitAlignment(Alignment); // If the block has its address taken, emit any labels that were used to // reference the block. It is possible that there is more than one label @@ -2987,7 +3038,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { // their corresponding BB's address taken in IR if (BB->hasAddressTaken()) for (MCSymbol *Sym : MMI->getAddrLabelSymbolToEmit(BB)) - OutStreamer->EmitLabel(Sym); + OutStreamer->emitLabel(Sym); } // Print some verbose block comments. @@ -3004,25 +3055,44 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { emitBasicBlockLoopComments(MBB, MLI, *this); } - // Print the main label for the block. if (MBB.pred_empty() || - (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() && - !MBB.hasLabelMustBeEmitted())) { + (!MF->hasBBLabels() && isBlockOnlyReachableByFallthrough(&MBB) && + !MBB.isEHFuncletEntry() && !MBB.hasLabelMustBeEmitted())) { if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":", false); } } else { - if (isVerbose() && MBB.hasLabelMustBeEmitted()) + if (isVerbose() && MBB.hasLabelMustBeEmitted()) { OutStreamer->AddComment("Label of block must be emitted"); - OutStreamer->EmitLabel(MBB.getSymbol()); + } + auto *BBSymbol = MBB.getSymbol(); + // Switch to a new section if this basic block must begin a section. + if (MBB.isBeginSection()) { + OutStreamer->SwitchSection( + getObjFileLowering().getSectionForMachineBasicBlock(MF->getFunction(), + MBB, TM)); + CurrentSectionBeginSym = BBSymbol; + } + OutStreamer->emitLabel(BBSymbol); + // With BB sections, each basic block must handle CFI information on its own + // if it begins a section. + if (MBB.isBeginSection()) + for (const HandlerInfo &HI : Handlers) + HI.Handler->beginBasicBlock(MBB); } } -void AsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} +void AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) { + // Check if CFI information needs to be updated for this MBB with basic block + // sections. + if (MBB.isEndSection()) + for (const HandlerInfo &HI : Handlers) + HI.Handler->endBasicBlock(MBB); +} -void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, +void AsmPrinter::emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition) const { MCSymbolAttr Attr = MCSA_Invalid; @@ -3040,7 +3110,7 @@ void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, } if (Attr != MCSA_Invalid) - OutStreamer->EmitSymbolAttribute(Sym, Attr); + OutStreamer->emitSymbolAttribute(Sym, Attr); } /// isBlockOnlyReachableByFallthough - Return true if the basic block has @@ -3048,6 +3118,10 @@ void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, /// the predecessor and this block is a fall-through. bool AsmPrinter:: isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // With BasicBlock Sections, beginning of the section is not a fallthrough. + if (MBB->isBeginSection()) + return false; + // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. if (MBB->isEHPad() || MBB->pred_empty()) @@ -3097,11 +3171,10 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) { auto Name = S.getName(); - for (GCMetadataPrinterRegistry::iterator - I = GCMetadataPrinterRegistry::begin(), - E = GCMetadataPrinterRegistry::end(); I != E; ++I) - if (Name == I->getName()) { - std::unique_ptr<GCMetadataPrinter> GMP = I->instantiate(); + for (const GCMetadataPrinterRegistry::entry &GCMetaPrinter : + GCMetadataPrinterRegistry::entries()) + if (Name == GCMetaPrinter.getName()) { + std::unique_ptr<GCMetadataPrinter> GMP = GCMetaPrinter.instantiate(); GMP->S = &S; auto IterBool = GCMap.insert(std::make_pair(&S, std::move(GMP))); return IterBool.first->second.get(); @@ -3139,18 +3212,15 @@ void AsmPrinterHandler::markFunctionEnd() {} // In the binary's "xray_instr_map" section, an array of these function entries // describes each instrumentation point. When XRay patches your code, the index // into this table will be given to your handler as a patch point identifier. -void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out, - const MCSymbol *CurrentFnSym) const { - Out->EmitSymbolValue(Sled, Bytes); - Out->EmitSymbolValue(CurrentFnSym, Bytes); +void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out) const { auto Kind8 = static_cast<uint8_t>(Kind); - Out->EmitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1)); - Out->EmitBinaryData( + Out->emitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1)); + Out->emitBinaryData( StringRef(reinterpret_cast<const char *>(&AlwaysInstrument), 1)); - Out->EmitBinaryData(StringRef(reinterpret_cast<const char *>(&Version), 1)); + Out->emitBinaryData(StringRef(reinterpret_cast<const char *>(&Version), 1)); auto Padding = (4 * Bytes) - ((2 * Bytes) + 3); assert(Padding >= 0 && "Instrumentation map entry > 4 * Word Size"); - Out->EmitZeros(Padding); + Out->emitZeros(Padding); } void AsmPrinter::emitXRayTable() { @@ -3161,28 +3231,34 @@ void AsmPrinter::emitXRayTable() { const Function &F = MF->getFunction(); MCSection *InstMap = nullptr; MCSection *FnSledIndex = nullptr; - if (MF->getSubtarget().getTargetTriple().isOSBinFormatELF()) { - auto Associated = dyn_cast<MCSymbolELF>(CurrentFnSym); - assert(Associated != nullptr); - auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER; - std::string GroupName; + const Triple &TT = TM.getTargetTriple(); + // Use PC-relative addresses on all targets except MIPS (MIPS64 cannot use + // PC-relative addresses because R_MIPS_PC64 does not exist). + bool PCRel = !TT.isMIPS(); + if (TT.isOSBinFormatELF()) { + auto LinkedToSym = cast<MCSymbolELF>(CurrentFnSym); + auto Flags = ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER; + if (!PCRel) + Flags |= ELF::SHF_WRITE; + StringRef GroupName; if (F.hasComdat()) { Flags |= ELF::SHF_GROUP; GroupName = F.getComdat()->getName(); } - - auto UniqueID = ++XRayFnUniqueID; - InstMap = - OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, Flags, 0, - GroupName, UniqueID, Associated); - FnSledIndex = - OutContext.getELFSection("xray_fn_idx", ELF::SHT_PROGBITS, Flags, 0, - GroupName, UniqueID, Associated); + InstMap = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, + Flags, 0, GroupName, + MCSection::NonUniqueID, LinkedToSym); + + if (!TM.Options.XRayOmitFunctionIndex) + FnSledIndex = OutContext.getELFSection( + "xray_fn_idx", ELF::SHT_PROGBITS, Flags | ELF::SHF_WRITE, 0, + GroupName, MCSection::NonUniqueID, LinkedToSym); } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) { InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map", 0, SectionKind::getReadOnlyWithRel()); - FnSledIndex = OutContext.getMachOSection("__DATA", "xray_fn_idx", 0, - SectionKind::getReadOnlyWithRel()); + if (!TM.Options.XRayOmitFunctionIndex) + FnSledIndex = OutContext.getMachOSection( + "__DATA", "xray_fn_idx", 0, SectionKind::getReadOnlyWithRel()); } else { llvm_unreachable("Unsupported target"); } @@ -3192,23 +3268,46 @@ void AsmPrinter::emitXRayTable() { // Now we switch to the instrumentation map section. Because this is done // per-function, we are able to create an index entry that will represent the // range of sleds associated with a function. + auto &Ctx = OutContext; MCSymbol *SledsStart = OutContext.createTempSymbol("xray_sleds_start", true); OutStreamer->SwitchSection(InstMap); - OutStreamer->EmitLabel(SledsStart); - for (const auto &Sled : Sleds) - Sled.emit(WordSizeBytes, OutStreamer.get(), CurrentFnSym); + OutStreamer->emitLabel(SledsStart); + for (const auto &Sled : Sleds) { + if (PCRel) { + MCSymbol *Dot = Ctx.createTempSymbol(); + OutStreamer->emitLabel(Dot); + OutStreamer->emitValueImpl( + MCBinaryExpr::createSub(MCSymbolRefExpr::create(Sled.Sled, Ctx), + MCSymbolRefExpr::create(Dot, Ctx), Ctx), + WordSizeBytes); + OutStreamer->emitValueImpl( + MCBinaryExpr::createSub( + MCSymbolRefExpr::create(CurrentFnBegin, Ctx), + MCBinaryExpr::createAdd( + MCSymbolRefExpr::create(Dot, Ctx), + MCConstantExpr::create(WordSizeBytes, Ctx), Ctx), + Ctx), + WordSizeBytes); + } else { + OutStreamer->emitSymbolValue(Sled.Sled, WordSizeBytes); + OutStreamer->emitSymbolValue(CurrentFnSym, WordSizeBytes); + } + Sled.emit(WordSizeBytes, OutStreamer.get()); + } MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true); - OutStreamer->EmitLabel(SledsEnd); + OutStreamer->emitLabel(SledsEnd); // We then emit a single entry in the index per function. We use the symbols // that bound the instrumentation map as the range for a specific function. // Each entry here will be 2 * word size aligned, as we're writing down two // pointers. This should work for both 32-bit and 64-bit platforms. - OutStreamer->SwitchSection(FnSledIndex); - OutStreamer->EmitCodeAlignment(2 * WordSizeBytes); - OutStreamer->EmitSymbolValue(SledsStart, WordSizeBytes, false); - OutStreamer->EmitSymbolValue(SledsEnd, WordSizeBytes, false); - OutStreamer->SwitchSection(PrevSection); + if (FnSledIndex) { + OutStreamer->SwitchSection(FnSledIndex); + OutStreamer->emitCodeAlignment(2 * WordSizeBytes); + OutStreamer->emitSymbolValue(SledsStart, WordSizeBytes, false); + OutStreamer->emitSymbolValue(SledsEnd, WordSizeBytes, false); + OutStreamer->SwitchSection(PrevSection); + } Sleds.clear(); } @@ -3239,31 +3338,24 @@ void AsmPrinter::emitPatchableFunctionEntries() { const unsigned PointerSize = getPointerSize(); if (TM.getTargetTriple().isOSBinFormatELF()) { auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC; + const MCSymbolELF *LinkedToSym = nullptr; + StringRef GroupName; - // As of binutils 2.33, GNU as does not support section flag "o" or linkage - // field "unique". Use SHF_LINK_ORDER if we are using the integrated - // assembler. + // GNU as < 2.35 did not support section flag 'o'. Use SHF_LINK_ORDER only + // if we are using the integrated assembler. if (MAI->useIntegratedAssembler()) { Flags |= ELF::SHF_LINK_ORDER; - std::string GroupName; if (F.hasComdat()) { Flags |= ELF::SHF_GROUP; GroupName = F.getComdat()->getName(); } - MCSection *Section = getObjFileLowering().SectionForGlobal(&F, TM); - unsigned UniqueID = - PatchableFunctionEntryID - .try_emplace(Section, PatchableFunctionEntryID.size()) - .first->second; - OutStreamer->SwitchSection(OutContext.getELFSection( - "__patchable_function_entries", ELF::SHT_PROGBITS, Flags, 0, - GroupName, UniqueID, cast<MCSymbolELF>(CurrentFnSym))); - } else { - OutStreamer->SwitchSection(OutContext.getELFSection( - "__patchable_function_entries", ELF::SHT_PROGBITS, Flags)); + LinkedToSym = cast<MCSymbolELF>(CurrentFnSym); } - EmitAlignment(Align(PointerSize)); - OutStreamer->EmitSymbolValue(CurrentPatchableFunctionEntrySym, PointerSize); + OutStreamer->SwitchSection(OutContext.getELFSection( + "__patchable_function_entries", ELF::SHT_PROGBITS, Flags, 0, GroupName, + MCSection::NonUniqueID, LinkedToSym)); + emitAlignment(Align(PointerSize)); + OutStreamer->emitSymbolValue(CurrentPatchableFunctionEntrySym, PointerSize); } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 992e44d95306..d81a9be26d39 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -36,22 +36,23 @@ using namespace llvm; //===----------------------------------------------------------------------===// /// EmitSLEB128 - emit the specified signed leb128 value. -void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const { +void AsmPrinter::emitSLEB128(int64_t Value, const char *Desc) const { if (isVerbose() && Desc) OutStreamer->AddComment(Desc); - OutStreamer->EmitSLEB128IntValue(Value); + OutStreamer->emitSLEB128IntValue(Value); } -void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc, unsigned PadTo) const { +void AsmPrinter::emitULEB128(uint64_t Value, const char *Desc, + unsigned PadTo) const { if (isVerbose() && Desc) OutStreamer->AddComment(Desc); - OutStreamer->EmitULEB128IntValue(Value, PadTo); + OutStreamer->emitULEB128IntValue(Value, PadTo); } /// Emit something like ".uleb128 Hi-Lo". -void AsmPrinter::EmitLabelDifferenceAsULEB128(const MCSymbol *Hi, +void AsmPrinter::emitLabelDifferenceAsULEB128(const MCSymbol *Hi, const MCSymbol *Lo) const { OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); } @@ -105,7 +106,7 @@ static const char *DecodeDWARFEncoding(unsigned Encoding) { /// encoding. If verbose assembly output is enabled, we output comments /// describing the encoding. Desc is an optional string saying what the /// encoding is specifying (e.g. "LSDA"). -void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { +void AsmPrinter::emitEncodingByte(unsigned Val, const char *Desc) const { if (isVerbose()) { if (Desc) OutStreamer->AddComment(Twine(Desc) + " Encoding = " + @@ -114,7 +115,7 @@ void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); } - OutStreamer->EmitIntValue(Val, 1); + OutStreamer->emitIntValue(Val, 1); } /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. @@ -136,16 +137,16 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { } } -void AsmPrinter::EmitTTypeReference(const GlobalValue *GV, +void AsmPrinter::emitTTypeReference(const GlobalValue *GV, unsigned Encoding) const { if (GV) { const TargetLoweringObjectFile &TLOF = getObjFileLowering(); const MCExpr *Exp = TLOF.getTTypeGlobalReference(GV, Encoding, TM, MMI, *OutStreamer); - OutStreamer->EmitValue(Exp, GetSizeOfEncodedValue(Encoding)); + OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding)); } else - OutStreamer->EmitIntValue(0, GetSizeOfEncodedValue(Encoding)); + OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding)); } void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label, @@ -159,13 +160,13 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label, // If the format uses relocations with dwarf, refer to the symbol directly. if (MAI->doesDwarfUseRelocationsAcrossSections()) { - OutStreamer->EmitSymbolValue(Label, 4); + OutStreamer->emitSymbolValue(Label, 4); return; } } // Otherwise, emit it as a label difference from the start of the section. - EmitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4); + emitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4); } void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { @@ -179,27 +180,26 @@ void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { emitInt32(S.Offset); } -void AsmPrinter::EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { - EmitLabelPlusOffset(Label, Offset, MAI->getCodePointerSize()); +void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { + // TODO: Support DWARF64 + emitLabelPlusOffset(Label, Offset, 4); } -void AsmPrinter::EmitCallSiteOffset(const MCSymbol *Hi, - const MCSymbol *Lo, +void AsmPrinter::emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Encoding) const { // The least significant 3 bits specify the width of the encoding if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128) - EmitLabelDifferenceAsULEB128(Hi, Lo); + emitLabelDifferenceAsULEB128(Hi, Lo); else - EmitLabelDifference(Hi, Lo, GetSizeOfEncodedValue(Encoding)); + emitLabelDifference(Hi, Lo, GetSizeOfEncodedValue(Encoding)); } -void AsmPrinter::EmitCallSiteValue(uint64_t Value, - unsigned Encoding) const { +void AsmPrinter::emitCallSiteValue(uint64_t Value, unsigned Encoding) const { // The least significant 3 bits specify the width of the encoding if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128) - EmitULEB128(Value); + emitULEB128(Value); else - OutStreamer->EmitIntValue(Value, GetSizeOfEncodedValue(Encoding)); + OutStreamer->emitIntValue(Value, GetSizeOfEncodedValue(Encoding)); } //===----------------------------------------------------------------------===// @@ -211,40 +211,43 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { default: llvm_unreachable("Unexpected instruction"); case MCCFIInstruction::OpDefCfaOffset: - OutStreamer->EmitCFIDefCfaOffset(Inst.getOffset()); + OutStreamer->emitCFIDefCfaOffset(Inst.getOffset()); break; case MCCFIInstruction::OpAdjustCfaOffset: - OutStreamer->EmitCFIAdjustCfaOffset(Inst.getOffset()); + OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset()); break; case MCCFIInstruction::OpDefCfa: - OutStreamer->EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset()); + OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset()); break; case MCCFIInstruction::OpDefCfaRegister: - OutStreamer->EmitCFIDefCfaRegister(Inst.getRegister()); + OutStreamer->emitCFIDefCfaRegister(Inst.getRegister()); break; case MCCFIInstruction::OpOffset: - OutStreamer->EmitCFIOffset(Inst.getRegister(), Inst.getOffset()); + OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset()); break; case MCCFIInstruction::OpRegister: - OutStreamer->EmitCFIRegister(Inst.getRegister(), Inst.getRegister2()); + OutStreamer->emitCFIRegister(Inst.getRegister(), Inst.getRegister2()); break; case MCCFIInstruction::OpWindowSave: - OutStreamer->EmitCFIWindowSave(); + OutStreamer->emitCFIWindowSave(); break; case MCCFIInstruction::OpNegateRAState: - OutStreamer->EmitCFINegateRAState(); + OutStreamer->emitCFINegateRAState(); break; case MCCFIInstruction::OpSameValue: - OutStreamer->EmitCFISameValue(Inst.getRegister()); + OutStreamer->emitCFISameValue(Inst.getRegister()); break; case MCCFIInstruction::OpGnuArgsSize: - OutStreamer->EmitCFIGnuArgsSize(Inst.getOffset()); + OutStreamer->emitCFIGnuArgsSize(Inst.getOffset()); break; case MCCFIInstruction::OpEscape: - OutStreamer->EmitCFIEscape(Inst.getValues()); + OutStreamer->emitCFIEscape(Inst.getValues()); break; case MCCFIInstruction::OpRestore: - OutStreamer->EmitCFIRestore(Inst.getRegister()); + OutStreamer->emitCFIRestore(Inst.getRegister()); + break; + case MCCFIInstruction::OpUndefined: + OutStreamer->emitCFIUndefined(Inst.getRegister()); break; } } @@ -256,7 +259,7 @@ void AsmPrinter::emitDwarfDIE(const DIE &Die) const { Twine::utohexstr(Die.getOffset()) + ":0x" + Twine::utohexstr(Die.getSize()) + " " + dwarf::TagString(Die.getTag())); - EmitULEB128(Die.getAbbrevNumber()); + emitULEB128(Die.getAbbrevNumber()); // Emit the DIE attribute values. for (const auto &V : Die.values()) { @@ -271,7 +274,7 @@ void AsmPrinter::emitDwarfDIE(const DIE &Die) const { } // Emit an attribute using the defined form. - V.EmitValue(this); + V.emitValue(this); } // Emit the DIE children if any. @@ -286,7 +289,7 @@ void AsmPrinter::emitDwarfDIE(const DIE &Die) const { void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { // Emit the abbreviations code (base 1 index.) - EmitULEB128(Abbrev.getNumber(), "Abbreviation Code"); + emitULEB128(Abbrev.getNumber(), "Abbreviation Code"); // Emit the abbreviations data. Abbrev.Emit(this); diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index c631cc5360b8..538107cecd8b 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -106,7 +106,7 @@ unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr, /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. -void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, +void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MCTargetOptions &MCOptions, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { @@ -127,7 +127,7 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, if (!MCAI->useIntegratedAssembler() && !OutStreamer->isIntegratedAssemblerRequired()) { emitInlineAsmStart(); - OutStreamer->EmitRawText(Str); + OutStreamer->emitRawText(Str); emitInlineAsmEnd(STI, nullptr); return; } @@ -489,9 +489,9 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, OS << '\n' << (char)0; // null terminate string. } -/// EmitInlineAsm - This method formats and emits the specified machine -/// instruction that is an inline asm. -void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { +/// This method formats and emits the specified machine instruction that is an +/// inline asm. +void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const { assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); // Count the number of register definitions to find the asm string. @@ -584,7 +584,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note); } - EmitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD, + emitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD, MI->getInlineAsmDialect()); // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't @@ -592,7 +592,6 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { OutStreamer->emitRawComment(MAI->getInlineAsmEnd()); } - /// PrintSpecial - Print information related to the specified machine instr /// that is independent of the operand, and may be independent of the instr /// itself. This can be useful for portably encoding the comment character diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h index 09f7496cd4ef..90929a217368 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h @@ -30,8 +30,9 @@ class ByteStreamer { public: // For now we're just handling the calls we need for dwarf emission/hashing. virtual void EmitInt8(uint8_t Byte, const Twine &Comment = "") = 0; - virtual void EmitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0; - virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "", unsigned PadTo = 0) = 0; + virtual void emitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0; + virtual void emitULEB128(uint64_t DWord, const Twine &Comment = "", + unsigned PadTo = 0) = 0; }; class APByteStreamer final : public ByteStreamer { @@ -44,13 +45,14 @@ public: AP.OutStreamer->AddComment(Comment); AP.emitInt8(Byte); } - void EmitSLEB128(uint64_t DWord, const Twine &Comment) override { + void emitSLEB128(uint64_t DWord, const Twine &Comment) override { AP.OutStreamer->AddComment(Comment); - AP.EmitSLEB128(DWord); + AP.emitSLEB128(DWord); } - void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override { + void emitULEB128(uint64_t DWord, const Twine &Comment, + unsigned PadTo) override { AP.OutStreamer->AddComment(Comment); - AP.EmitULEB128(DWord); + AP.emitULEB128(DWord, nullptr, PadTo); } }; @@ -62,10 +64,11 @@ class HashingByteStreamer final : public ByteStreamer { void EmitInt8(uint8_t Byte, const Twine &Comment) override { Hash.update(Byte); } - void EmitSLEB128(uint64_t DWord, const Twine &Comment) override { + void emitSLEB128(uint64_t DWord, const Twine &Comment) override { Hash.addSLEB128(DWord); } - void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override { + void emitULEB128(uint64_t DWord, const Twine &Comment, + unsigned PadTo) override { Hash.addULEB128(DWord); } }; @@ -90,7 +93,7 @@ public: if (GenerateComments) Comments.push_back(Comment.str()); } - void EmitSLEB128(uint64_t DWord, const Twine &Comment) override { + void emitSLEB128(uint64_t DWord, const Twine &Comment) override { raw_svector_ostream OSE(Buffer); unsigned Length = encodeSLEB128(DWord, OSE); if (GenerateComments) { @@ -102,7 +105,8 @@ public: } } - void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override { + void emitULEB128(uint64_t DWord, const Twine &Comment, + unsigned PadTo) override { raw_svector_ostream OSE(Buffer); unsigned Length = encodeULEB128(DWord, OSE, PadTo); if (GenerateComments) { diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 62ad356e7f8f..3f053c7a38c7 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -101,27 +101,27 @@ public: CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable) : OS(&OS), TypeTable(TypeTable) {} - void EmitBytes(StringRef Data) { OS->EmitBytes(Data); } + void emitBytes(StringRef Data) override { OS->emitBytes(Data); } - void EmitIntValue(uint64_t Value, unsigned Size) { - OS->EmitIntValueInHex(Value, Size); + void emitIntValue(uint64_t Value, unsigned Size) override { + OS->emitIntValueInHex(Value, Size); } - void EmitBinaryData(StringRef Data) { OS->EmitBinaryData(Data); } + void emitBinaryData(StringRef Data) override { OS->emitBinaryData(Data); } - void AddComment(const Twine &T) { OS->AddComment(T); } + void AddComment(const Twine &T) override { OS->AddComment(T); } - void AddRawComment(const Twine &T) { OS->emitRawComment(T); } + void AddRawComment(const Twine &T) override { OS->emitRawComment(T); } - bool isVerboseAsm() { return OS->isVerboseAsm(); } + bool isVerboseAsm() override { return OS->isVerboseAsm(); } - std::string getTypeName(TypeIndex TI) { + std::string getTypeName(TypeIndex TI) override { std::string TypeName; if (!TI.isNoneType()) { if (TI.isSimple()) - TypeName = TypeIndex::simpleTypeName(TI); + TypeName = std::string(TypeIndex::simpleTypeName(TI)); else - TypeName = TypeTable.getTypeName(TI); + TypeName = std::string(TypeTable.getTypeName(TI)); } return TypeName; } @@ -183,7 +183,7 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { if (Dir.startswith("/") || Filename.startswith("/")) { if (llvm::sys::path::is_absolute(Filename, llvm::sys::path::Style::posix)) return Filename; - Filepath = Dir; + Filepath = std::string(Dir); if (Dir.back() != '/') Filepath += '/'; Filepath += Filename; @@ -195,7 +195,7 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { // that would increase the IR size and probably not needed for other users. // For now, just concatenate and canonicalize the path here. if (Filename.find(':') == 1) - Filepath = Filename; + Filepath = std::string(Filename); else Filepath = (Dir + "\\" + Filename).str(); @@ -250,8 +250,15 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) { ChecksumAsBytes = ArrayRef<uint8_t>( reinterpret_cast<const uint8_t *>(CKMem), Checksum.size()); switch (F->getChecksum()->Kind) { - case DIFile::CSK_MD5: CSKind = FileChecksumKind::MD5; break; - case DIFile::CSK_SHA1: CSKind = FileChecksumKind::SHA1; break; + case DIFile::CSK_MD5: + CSKind = FileChecksumKind::MD5; + break; + case DIFile::CSK_SHA1: + CSKind = FileChecksumKind::SHA1; + break; + case DIFile::CSK_SHA256: + CSKind = FileChecksumKind::SHA256; + break; } } bool Success = OS.EmitCVFileDirective(NextId, FullPath, ChecksumAsBytes, @@ -303,12 +310,19 @@ static StringRef getPrettyScopeName(const DIScope *Scope) { return StringRef(); } -static const DISubprogram *getQualifiedNameComponents( +const DISubprogram *CodeViewDebug::collectParentScopeNames( const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) { const DISubprogram *ClosestSubprogram = nullptr; while (Scope != nullptr) { if (ClosestSubprogram == nullptr) ClosestSubprogram = dyn_cast<DISubprogram>(Scope); + + // If a type appears in a scope chain, make sure it gets emitted. The + // frontend will be responsible for deciding if this should be a forward + // declaration or a complete type. + if (const auto *Ty = dyn_cast<DICompositeType>(Scope)) + DeferredCompleteTypes.push_back(Ty); + StringRef ScopeName = getPrettyScopeName(Scope); if (!ScopeName.empty()) QualifiedNameComponents.push_back(ScopeName); @@ -317,24 +331,18 @@ static const DISubprogram *getQualifiedNameComponents( return ClosestSubprogram; } -static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents, +static std::string formatNestedName(ArrayRef<StringRef> QualifiedNameComponents, StringRef TypeName) { std::string FullyQualifiedName; for (StringRef QualifiedNameComponent : llvm::reverse(QualifiedNameComponents)) { - FullyQualifiedName.append(QualifiedNameComponent); + FullyQualifiedName.append(std::string(QualifiedNameComponent)); FullyQualifiedName.append("::"); } - FullyQualifiedName.append(TypeName); + FullyQualifiedName.append(std::string(TypeName)); return FullyQualifiedName; } -static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) { - SmallVector<StringRef, 5> QualifiedNameComponents; - getQualifiedNameComponents(Scope, QualifiedNameComponents); - return getQualifiedName(QualifiedNameComponents, Name); -} - struct CodeViewDebug::TypeLoweringScope { TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; } ~TypeLoweringScope() { @@ -347,7 +355,18 @@ struct CodeViewDebug::TypeLoweringScope { CodeViewDebug &CVD; }; -static std::string getFullyQualifiedName(const DIScope *Ty) { +std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Scope, + StringRef Name) { + // Ensure types in the scope chain are emitted as soon as possible. + // This can create otherwise a situation where S_UDTs are emitted while + // looping in emitDebugInfoForUDTs. + TypeLoweringScope S(*this); + SmallVector<StringRef, 5> QualifiedNameComponents; + collectParentScopeNames(Scope, QualifiedNameComponents); + return formatNestedName(QualifiedNameComponents, Name); +} + +std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Ty) { const DIScope *Scope = Ty->getScope(); return getFullyQualifiedName(Scope, getPrettyScopeName(Ty)); } @@ -418,10 +437,11 @@ getFunctionOptions(const DISubroutineType *Ty, ReturnTy = TypeArray[0]; } - if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) { - if (isNonTrivial(ReturnDCTy)) + // Add CxxReturnUdt option to functions that return nontrivial record types + // or methods that return record types. + if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) + if (isNonTrivial(ReturnDCTy) || ClassTy) FO |= FunctionOptions::CxxReturnUdt; - } // DISubroutineType is unnamed. Use DISubprogram's i.e. SPName in comparison. if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) { @@ -543,15 +563,15 @@ void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL, addLocIfNotPresent(CurFn->ChildSites, Loc); } - OS.EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), + OS.emitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), /*PrologueEnd=*/false, /*IsStmt=*/false, DL->getFilename(), SMLoc()); } void CodeViewDebug::emitCodeViewMagicVersion() { - OS.EmitValueToAlignment(4); + OS.emitValueToAlignment(4); OS.AddComment("Debug section magic"); - OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4); + OS.emitInt32(COFF::DEBUG_SECTION_MAGIC); } void CodeViewDebug::endModule() { @@ -600,11 +620,11 @@ void CodeViewDebug::endModule() { // This subsection holds a file index to offset in string table table. OS.AddComment("File index to string table offset subsection"); - OS.EmitCVFileChecksumsDirective(); + OS.emitCVFileChecksumsDirective(); // This subsection holds the string table. OS.AddComment("String table"); - OS.EmitCVStringTableDirective(); + OS.emitCVStringTableDirective(); // Emit S_BUILDINFO, which points to LF_BUILDINFO. Put this in its own symbol // subsection in the generic .debug$S section at the end. There is no @@ -631,7 +651,7 @@ emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, SmallString<32> NullTerminatedString( S.take_front(MaxRecordLength - MaxFixedRecordLength - 1)); NullTerminatedString.push_back('\0'); - OS.EmitBytes(NullTerminatedString); + OS.emitBytes(NullTerminatedString); } void CodeViewDebug::emitTypeInformation() { @@ -674,13 +694,13 @@ void CodeViewDebug::emitTypeGlobalHashes() { // hardcoded to version 0, SHA1. OS.SwitchSection(Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection()); - OS.EmitValueToAlignment(4); + OS.emitValueToAlignment(4); OS.AddComment("Magic"); - OS.EmitIntValue(COFF::DEBUG_HASHES_SECTION_MAGIC, 4); + OS.emitInt32(COFF::DEBUG_HASHES_SECTION_MAGIC); OS.AddComment("Section Version"); - OS.EmitIntValue(0, 2); + OS.emitInt16(0); OS.AddComment("Hash Algorithm"); - OS.EmitIntValue(uint16_t(GlobalTypeHashAlg::SHA1_8), 2); + OS.emitInt16(uint16_t(GlobalTypeHashAlg::SHA1_8)); TypeIndex TI(TypeIndex::FirstNonSimpleIndex); for (const auto &GHR : TypeTable.hashes()) { @@ -696,7 +716,7 @@ void CodeViewDebug::emitTypeGlobalHashes() { assert(GHR.Hash.size() == 8); StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()), GHR.Hash.size()); - OS.EmitBinaryData(S); + OS.emitBinaryData(S); } } @@ -775,16 +795,16 @@ void CodeViewDebug::emitCompilerInformation() { // TODO: Figure out which other flags need to be set. OS.AddComment("Flags and language"); - OS.EmitIntValue(Flags, 4); + OS.emitInt32(Flags); OS.AddComment("CPUType"); - OS.EmitIntValue(static_cast<uint64_t>(TheCPU), 2); + OS.emitInt16(static_cast<uint64_t>(TheCPU)); StringRef CompilerVersion = CU->getProducer(); Version FrontVer = parseVersion(CompilerVersion); OS.AddComment("Frontend version"); for (int N = 0; N < 4; ++N) - OS.EmitIntValue(FrontVer.Part[N], 2); + OS.emitInt16(FrontVer.Part[N]); // Some Microsoft tools, like Binscope, expect a backend version number of at // least 8.something, so we'll coerce the LLVM version into a form that @@ -797,7 +817,7 @@ void CodeViewDebug::emitCompilerInformation() { Version BackVer = {{ Major, 0, 0, 0 }}; OS.AddComment("Backend version"); for (int N = 0; N < 4; ++N) - OS.EmitIntValue(BackVer.Part[N], 2); + OS.emitInt16(BackVer.Part[N]); OS.AddComment("Null-terminated compiler version string"); emitNullTerminatedSymbolName(OS, CompilerVersion); @@ -841,7 +861,7 @@ void CodeViewDebug::emitBuildInfo() { MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols); MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO); OS.AddComment("LF_BUILDINFO index"); - OS.EmitIntValue(BuildInfoIndex.getIndex(), 4); + OS.emitInt32(BuildInfoIndex.getIndex()); endSymbolRecord(BIEnd); endCVSubsection(BISubsecEnd); } @@ -858,7 +878,7 @@ void CodeViewDebug::emitInlineeLinesSubsection() { // for instance, will display a warning that the breakpoints are not valid if // the pdb does not match the source. OS.AddComment("Inlinee lines signature"); - OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4); + OS.emitInt32(unsigned(InlineeLinesSignature::Normal)); for (const DISubprogram *SP : InlinedSubprograms) { assert(TypeIndices.count({SP, nullptr})); @@ -870,11 +890,11 @@ void CodeViewDebug::emitInlineeLinesSubsection() { SP->getFilename() + Twine(':') + Twine(SP->getLine())); OS.AddBlankLine(); OS.AddComment("Type index of inlined function"); - OS.EmitIntValue(InlineeIdx.getIndex(), 4); + OS.emitInt32(InlineeIdx.getIndex()); OS.AddComment("Offset into filechecksum table"); - OS.EmitCVFileChecksumOffsetDirective(FileId); + OS.emitCVFileChecksumOffsetDirective(FileId); OS.AddComment("Starting line number"); - OS.EmitIntValue(SP->getLine(), 4); + OS.emitInt32(SP->getLine()); } endCVSubsection(InlineEnd); @@ -890,16 +910,16 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE); OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Inlinee type index"); - OS.EmitIntValue(InlineeIdx.getIndex(), 4); + OS.emitInt32(InlineeIdx.getIndex()); unsigned FileId = maybeRecordFile(Site.Inlinee->getFile()); unsigned StartLineNum = Site.Inlinee->getLine(); - OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum, + OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum, FI.Begin, FI.End); endSymbolRecord(InlineEnd); @@ -943,7 +963,8 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) { void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, FunctionInfo &FI, const MCSymbol *Fn) { - std::string FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName()); + std::string FuncName = + std::string(GlobalValue::dropLLVMManglingEscape(GV->getName())); const ThunkOrdinal ordinal = ThunkOrdinal::Standard; // Only supported kind. OS.AddComment("Symbol subsection for " + Twine(FuncName)); @@ -952,11 +973,11 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, // Emit S_THUNK32 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32); OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrNext"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Thunk section relative address"); OS.EmitCOFFSecRel32(Fn, /*Offset=*/0); OS.AddComment("Thunk section index"); @@ -964,7 +985,7 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, OS.AddComment("Code size"); OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2); OS.AddComment("Ordinal"); - OS.EmitIntValue(unsigned(ordinal), 1); + OS.emitInt8(unsigned(ordinal)); OS.AddComment("Function name"); emitNullTerminatedSymbolName(OS, FuncName); // Additional fields specific to the thunk ordinal would go here. @@ -1006,7 +1027,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // If our DISubprogram name is empty, use the mangled name. if (FuncName.empty()) - FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName()); + FuncName = std::string(GlobalValue::dropLLVMManglingEscape(GV->getName())); // Emit FPO data, but only on 32-bit x86. No other platforms use it. if (Triple(MMI->getModule()->getTargetTriple()).getArch() == Triple::x86) @@ -1022,27 +1043,27 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // These fields are filled in by tools like CVPACK which run after the fact. OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrNext"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); // This is the important bit that tells the debugger where the function // code is located and what's its size: OS.AddComment("Code size"); OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4); OS.AddComment("Offset after prologue"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Offset before epilogue"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Function type index"); - OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4); + OS.emitInt32(getFuncIdForSubprogram(GV->getSubprogram()).getIndex()); OS.AddComment("Function section relative address"); OS.EmitCOFFSecRel32(Fn, /*Offset=*/0); OS.AddComment("Function section index"); OS.EmitCOFFSectionIndex(Fn); OS.AddComment("Flags"); - OS.EmitIntValue(0, 1); + OS.emitInt8(0); // Emit the function display name as a null-terminated string. OS.AddComment("Function name"); // Truncate the name so we won't overflow the record length field. @@ -1052,19 +1073,19 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC); // Subtract out the CSR size since MSVC excludes that and we include it. OS.AddComment("FrameSize"); - OS.EmitIntValue(FI.FrameSize - FI.CSRSize, 4); + OS.emitInt32(FI.FrameSize - FI.CSRSize); OS.AddComment("Padding"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Offset of padding"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Bytes of callee saved registers"); - OS.EmitIntValue(FI.CSRSize, 4); + OS.emitInt32(FI.CSRSize); OS.AddComment("Exception handler offset"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Exception handler section"); - OS.EmitIntValue(0, 2); + OS.emitInt16(0); OS.AddComment("Flags (defines frame register)"); - OS.EmitIntValue(uint32_t(FI.FrameProcOpts), 4); + OS.emitInt32(uint32_t(FI.FrameProcOpts)); endSymbolRecord(FrameProcEnd); emitLocalVariableList(FI, FI.Locals); @@ -1088,13 +1109,13 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.EmitCOFFSecRel32(Label, /*Offset=*/0); // FIXME: Make sure we don't overflow the max record size. OS.EmitCOFFSectionIndex(Label); - OS.EmitIntValue(Strs->getNumOperands(), 2); + OS.emitInt16(Strs->getNumOperands()); for (Metadata *MD : Strs->operands()) { // MDStrings are null terminated, so we can do EmitBytes and get the // nice .asciz directive. StringRef Str = cast<MDString>(MD)->getString(); assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString"); - OS.EmitBytes(StringRef(Str.data(), Str.size() + 1)); + OS.emitBytes(StringRef(Str.data(), Str.size() + 1)); } endSymbolRecord(AnnotEnd); } @@ -1111,7 +1132,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.AddComment("Call instruction length"); OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2); OS.AddComment("Type index"); - OS.EmitIntValue(getCompleteTypeIndex(DITy).getIndex(), 4); + OS.emitInt32(getCompleteTypeIndex(DITy).getIndex()); endSymbolRecord(HeapAllocEnd); } @@ -1124,7 +1145,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, endCVSubsection(SymbolsEnd); // We have an assembler directive that takes care of the whole line table. - OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End); + OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End); } CodeViewDebug::LocalVarDefRange @@ -1173,7 +1194,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable( } // Get the frame register used and the offset. - unsigned FrameReg = 0; + Register FrameReg; int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg); uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg); @@ -1468,12 +1489,12 @@ void CodeViewDebug::addToUDTs(const DIType *Ty) { if (!shouldEmitUdt(Ty)) return; - SmallVector<StringRef, 5> QualifiedNameComponents; + SmallVector<StringRef, 5> ParentScopeNames; const DISubprogram *ClosestSubprogram = - getQualifiedNameComponents(Ty->getScope(), QualifiedNameComponents); + collectParentScopeNames(Ty->getScope(), ParentScopeNames); std::string FullyQualifiedName = - getQualifiedName(QualifiedNameComponents, getPrettyScopeName(Ty)); + formatNestedName(ParentScopeNames, getPrettyScopeName(Ty)); if (ClosestSubprogram == nullptr) { GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty); @@ -1571,7 +1592,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { assert(Element->getTag() == dwarf::DW_TAG_subrange_type); const DISubrange *Subrange = cast<DISubrange>(Element); - assert(Subrange->getLowerBound() == 0 && + assert(!Subrange->getRawLowerBound() && "codeview doesn't support subranges with lower bounds"); int64_t Count = -1; if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>()) @@ -1767,11 +1788,12 @@ translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags) { TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty, PointerOptions PO) { assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type); + bool IsPMF = isa<DISubroutineType>(Ty->getBaseType()); TypeIndex ClassTI = getTypeIndex(Ty->getClassType()); - TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType()); + TypeIndex PointeeTI = + getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() : nullptr); PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64 : PointerKind::Near32; - bool IsPMF = isa<DISubroutineType>(Ty->getBaseType()); PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction : PointerMode::PointerToDataMember; @@ -2063,7 +2085,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { // order, which is what MSVC does. if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) { EnumeratorRecord ER(MemberAccess::Public, - APSInt::getUnsigned(Enumerator->getValue()), + APSInt(Enumerator->getValue(), true), Enumerator->getName()); ContinuationBuilder.writeMemberType(ER); EnumeratorCount++; @@ -2248,7 +2270,7 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) { // MSVC appears to set this flag by searching any destructor or method with // FunctionOptions::Constructor among the emitted members. Clang AST has all - // the members, however special member functions are not yet emitted into + // the members, however special member functions are not yet emitted into // debug information. For now checking a class's non-triviality seems enough. // FIXME: not true for a nested unnamed struct. if (isNonTrivial(Ty)) @@ -2625,9 +2647,9 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, TypeIndex TI = Var.UseReferenceType ? getTypeIndexForReferenceTo(Var.DIVar->getType()) : getCompleteTypeIndex(Var.DIVar->getType()); - OS.EmitIntValue(TI.getIndex(), 4); + OS.emitInt32(TI.getIndex()); OS.AddComment("Flags"); - OS.EmitIntValue(static_cast<uint16_t>(Flags), 2); + OS.emitInt16(static_cast<uint16_t>(Flags)); // Truncate the name so we won't overflow the record length field. emitNullTerminatedSymbolName(OS, Var.DIVar->getName()); endSymbolRecord(LocalEnd); @@ -2660,7 +2682,7 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, : (EncFP == FI.EncodedLocalFramePtrReg))) { DefRangeFramePointerRelHeader DRHdr; DRHdr.Offset = Offset; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { uint16_t RegRelFlags = 0; if (DefRange.IsSubfield) { @@ -2672,7 +2694,7 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, DRHdr.Register = Reg; DRHdr.Flags = RegRelFlags; DRHdr.BasePointerOffset = Offset; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } else { assert(DefRange.DataOffset == 0 && "unexpected offset into register"); @@ -2681,12 +2703,12 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; DRHdr.OffsetInParent = DefRange.StructOffset; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { DefRangeRegisterHeader DRHdr; DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } } @@ -2704,9 +2726,9 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block, const FunctionInfo& FI) { MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32); OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); // PtrParent + OS.emitInt32(0); // PtrParent OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); // PtrEnd + OS.emitInt32(0); // PtrEnd OS.AddComment("Code size"); OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4); // Code Size OS.AddComment("Function section relative address"); @@ -2914,17 +2936,17 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) { MCSymbol *CodeViewDebug::beginCVSubsection(DebugSubsectionKind Kind) { MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(), *EndLabel = MMI->getContext().createTempSymbol(); - OS.EmitIntValue(unsigned(Kind), 4); + OS.emitInt32(unsigned(Kind)); OS.AddComment("Subsection size"); OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4); - OS.EmitLabel(BeginLabel); + OS.emitLabel(BeginLabel); return EndLabel; } void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) { - OS.EmitLabel(EndLabel); + OS.emitLabel(EndLabel); // Every subsection must be aligned to a 4-byte boundary. - OS.EmitValueToAlignment(4); + OS.emitValueToAlignment(4); } static StringRef getSymbolName(SymbolKind SymKind) { @@ -2939,10 +2961,10 @@ MCSymbol *CodeViewDebug::beginSymbolRecord(SymbolKind SymKind) { *EndLabel = MMI->getContext().createTempSymbol(); OS.AddComment("Record length"); OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2); - OS.EmitLabel(BeginLabel); + OS.emitLabel(BeginLabel); if (OS.isVerboseAsm()) OS.AddComment("Record kind: " + getSymbolName(SymKind)); - OS.EmitIntValue(unsigned(SymKind), 2); + OS.emitInt16(unsigned(SymKind)); return EndLabel; } @@ -2951,27 +2973,31 @@ void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) { // an extra copy of every symbol record in LLD. This increases object file // size by less than 1% in the clang build, and is compatible with the Visual // C++ linker. - OS.EmitValueToAlignment(4); - OS.EmitLabel(SymEnd); + OS.emitValueToAlignment(4); + OS.emitLabel(SymEnd); } void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) { OS.AddComment("Record length"); - OS.EmitIntValue(2, 2); + OS.emitInt16(2); if (OS.isVerboseAsm()) OS.AddComment("Record kind: " + getSymbolName(EndKind)); - OS.EmitIntValue(unsigned(EndKind), 2); // Record Kind + OS.emitInt16(uint16_t(EndKind)); // Record Kind } void CodeViewDebug::emitDebugInfoForUDTs( - ArrayRef<std::pair<std::string, const DIType *>> UDTs) { + const std::vector<std::pair<std::string, const DIType *>> &UDTs) { +#ifndef NDEBUG + size_t OriginalSize = UDTs.size(); +#endif for (const auto &UDT : UDTs) { const DIType *T = UDT.second; assert(shouldEmitUdt(T)); - MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT); OS.AddComment("Type"); - OS.EmitIntValue(getCompleteTypeIndex(T).getIndex(), 4); + OS.emitInt32(getCompleteTypeIndex(T).getIndex()); + assert(OriginalSize == UDTs.size() && + "getCompleteTypeIndex found new UDTs!"); emitNullTerminatedSymbolName(OS, UDT.first); endSymbolRecord(UDTRecordEnd); } @@ -3075,6 +3101,14 @@ void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) { void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { const DIGlobalVariable *DIGV = CVGV.DIGV; + + const DIScope *Scope = DIGV->getScope(); + // For static data members, get the scope from the declaration. + if (const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>( + DIGV->getRawStaticDataMemberDeclaration())) + Scope = MemberDecl->getScope(); + std::string QualifiedName = getFullyQualifiedName(Scope, DIGV->getName()); + if (const GlobalVariable *GV = CVGV.GVInfo.dyn_cast<const GlobalVariable *>()) { // DataSym record, see SymbolRecord.h for more info. Thread local data @@ -3087,18 +3121,16 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { : SymbolKind::S_GDATA32); MCSymbol *DataEnd = beginSymbolRecord(DataSym); OS.AddComment("Type"); - OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4); + OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex()); OS.AddComment("DataOffset"); OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0); OS.AddComment("Segment"); OS.EmitCOFFSectionIndex(GVSym); OS.AddComment("Name"); const unsigned LengthOfDataRecord = 12; - emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord); + emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord); endSymbolRecord(DataEnd); } else { - // FIXME: Currently this only emits the global variables in the IR metadata. - // This should also emit enums and static data members. const DIExpression *DIE = CVGV.GVInfo.get<const DIExpression *>(); assert(DIE->isConstant() && "Global constant variables must contain a constant expression."); @@ -3106,7 +3138,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT); OS.AddComment("Type"); - OS.EmitIntValue(getTypeIndex(DIGV->getType()).getIndex(), 4); + OS.emitInt32(getTypeIndex(DIGV->getType()).getIndex()); OS.AddComment("Value"); // Encoded integers shouldn't need more than 10 bytes. @@ -3115,16 +3147,10 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { CodeViewRecordIO IO(Writer); cantFail(IO.mapEncodedInteger(Val)); StringRef SRef((char *)data, Writer.getOffset()); - OS.EmitBinaryData(SRef); + OS.emitBinaryData(SRef); OS.AddComment("Name"); - const DIScope *Scope = DIGV->getScope(); - // For static data members, get the scope from the declaration. - if (const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>( - DIGV->getRawStaticDataMemberDeclaration())) - Scope = MemberDecl->getScope(); - emitNullTerminatedSymbolName(OS, - getFullyQualifiedName(Scope, DIGV->getName())); + emitNullTerminatedSymbolName(OS, QualifiedName); endSymbolRecord(SConstantEnd); } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index b56b9047e1a9..82f0293874d0 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -310,8 +310,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { void emitDebugInfoForRetainedTypes(); - void - emitDebugInfoForUDTs(ArrayRef<std::pair<std::string, const DIType *>> UDTs); + void emitDebugInfoForUDTs( + const std::vector<std::pair<std::string, const DIType *>> &UDTs); void emitDebugInfoForGlobals(); void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals); @@ -443,6 +443,15 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex TI, const DIType *ClassTy = nullptr); + /// Collect the names of parent scopes, innermost to outermost. Return the + /// innermost subprogram scope if present. Ensure that parent type scopes are + /// inserted into the type table. + const DISubprogram * + collectParentScopeNames(const DIScope *Scope, + SmallVectorImpl<StringRef> &ParentScopeNames); + std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name); + std::string getFullyQualifiedName(const DIScope *Scope); + unsigned getPointerSizeInBytes(); protected: diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index 84b86a71fa5f..edf82fbed650 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -67,17 +67,17 @@ void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { /// void DIEAbbrev::Emit(const AsmPrinter *AP) const { // Emit its Dwarf tag type. - AP->EmitULEB128(Tag, dwarf::TagString(Tag).data()); + AP->emitULEB128(Tag, dwarf::TagString(Tag).data()); // Emit whether it has children DIEs. - AP->EmitULEB128((unsigned)Children, dwarf::ChildrenString(Children).data()); + AP->emitULEB128((unsigned)Children, dwarf::ChildrenString(Children).data()); // For each attribute description. for (unsigned i = 0, N = Data.size(); i < N; ++i) { const DIEAbbrevData &AttrData = Data[i]; // Emit attribute type. - AP->EmitULEB128(AttrData.getAttribute(), + AP->emitULEB128(AttrData.getAttribute(), dwarf::AttributeString(AttrData.getAttribute()).data()); // Emit form type. @@ -92,17 +92,17 @@ void DIEAbbrev::Emit(const AsmPrinter *AP) const { llvm_unreachable("Invalid form for specified DWARF version"); } #endif - AP->EmitULEB128(AttrData.getForm(), + AP->emitULEB128(AttrData.getForm(), dwarf::FormEncodingString(AttrData.getForm()).data()); // Emit value for DW_FORM_implicit_const. if (AttrData.getForm() == dwarf::DW_FORM_implicit_const) - AP->EmitSLEB128(AttrData.getValue()); + AP->emitSLEB128(AttrData.getValue()); } // Mark end of abbreviation. - AP->EmitULEB128(0, "EOM(1)"); - AP->EmitULEB128(0, "EOM(2)"); + AP->emitULEB128(0, "EOM(1)"); + AP->emitULEB128(0, "EOM(2)"); } LLVM_DUMP_METHOD @@ -325,13 +325,13 @@ DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag) "expected a unit TAG"); } -void DIEValue::EmitValue(const AsmPrinter *AP) const { +void DIEValue::emitValue(const AsmPrinter *AP) const { switch (Ty) { case isNone: llvm_unreachable("Expected valid DIEValue"); #define HANDLE_DIEVALUE(T) \ case is##T: \ - getDIE##T().EmitValue(AP, Form); \ + getDIE##T().emitValue(AP, Form); \ break; #include "llvm/CodeGen/DIEValue.def" } @@ -374,7 +374,7 @@ LLVM_DUMP_METHOD void DIEValue::dump() const { /// EmitValue - Emit integer of appropriate size. /// -void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { +void DIEInteger::emitValue(const AsmPrinter *Asm, dwarf::Form Form) const { switch (Form) { case dwarf::DW_FORM_implicit_const: case dwarf::DW_FORM_flag_present: @@ -409,7 +409,7 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_strp_sup: case dwarf::DW_FORM_addr: case dwarf::DW_FORM_ref_addr: - Asm->OutStreamer->EmitIntValue(Integer, SizeOf(Asm, Form)); + Asm->OutStreamer->emitIntValue(Integer, SizeOf(Asm, Form)); return; case dwarf::DW_FORM_GNU_str_index: case dwarf::DW_FORM_GNU_addr_index: @@ -418,10 +418,10 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_addrx: case dwarf::DW_FORM_rnglistx: case dwarf::DW_FORM_udata: - Asm->EmitULEB128(Integer); + Asm->emitULEB128(Integer); return; case dwarf::DW_FORM_sdata: - Asm->EmitSLEB128(Integer); + Asm->emitSLEB128(Integer); return; default: llvm_unreachable("DIE Value form not supported yet"); } @@ -465,8 +465,8 @@ void DIEInteger::print(raw_ostream &O) const { /// EmitValue - Emit expression value. /// -void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { - AP->EmitDebugValue(Expr, SizeOf(AP, Form)); +void DIEExpr::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->emitDebugValue(Expr, SizeOf(AP, Form)); } /// SizeOf - Determine size of expression value in bytes. @@ -487,12 +487,11 @@ void DIEExpr::print(raw_ostream &O) const { O << "Expr: " << *Expr; } /// EmitValue - Emit label value. /// -void DIELabel::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { - AP->EmitLabelReference(Label, SizeOf(AP, Form), - Form == dwarf::DW_FORM_strp || - Form == dwarf::DW_FORM_sec_offset || - Form == dwarf::DW_FORM_ref_addr || - Form == dwarf::DW_FORM_data4); +void DIELabel::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->emitLabelReference( + Label, SizeOf(AP, Form), + Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_sec_offset || + Form == dwarf::DW_FORM_ref_addr || Form == dwarf::DW_FORM_data4); } /// SizeOf - Determine size of label value in bytes. @@ -511,10 +510,10 @@ void DIELabel::print(raw_ostream &O) const { O << "Lbl: " << Label->getName(); } // DIEBaseTypeRef Implementation //===----------------------------------------------------------------------===// -void DIEBaseTypeRef::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { +void DIEBaseTypeRef::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { uint64_t Offset = CU->ExprRefedBaseTypes[Index].Die->getOffset(); assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); - AP->EmitULEB128(Offset, nullptr, ULEB128PadSize); + AP->emitULEB128(Offset, nullptr, ULEB128PadSize); } unsigned DIEBaseTypeRef::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { @@ -530,8 +529,8 @@ void DIEBaseTypeRef::print(raw_ostream &O) const { O << "BaseTypeRef: " << Index /// EmitValue - Emit delta value. /// -void DIEDelta::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { - AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form)); +void DIEDelta::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { + AP->emitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form)); } /// SizeOf - Determine size of delta value in bytes. @@ -554,7 +553,7 @@ void DIEDelta::print(raw_ostream &O) const { /// EmitValue - Emit string value. /// -void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { +void DIEString::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { // Index of string in symbol table. switch (Form) { case dwarf::DW_FORM_GNU_str_index: @@ -563,13 +562,13 @@ void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { case dwarf::DW_FORM_strx2: case dwarf::DW_FORM_strx3: case dwarf::DW_FORM_strx4: - DIEInteger(S.getIndex()).EmitValue(AP, Form); + DIEInteger(S.getIndex()).emitValue(AP, Form); return; case dwarf::DW_FORM_strp: if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) - DIELabel(S.getSymbol()).EmitValue(AP, Form); + DIELabel(S.getSymbol()).emitValue(AP, Form); else - DIEInteger(S.getOffset()).EmitValue(AP, Form); + DIEInteger(S.getOffset()).emitValue(AP, Form); return; default: llvm_unreachable("Expected valid string form"); @@ -605,9 +604,9 @@ void DIEString::print(raw_ostream &O) const { //===----------------------------------------------------------------------===// // DIEInlineString Implementation //===----------------------------------------------------------------------===// -void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { +void DIEInlineString::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { if (Form == dwarf::DW_FORM_string) { - AP->OutStreamer->EmitBytes(S); + AP->OutStreamer->emitBytes(S); AP->emitInt8(0); return; } @@ -630,18 +629,18 @@ void DIEInlineString::print(raw_ostream &O) const { /// EmitValue - Emit debug information entry offset. /// -void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { +void DIEEntry::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { switch (Form) { case dwarf::DW_FORM_ref1: case dwarf::DW_FORM_ref2: case dwarf::DW_FORM_ref4: case dwarf::DW_FORM_ref8: - AP->OutStreamer->EmitIntValue(Entry->getOffset(), SizeOf(AP, Form)); + AP->OutStreamer->emitIntValue(Entry->getOffset(), SizeOf(AP, Form)); return; case dwarf::DW_FORM_ref_udata: - AP->EmitULEB128(Entry->getOffset()); + AP->emitULEB128(Entry->getOffset()); return; case dwarf::DW_FORM_ref_addr: { @@ -649,11 +648,11 @@ void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { unsigned Addr = Entry->getDebugSectionOffset(); if (const MCSymbol *SectionSym = Entry->getUnit()->getCrossSectionRelativeBaseAddress()) { - AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form), true); + AP->emitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form), true); return; } - AP->OutStreamer->EmitIntValue(Addr, SizeOf(AP, Form)); + AP->OutStreamer->emitIntValue(Addr, SizeOf(AP, Form)); return; } default: @@ -711,7 +710,7 @@ unsigned DIELoc::ComputeSize(const AsmPrinter *AP) const { /// EmitValue - Emit location data. /// -void DIELoc::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { +void DIELoc::emitValue(const AsmPrinter *Asm, dwarf::Form Form) const { switch (Form) { default: llvm_unreachable("Improper form for block"); case dwarf::DW_FORM_block1: Asm->emitInt8(Size); break; @@ -719,11 +718,12 @@ void DIELoc::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_block4: Asm->emitInt32(Size); break; case dwarf::DW_FORM_block: case dwarf::DW_FORM_exprloc: - Asm->EmitULEB128(Size); break; + Asm->emitULEB128(Size); + break; } for (const auto &V : values()) - V.EmitValue(Asm); + V.emitValue(Asm); } /// SizeOf - Determine size of location data in bytes. @@ -762,19 +762,21 @@ unsigned DIEBlock::ComputeSize(const AsmPrinter *AP) const { /// EmitValue - Emit block data. /// -void DIEBlock::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { +void DIEBlock::emitValue(const AsmPrinter *Asm, dwarf::Form Form) const { switch (Form) { default: llvm_unreachable("Improper form for block"); case dwarf::DW_FORM_block1: Asm->emitInt8(Size); break; case dwarf::DW_FORM_block2: Asm->emitInt16(Size); break; case dwarf::DW_FORM_block4: Asm->emitInt32(Size); break; - case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break; + case dwarf::DW_FORM_block: + Asm->emitULEB128(Size); + break; case dwarf::DW_FORM_string: break; case dwarf::DW_FORM_data16: break; } for (const auto &V : values()) - V.EmitValue(Asm); + V.emitValue(Asm); } /// SizeOf - Determine size of block data in bytes. @@ -811,9 +813,9 @@ unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { /// EmitValue - Emit label value. /// -void DIELocList::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { +void DIELocList::emitValue(const AsmPrinter *AP, dwarf::Form Form) const { if (Form == dwarf::DW_FORM_loclistx) { - AP->EmitULEB128(Index); + AP->emitULEB128(Index); return; } DwarfDebug *DD = AP->getDwarfDebug(); diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp index bfac8850a2a6..f26ef63eedec 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -17,10 +17,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/DIE.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/MD5.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -224,8 +222,9 @@ void DIEHash::hashLocList(const DIELocList &LocList) { HashingByteStreamer Streamer(*this); DwarfDebug &DD = *AP->getDwarfDebug(); const DebugLocStream &Locs = DD.getDebugLocs(); - for (const auto &Entry : Locs.getEntries(Locs.getList(LocList.getValue()))) - DD.emitDebugLocEntry(Streamer, Entry, nullptr); + const DebugLocStream::List &List = Locs.getList(LocList.getValue()); + for (const DebugLocStream::Entry &Entry : Locs.getEntries(List)) + DD.emitDebugLocEntry(Streamer, Entry, List.CU); } // Hash an individual attribute \param Attr based on the type of attribute and @@ -361,7 +360,7 @@ void DIEHash::computeHash(const DIE &Die) { for (auto &C : Die.children()) { // 7.27 Step 7 // If C is a nested type entry or a member function entry, ... - if (isType(C.getTag()) || C.getTag() == dwarf::DW_TAG_subprogram) { + if (isType(C.getTag()) || (C.getTag() == dwarf::DW_TAG_subprogram && isType(C.getParent()->getTag()))) { StringRef Name = getDIEStringAttr(C, dwarf::DW_AT_name); // ... and has a DW_AT_name attribute if (!Name.empty()) { diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.h index 2e49514c98be..1a69f6772873 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DIEHash.h @@ -20,7 +20,6 @@ namespace llvm { class AsmPrinter; -class CompileUnit; /// An object containing the capability of hashing and adding hash /// attributes onto a DIE. diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 170fc8b6d49f..584b7614915d 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -47,7 +47,8 @@ static Register isDescribedByReg(const MachineInstr &MI) { return 0; // If location of variable is described using a register (directly or // indirectly), this register is always a first operand. - return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : Register(); + return MI.getDebugOperand(0).isReg() ? MI.getDebugOperand(0).getReg() + : Register(); } bool DbgValueHistoryMap::startDbgValue(InlinedEntity Var, diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index 22f458e4b03e..880791a06d93 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -32,9 +32,9 @@ DbgVariableLocation::extractFromMachineInstruction( DbgVariableLocation Location; if (!Instruction.isDebugValue()) return None; - if (!Instruction.getOperand(0).isReg()) + if (!Instruction.getDebugOperand(0).isReg()) return None; - Location.Register = Instruction.getOperand(0).getReg(); + Location.Register = Instruction.getDebugOperand(0).getReg(); Location.FragmentInfo.reset(); // We only handle expressions generated by DIExpression::appendOffset, // which doesn't require a full stack machine. @@ -124,21 +124,6 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) { return LabelsAfterInsn.lookup(MI); } -// Return the function-local offset of an instruction. -const MCExpr * -DebugHandlerBase::getFunctionLocalOffsetAfterInsn(const MachineInstr *MI) { - MCContext &MC = Asm->OutContext; - - MCSymbol *Start = Asm->getFunctionBegin(); - const auto *StartRef = MCSymbolRefExpr::create(Start, MC); - - MCSymbol *AfterInsn = getLabelAfterInsn(MI); - assert(AfterInsn && "Expected label after instruction"); - const auto *AfterRef = MCSymbolRefExpr::create(AfterInsn, MC); - - return MCBinaryExpr::createSub(AfterRef, StartRef, MC); -} - /// If this type is derived from a base type then return base type size. uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) { assert(Ty); @@ -215,7 +200,7 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) { continue; auto IsDescribedByReg = [](const MachineInstr *MI) { - return MI->getOperand(0).isReg() && MI->getOperand(0).getReg(); + return MI->getDebugOperand(0).isReg() && MI->getDebugOperand(0).getReg(); }; // The first mention of a function argument gets the CurrentFnBegin label, @@ -297,7 +282,7 @@ void DebugHandlerBase::beginInstruction(const MachineInstr *MI) { if (!PrevLabel) { PrevLabel = MMI->getContext().createTempSymbol(); - Asm->OutStreamer->EmitLabel(PrevLabel); + Asm->OutStreamer->emitLabel(PrevLabel); } I->second = PrevLabel; } @@ -329,7 +314,7 @@ void DebugHandlerBase::endInstruction() { // We need a label after this instruction. if (!PrevLabel) { PrevLabel = MMI->getContext().createTempSymbol(); - Asm->OutStreamer->EmitLabel(PrevLabel); + Asm->OutStreamer->emitLabel(PrevLabel); } I->second = PrevLabel; } @@ -342,3 +327,17 @@ void DebugHandlerBase::endFunction(const MachineFunction *MF) { LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); } + +void DebugHandlerBase::beginBasicBlock(const MachineBasicBlock &MBB) { + if (!MBB.isBeginSection()) + return; + + PrevLabel = MBB.getSymbol(); +} + +void DebugHandlerBase::endBasicBlock(const MachineBasicBlock &MBB) { + if (!MBB.isEndSection()) + return; + + PrevLabel = nullptr; +} diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index facbf22946e4..11ed1062f77e 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -47,8 +47,8 @@ void DwarfCFIExceptionBase::markFunctionEnd() { } void DwarfCFIExceptionBase::endFragment() { - if (shouldEmitCFI) - Asm->OutStreamer->EmitCFIEndProc(); + if (shouldEmitCFI && !Asm->MF->hasBBSections()) + Asm->OutStreamer->emitCFIEndProc(); } DwarfCFIException::DwarfCFIException(AsmPrinter *A) @@ -133,13 +133,13 @@ void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, if (!hasEmittedCFISections) { if (Asm->needsOnlyDebugCFIMoves()) - Asm->OutStreamer->EmitCFISections(false, true); + Asm->OutStreamer->emitCFISections(false, true); else if (Asm->TM.Options.ForceDwarfFrameSection) - Asm->OutStreamer->EmitCFISections(true, true); + Asm->OutStreamer->emitCFISections(true, true); hasEmittedCFISections = true; } - Asm->OutStreamer->EmitCFIStartProc(/*IsSimple=*/false); + Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); // Indicate personality routine, if any. if (!shouldEmitPersonality) @@ -157,11 +157,11 @@ void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned PerEncoding = TLOF.getPersonalityEncoding(); const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); - Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding); + Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); // Provide LSDA information. if (shouldEmitLSDA) - Asm->OutStreamer->EmitCFILsda(ESP(Asm), TLOF.getLSDAEncoding()); + Asm->OutStreamer->emitCFILsda(ESP(Asm), TLOF.getLSDAEncoding()); } /// endFunction - Gather and emit post-function exception information. @@ -172,3 +172,12 @@ void DwarfCFIException::endFunction(const MachineFunction *MF) { emitExceptionTable(); } + +void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) { + beginFragment(&MBB, getExceptionSym); +} + +void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) { + if (shouldEmitCFI) + Asm->OutStreamer->emitCFIEndProc(); +} diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index e97bcd62e8c7..296c380ae550 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -37,6 +37,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/Casting.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -113,8 +114,9 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) { // extend .file to support this. unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID(); if (!File) - return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", None, None, CUID); - return Asm->OutStreamer->EmitDwarfFileDirective( + return Asm->OutStreamer->emitDwarfFileDirective(0, "", "", None, None, + CUID); + return Asm->OutStreamer->emitDwarfFileDirective( 0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File), File->getSource(), CUID); } @@ -154,7 +156,8 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( DeclContext = GV->getScope(); // Add name and type. addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName()); - addType(*VariableDIE, GTy); + if (GTy) + addType(*VariableDIE, GTy); // Add scoping info. if (!GV->isLocalToUnit()) @@ -328,6 +331,8 @@ DIE *DwarfCompileUnit::getOrCreateCommonBlock( } void DwarfCompileUnit::addRange(RangeSpan Range) { + DD->insertSectionLabel(Range.Begin); + bool SameAsPrevCU = this == DD->getPrevCU(); DD->setPrevCU(this); // If we have no current ranges just add the range and return, otherwise, @@ -348,8 +353,6 @@ void DwarfCompileUnit::initStmtList() { if (CUNode->isDebugDirectivesOnly()) return; - // Define start line table label for each Compile Unit. - MCSymbol *LineTableStartSym; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); if (DD->useSectionsAsReferences()) { LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol(); @@ -363,13 +366,14 @@ void DwarfCompileUnit::initStmtList() { // left in the skeleton CU and so not included. // The line table entries are not always emitted in assembly, so it // is not okay to use line_table_start here. - StmtListValue = addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym, TLOF.getDwarfLineSection()->getBeginSymbol()); } void DwarfCompileUnit::applyStmtList(DIE &D) { - D.addValue(DIEValueAllocator, *StmtListValue); + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + addSectionLabel(D, dwarf::DW_AT_stmt_list, LineTableStartSym, + TLOF.getDwarfLineSection()->getBeginSymbol()); } void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, @@ -392,7 +396,14 @@ void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); - attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); + SmallVector<RangeSpan, 2> BB_List; + // If basic block sections are on, ranges for each basic block section has + // to be emitted separately. + for (const auto &R : Asm->MBBSectionRanges) + BB_List.push_back({R.second.BeginLabel, R.second.EndLabel}); + + attachRangesOrLowHighPC(*SPDie, BB_List); + if (DD->useAppleExtensionAttributes() && !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( *DD->getCurrentFunction())) @@ -400,15 +411,60 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { // Only include DW_AT_frame_base in full debug info if (!includeMinimalInlineScopes()) { - if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) { + const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); + TargetFrameLowering::DwarfFrameBase FrameBase = + TFI->getDwarfFrameBase(*Asm->MF); + switch (FrameBase.Kind) { + case TargetFrameLowering::DwarfFrameBase::Register: { + if (Register::isPhysicalRegister(FrameBase.Location.Reg)) { + MachineLocation Location(FrameBase.Location.Reg); + addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); + } + break; + } + case TargetFrameLowering::DwarfFrameBase::CFA: { DIELoc *Loc = new (DIEValueAllocator) DIELoc; addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa); addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc); - } else { - const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); - MachineLocation Location(RI->getFrameRegister(*Asm->MF)); - if (Register::isPhysicalRegister(Location.getReg())) - addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); + break; + } + case TargetFrameLowering::DwarfFrameBase::WasmFrameBase: { + // FIXME: duplicated from Target/WebAssembly/WebAssembly.h + // don't want to depend on target specific headers in this code? + const unsigned TI_GLOBAL_RELOC = 3; + if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC) { + // These need to be relocatable. + assert(FrameBase.Location.WasmLoc.Index == 0); // Only SP so far. + auto SPSym = cast<MCSymbolWasm>( + Asm->GetExternalSymbolSymbol("__stack_pointer")); + // FIXME: this repeats what WebAssemblyMCInstLower:: + // GetExternalSymbolSymbol does, since if there's no code that + // refers to this symbol, we have to set it here. + SPSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); + SPSym->setGlobalType(wasm::WasmGlobalType{ + uint8_t(Asm->getSubtargetInfo().getTargetTriple().getArch() == + Triple::wasm64 + ? wasm::WASM_TYPE_I64 + : wasm::WASM_TYPE_I32), + true}); + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_WASM_location); + addSInt(*Loc, dwarf::DW_FORM_sdata, FrameBase.Location.WasmLoc.Kind); + addLabel(*Loc, dwarf::DW_FORM_udata, SPSym); + DD->addArangeLabel(SymbolCU(this, SPSym)); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); + addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc); + } else { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); + DIExpressionCursor Cursor({}); + DwarfExpr.addWasmLocation(FrameBase.Location.WasmLoc.Kind, + FrameBase.Location.WasmLoc.Index); + DwarfExpr.addExpression(std::move(Cursor)); + addBlock(*SPDie, dwarf::DW_AT_frame_base, DwarfExpr.finalize()); + } + break; + } } } @@ -521,9 +577,33 @@ void DwarfCompileUnit::attachRangesOrLowHighPC( DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) { SmallVector<RangeSpan, 2> List; List.reserve(Ranges.size()); - for (const InsnRange &R : Ranges) - List.push_back( - {DD->getLabelBeforeInsn(R.first), DD->getLabelAfterInsn(R.second)}); + for (const InsnRange &R : Ranges) { + auto *BeginLabel = DD->getLabelBeforeInsn(R.first); + auto *EndLabel = DD->getLabelAfterInsn(R.second); + + const auto *BeginMBB = R.first->getParent(); + const auto *EndMBB = R.second->getParent(); + + const auto *MBB = BeginMBB; + // Basic block sections allows basic block subsets to be placed in unique + // sections. For each section, the begin and end label must be added to the + // list. If there is more than one range, debug ranges must be used. + // Otherwise, low/high PC can be used. + // FIXME: Debug Info Emission depends on block order and this assumes that + // the order of blocks will be frozen beyond this point. + do { + if (MBB->sameSection(EndMBB) || MBB->isEndSection()) { + auto MBBSectionRange = Asm->MBBSectionRanges[MBB->getSectionIDNum()]; + List.push_back( + {MBB->sameSection(BeginMBB) ? BeginLabel + : MBBSectionRange.BeginLabel, + MBB->sameSection(EndMBB) ? EndLabel : MBBSectionRange.EndLabel}); + } + if (MBB->sameSection(EndMBB)) + break; + MBB = MBB->getNextNode(); + } while (true); + } attachRangesOrLowHighPC(Die, std::move(List)); } @@ -654,7 +734,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, DIELoc *Loc = new (DIEValueAllocator) DIELoc; DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); for (auto &Fragment : DV.getFrameIndexExprs()) { - unsigned FrameReg = 0; + Register FrameReg; const DIExpression *Expr = Fragment.Expr; const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg); @@ -719,11 +799,22 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) { auto *Array = dyn_cast<DICompositeType>(Var->getType()); if (!Array || Array->getTag() != dwarf::DW_TAG_array_type) return Result; + if (auto *DLVar = Array->getDataLocation()) + Result.push_back(DLVar); for (auto *El : Array->getElements()) { if (auto *Subrange = dyn_cast<DISubrange>(El)) { - auto Count = Subrange->getCount(); - if (auto *Dependency = Count.dyn_cast<DIVariable *>()) - Result.push_back(Dependency); + if (auto Count = Subrange->getCount()) + if (auto *Dependency = Count.dyn_cast<DIVariable *>()) + Result.push_back(Dependency); + if (auto LB = Subrange->getLowerBound()) + if (auto *Dependency = LB.dyn_cast<DIVariable *>()) + Result.push_back(Dependency); + if (auto UB = Subrange->getUpperBound()) + if (auto *Dependency = UB.dyn_cast<DIVariable *>()) + Result.push_back(Dependency); + if (auto ST = Subrange->getStride()) + if (auto *Dependency = ST.dyn_cast<DIVariable *>()) + Result.push_back(Dependency); } } return Result; @@ -904,13 +995,12 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } -/// Whether to use the GNU analog for a DWARF5 tag, attribute, or location atom. -static bool useGNUAnalogForDwarf5Feature(DwarfDebug *DD) { +bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const { return DD->getDwarfVersion() == 4 && DD->tuneForGDB(); } dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUTag(dwarf::Tag Tag) const { - if (!useGNUAnalogForDwarf5Feature(DD)) + if (!useGNUAnalogForDwarf5Feature()) return Tag; switch (Tag) { case dwarf::DW_TAG_call_site: @@ -924,7 +1014,7 @@ dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUTag(dwarf::Tag Tag) const { dwarf::Attribute DwarfCompileUnit::getDwarf5OrGNUAttr(dwarf::Attribute Attr) const { - if (!useGNUAnalogForDwarf5Feature(DD)) + if (!useGNUAnalogForDwarf5Feature()) return Attr; switch (Attr) { case dwarf::DW_AT_call_all_calls: @@ -933,7 +1023,7 @@ DwarfCompileUnit::getDwarf5OrGNUAttr(dwarf::Attribute Attr) const { return dwarf::DW_AT_GNU_call_site_target; case dwarf::DW_AT_call_origin: return dwarf::DW_AT_abstract_origin; - case dwarf::DW_AT_call_pc: + case dwarf::DW_AT_call_return_pc: return dwarf::DW_AT_low_pc; case dwarf::DW_AT_call_value: return dwarf::DW_AT_GNU_call_site_value; @@ -946,7 +1036,7 @@ DwarfCompileUnit::getDwarf5OrGNUAttr(dwarf::Attribute Attr) const { dwarf::LocationAtom DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const { - if (!useGNUAnalogForDwarf5Feature(DD)) + if (!useGNUAnalogForDwarf5Feature()) return Loc; switch (Loc) { case dwarf::DW_OP_entry_value: @@ -956,9 +1046,12 @@ DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const { } } -DIE &DwarfCompileUnit::constructCallSiteEntryDIE( - DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail, - const MCSymbol *PCAddr, const MCExpr *PCOffset, unsigned CallReg) { +DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE, + DIE *CalleeDIE, + bool IsTail, + const MCSymbol *PCAddr, + const MCSymbol *CallAddr, + unsigned CallReg) { // Insert a call site entry DIE within ScopeDIE. DIE &CallSiteDIE = createAndAddDIE(getDwarf5OrGNUTag(dwarf::DW_TAG_call_site), ScopeDIE, nullptr); @@ -968,24 +1061,41 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE( addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target), MachineLocation(CallReg)); } else { - DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP); - assert(CalleeDIE && "Could not create DIE for call site entry origin"); + assert(CalleeDIE && "No DIE for call site entry origin"); addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin), *CalleeDIE); } - if (IsTail) + if (IsTail) { // Attach DW_AT_call_tail_call to tail calls for standards compliance. addFlag(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_tail_call)); + // Attach the address of the branch instruction to allow the debugger to + // show where the tail call occurred. This attribute has no GNU analog. + // + // GDB works backwards from non-standard usage of DW_AT_low_pc (in DWARF4 + // mode -- equivalently, in DWARF5 mode, DW_AT_call_return_pc) at tail-call + // site entries to figure out the PC of tail-calling branch instructions. + // This means it doesn't need the compiler to emit DW_AT_call_pc, so we + // don't emit it here. + // + // There's no need to tie non-GDB debuggers to this non-standardness, as it + // adds unnecessary complexity to the debugger. For non-GDB debuggers, emit + // the standard DW_AT_call_pc info. + if (!useGNUAnalogForDwarf5Feature()) + addLabelAddress(CallSiteDIE, dwarf::DW_AT_call_pc, CallAddr); + } + // Attach the return PC to allow the debugger to disambiguate call paths // from one function to another. - if (DD->getDwarfVersion() == 4 && DD->tuneForGDB()) { - assert(PCAddr && "Missing PC information for a call"); - addLabelAddress(CallSiteDIE, dwarf::DW_AT_low_pc, PCAddr); - } else if (!IsTail || DD->tuneForGDB()) { - assert(PCOffset && "Missing return PC information for a call"); - addAddressExpr(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCOffset); + // + // The return PC is only really needed when the call /isn't/ a tail call, but + // GDB expects it in DWARF4 mode, even for tail calls (see the comment above + // the DW_AT_call_pc emission logic for an explanation). + if (!IsTail || useGNUAnalogForDwarf5Feature()) { + assert(PCAddr && "Missing return PC information for a call"); + addLabelAddress(CallSiteDIE, + getDwarf5OrGNUAttr(dwarf::DW_AT_call_return_pc), PCAddr); } return CallSiteDIE; @@ -1108,7 +1218,7 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) { // Don't bother labeling the .dwo unit, as its offset isn't used. if (!Skeleton && !DD->useSectionsAsReferences()) { LabelBegin = Asm->createTempSymbol("cu_begin"); - Asm->OutStreamer->EmitLabel(LabelBegin); + Asm->OutStreamer->emitLabel(LabelBegin); } dwarf::UnitType UT = Skeleton ? dwarf::DW_UT_split_compile @@ -1219,15 +1329,12 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); const DIExpression *DIExpr = DV.getSingleExpression(); DwarfExpr.addFragmentOffset(DIExpr); - if (Location.isIndirect()) - DwarfExpr.setMemoryLocationKind(); + DwarfExpr.setLocation(Location, DIExpr); DIExpressionCursor Cursor(DIExpr); - if (DIExpr->isEntryValue()) { - DwarfExpr.setEntryValueFlag(); + if (DIExpr->isEntryValue()) DwarfExpr.beginEntryValueExpression(Cursor); - } const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) @@ -1285,12 +1392,6 @@ void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form, Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, Form, DIEExpr(Expr)); } -void DwarfCompileUnit::addAddressExpr(DIE &Die, dwarf::Attribute Attribute, - const MCExpr *Expr) { - Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, - DIEExpr(Expr)); -} - void DwarfCompileUnit::applySubprogramAttributesToDefinition( const DISubprogram *SP, DIE &SPDie) { auto *SPDecl = SP->getDeclaration(); diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 8491d078ed89..4ccd8c96dd0d 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -47,9 +47,9 @@ class DwarfCompileUnit final : public DwarfUnit { unsigned UniqueID; bool HasRangeLists = false; - /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding - /// the need to search for it in applyStmtList. - DIE::value_iterator StmtListValue; + /// The start of the unit line section, this is also + /// reused in appyStmtList. + MCSymbol *LineTableStartSym; /// Skeleton unit associated with this unit. DwarfCompileUnit *Skeleton = nullptr; @@ -123,6 +123,9 @@ public: /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. void applyStmtList(DIE &D); + /// Get line table start symbol for this unit. + MCSymbol *getLineTableStartSym() const { return LineTableStartSym; } + /// A pair of GlobalVariable and DIExpression. struct GlobalExpr { const GlobalVariable *Var; @@ -230,6 +233,10 @@ public: void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); + /// Whether to use the GNU analog for a DWARF5 tag, attribute, or location + /// atom. Only applicable when emitting otherwise DWARF4-compliant debug info. + bool useGNUAnalogForDwarf5Feature() const; + /// This takes a DWARF 5 tag and returns it or a GNU analog. dwarf::Tag getDwarf5OrGNUTag(dwarf::Tag Tag) const; @@ -240,19 +247,17 @@ public: dwarf::LocationAtom getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const; /// Construct a call site entry DIE describing a call within \p Scope to a - /// callee described by \p CalleeSP. + /// callee described by \p CalleeDIE. + /// \p CalleeDIE is a declaration or definition subprogram DIE for the callee. + /// For indirect calls \p CalleeDIE is set to nullptr. /// \p IsTail specifies whether the call is a tail call. - /// \p PCAddr (used for GDB + DWARF 4 tuning) points to the PC value after - /// the call instruction. - /// \p PCOffset (used for cases other than GDB + DWARF 4 tuning) must be - /// non-zero for non-tail calls (in the case of non-gdb tuning, since for - /// GDB + DWARF 5 tuning we still generate PC info for tail calls) or be the - /// function-local offset to PC value after the call instruction. + /// \p PCAddr points to the PC value after the call instruction. + /// \p CallAddr points to the PC value at the call instruction (or is null). /// \p CallReg is a register location for an indirect call. For direct calls /// the \p CallReg is set to 0. - DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP, - bool IsTail, const MCSymbol *PCAddr, - const MCExpr *PCOffset, unsigned CallReg); + DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, DIE *CalleeDIE, bool IsTail, + const MCSymbol *PCAddr, + const MCSymbol *CallAddr, unsigned CallReg); /// Construct call site parameter DIEs for the \p CallSiteDIE. The \p Params /// were collected by the \ref collectCallSiteParameters. /// Note: The order of parameters does not matter, since debuggers recognize @@ -340,9 +345,6 @@ public: /// Add a Dwarf expression attribute data and value. void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr); - /// Add an attribute containing an address expression to \p Die. - void addAddressExpr(DIE &Die, dwarf::Attribute Attribute, const MCExpr *Expr); - void applySubprogramAttributesToDefinition(const DISubprogram *SP, DIE &SPDie); diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 6e643ad26410..45ed5256deb9 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -95,6 +95,10 @@ static cl::opt<bool> UseDwarfRangesBaseAddressSpecifier( "use-dwarf-ranges-base-address-specifier", cl::Hidden, cl::desc("Use base address specifiers in debug_ranges"), cl::init(false)); +static cl::opt<bool> EmitDwarfDebugEntryValues( + "emit-debug-entry-values", cl::Hidden, + cl::desc("Emit the debug entry values"), cl::init(false)); + static cl::opt<bool> GenerateARangeSection("generate-arange-section", cl::Hidden, cl::desc("Generate dwarf aranges"), @@ -163,6 +167,11 @@ static cl::opt<LinkageNameOption> "Abstract subprograms")), cl::init(DefaultLinkageNames)); +static cl::opt<unsigned> LocationAnalysisSizeLimit( + "singlevarlocation-input-bb-limit", + cl::desc("Maximum block size to analyze for single-location variables"), + cl::init(30000), cl::Hidden); + static const char *const DWARFGroupName = "dwarf"; static const char *const DWARFGroupDescription = "DWARF Emission"; static const char *const DbgTimerName = "writer"; @@ -176,11 +185,11 @@ void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) { } void DebugLocDwarfExpression::emitSigned(int64_t Value) { - getActiveStreamer().EmitSLEB128(Value, Twine(Value)); + getActiveStreamer().emitSLEB128(Value, Twine(Value)); } void DebugLocDwarfExpression::emitUnsigned(uint64_t Value) { - getActiveStreamer().EmitULEB128(Value, Twine(Value)); + getActiveStreamer().emitULEB128(Value, Twine(Value)); } void DebugLocDwarfExpression::emitData1(uint8_t Value) { @@ -189,7 +198,7 @@ void DebugLocDwarfExpression::emitData1(uint8_t Value) { void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) { assert(Idx < (1ULL << (ULEB128PadSize * 7)) && "Idx wont fit"); - getActiveStreamer().EmitULEB128(Idx, Twine(Idx), ULEB128PadSize); + getActiveStreamer().emitULEB128(Idx, Twine(Idx), ULEB128PadSize); } bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, @@ -232,26 +241,26 @@ const DIType *DbgVariable::getType() const { static DbgValueLoc getDebugLocValue(const MachineInstr *MI) { const DIExpression *Expr = MI->getDebugExpression(); assert(MI->getNumOperands() == 4); - if (MI->getOperand(0).isReg()) { - auto RegOp = MI->getOperand(0); - auto Op1 = MI->getOperand(1); + if (MI->getDebugOperand(0).isReg()) { + auto RegOp = MI->getDebugOperand(0); + auto Op1 = MI->getDebugOffset(); // If the second operand is an immediate, this is a // register-indirect address. assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset"); MachineLocation MLoc(RegOp.getReg(), Op1.isImm()); return DbgValueLoc(Expr, MLoc); } - if (MI->getOperand(0).isTargetIndex()) { - auto Op = MI->getOperand(0); + if (MI->getDebugOperand(0).isTargetIndex()) { + auto Op = MI->getDebugOperand(0); return DbgValueLoc(Expr, TargetIndexLocation(Op.getIndex(), Op.getOffset())); } - if (MI->getOperand(0).isImm()) - return DbgValueLoc(Expr, MI->getOperand(0).getImm()); - if (MI->getOperand(0).isFPImm()) - return DbgValueLoc(Expr, MI->getOperand(0).getFPImm()); - if (MI->getOperand(0).isCImm()) - return DbgValueLoc(Expr, MI->getOperand(0).getCImm()); + if (MI->getDebugOperand(0).isImm()) + return DbgValueLoc(Expr, MI->getDebugOperand(0).getImm()); + if (MI->getDebugOperand(0).isFPImm()) + return DbgValueLoc(Expr, MI->getDebugOperand(0).getFPImm()); + if (MI->getDebugOperand(0).isCImm()) + return DbgValueLoc(Expr, MI->getDebugOperand(0).getCImm()); llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); } @@ -419,6 +428,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) // a monolithic string offsets table without any header. UseSegmentedStringOffsetsTable = DwarfVersion >= 5; + // Emit call-site-param debug info for GDB and LLDB, if the target supports + // the debug entry values feature. It can also be enabled explicitly. + EmitDebugEntryValues = (Asm->TM.Options.ShouldEmitDebugEntryValues() && + (tuneForGDB() || tuneForLLDB())) || + EmitDwarfDebugEntryValues; + Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); } @@ -540,11 +555,222 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, } } +DIE &DwarfDebug::constructSubprogramDefinitionDIE(const DISubprogram *SP) { + DICompileUnit *Unit = SP->getUnit(); + assert(SP->isDefinition() && "Subprogram not a definition"); + assert(Unit && "Subprogram definition without parent unit"); + auto &CU = getOrCreateDwarfCompileUnit(Unit); + return *CU.getOrCreateSubprogramDIE(SP); +} + +/// Represents a parameter whose call site value can be described by applying a +/// debug expression to a register in the forwarded register worklist. +struct FwdRegParamInfo { + /// The described parameter register. + unsigned ParamReg; + + /// Debug expression that has been built up when walking through the + /// instruction chain that produces the parameter's value. + const DIExpression *Expr; +}; + +/// Register worklist for finding call site values. +using FwdRegWorklist = MapVector<unsigned, SmallVector<FwdRegParamInfo, 2>>; + +/// Append the expression \p Addition to \p Original and return the result. +static const DIExpression *combineDIExpressions(const DIExpression *Original, + const DIExpression *Addition) { + std::vector<uint64_t> Elts = Addition->getElements().vec(); + // Avoid multiple DW_OP_stack_values. + if (Original->isImplicit() && Addition->isImplicit()) + erase_if(Elts, [](uint64_t Op) { return Op == dwarf::DW_OP_stack_value; }); + const DIExpression *CombinedExpr = + (Elts.size() > 0) ? DIExpression::append(Original, Elts) : Original; + return CombinedExpr; +} + +/// Emit call site parameter entries that are described by the given value and +/// debug expression. +template <typename ValT> +static void finishCallSiteParams(ValT Val, const DIExpression *Expr, + ArrayRef<FwdRegParamInfo> DescribedParams, + ParamSet &Params) { + for (auto Param : DescribedParams) { + bool ShouldCombineExpressions = Expr && Param.Expr->getNumElements() > 0; + + // TODO: Entry value operations can currently not be combined with any + // other expressions, so we can't emit call site entries in those cases. + if (ShouldCombineExpressions && Expr->isEntryValue()) + continue; + + // If a parameter's call site value is produced by a chain of + // instructions we may have already created an expression for the + // parameter when walking through the instructions. Append that to the + // base expression. + const DIExpression *CombinedExpr = + ShouldCombineExpressions ? combineDIExpressions(Expr, Param.Expr) + : Expr; + assert((!CombinedExpr || CombinedExpr->isValid()) && + "Combined debug expression is invalid"); + + DbgValueLoc DbgLocVal(CombinedExpr, Val); + DbgCallSiteParam CSParm(Param.ParamReg, DbgLocVal); + Params.push_back(CSParm); + ++NumCSParams; + } +} + +/// Add \p Reg to the worklist, if it's not already present, and mark that the +/// given parameter registers' values can (potentially) be described using +/// that register and an debug expression. +static void addToFwdRegWorklist(FwdRegWorklist &Worklist, unsigned Reg, + const DIExpression *Expr, + ArrayRef<FwdRegParamInfo> ParamsToAdd) { + auto I = Worklist.insert({Reg, {}}); + auto &ParamsForFwdReg = I.first->second; + for (auto Param : ParamsToAdd) { + assert(none_of(ParamsForFwdReg, + [Param](const FwdRegParamInfo &D) { + return D.ParamReg == Param.ParamReg; + }) && + "Same parameter described twice by forwarding reg"); + + // If a parameter's call site value is produced by a chain of + // instructions we may have already created an expression for the + // parameter when walking through the instructions. Append that to the + // new expression. + const DIExpression *CombinedExpr = combineDIExpressions(Expr, Param.Expr); + ParamsForFwdReg.push_back({Param.ParamReg, CombinedExpr}); + } +} + +/// Interpret values loaded into registers by \p CurMI. +static void interpretValues(const MachineInstr *CurMI, + FwdRegWorklist &ForwardedRegWorklist, + ParamSet &Params) { + + const MachineFunction *MF = CurMI->getMF(); + const DIExpression *EmptyExpr = + DIExpression::get(MF->getFunction().getContext(), {}); + const auto &TRI = *MF->getSubtarget().getRegisterInfo(); + const auto &TII = *MF->getSubtarget().getInstrInfo(); + const auto &TLI = *MF->getSubtarget().getTargetLowering(); + + // If an instruction defines more than one item in the worklist, we may run + // into situations where a worklist register's value is (potentially) + // described by the previous value of another register that is also defined + // by that instruction. + // + // This can for example occur in cases like this: + // + // $r1 = mov 123 + // $r0, $r1 = mvrr $r1, 456 + // call @foo, $r0, $r1 + // + // When describing $r1's value for the mvrr instruction, we need to make sure + // that we don't finalize an entry value for $r0, as that is dependent on the + // previous value of $r1 (123 rather than 456). + // + // In order to not have to distinguish between those cases when finalizing + // entry values, we simply postpone adding new parameter registers to the + // worklist, by first keeping them in this temporary container until the + // instruction has been handled. + FwdRegWorklist TmpWorklistItems; + + // If the MI is an instruction defining one or more parameters' forwarding + // registers, add those defines. + auto getForwardingRegsDefinedByMI = [&](const MachineInstr &MI, + SmallSetVector<unsigned, 4> &Defs) { + if (MI.isDebugInstr()) + return; + + for (const MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.isDef() && + Register::isPhysicalRegister(MO.getReg())) { + for (auto FwdReg : ForwardedRegWorklist) + if (TRI.regsOverlap(FwdReg.first, MO.getReg())) + Defs.insert(FwdReg.first); + } + } + }; + + // Set of worklist registers that are defined by this instruction. + SmallSetVector<unsigned, 4> FwdRegDefs; + + getForwardingRegsDefinedByMI(*CurMI, FwdRegDefs); + if (FwdRegDefs.empty()) + return; + + for (auto ParamFwdReg : FwdRegDefs) { + if (auto ParamValue = TII.describeLoadedValue(*CurMI, ParamFwdReg)) { + if (ParamValue->first.isImm()) { + int64_t Val = ParamValue->first.getImm(); + finishCallSiteParams(Val, ParamValue->second, + ForwardedRegWorklist[ParamFwdReg], Params); + } else if (ParamValue->first.isReg()) { + Register RegLoc = ParamValue->first.getReg(); + unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); + Register FP = TRI.getFrameRegister(*MF); + bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP); + if (TRI.isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) { + MachineLocation MLoc(RegLoc, /*IsIndirect=*/IsSPorFP); + finishCallSiteParams(MLoc, ParamValue->second, + ForwardedRegWorklist[ParamFwdReg], Params); + } else { + // ParamFwdReg was described by the non-callee saved register + // RegLoc. Mark that the call site values for the parameters are + // dependent on that register instead of ParamFwdReg. Since RegLoc + // may be a register that will be handled in this iteration, we + // postpone adding the items to the worklist, and instead keep them + // in a temporary container. + addToFwdRegWorklist(TmpWorklistItems, RegLoc, ParamValue->second, + ForwardedRegWorklist[ParamFwdReg]); + } + } + } + } + + // Remove all registers that this instruction defines from the worklist. + for (auto ParamFwdReg : FwdRegDefs) + ForwardedRegWorklist.erase(ParamFwdReg); + + // Now that we are done handling this instruction, add items from the + // temporary worklist to the real one. + for (auto New : TmpWorklistItems) + addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, New.second); + TmpWorklistItems.clear(); +} + +static bool interpretNextInstr(const MachineInstr *CurMI, + FwdRegWorklist &ForwardedRegWorklist, + ParamSet &Params) { + // Skip bundle headers. + if (CurMI->isBundle()) + return true; + + // If the next instruction is a call we can not interpret parameter's + // forwarding registers or we finished the interpretation of all + // parameters. + if (CurMI->isCall()) + return false; + + if (ForwardedRegWorklist.empty()) + return false; + + // Avoid NOP description. + if (CurMI->getNumOperands() == 0) + return true; + + interpretValues(CurMI, ForwardedRegWorklist, Params); + + return true; +} + /// Try to interpret values loaded into registers that forward parameters /// for \p CallMI. Store parameters with interpreted value into \p Params. static void collectCallSiteParameters(const MachineInstr *CallMI, ParamSet &Params) { - auto *MF = CallMI->getMF(); + const MachineFunction *MF = CallMI->getMF(); auto CalleesMap = MF->getCallSitesInfo(); auto CallFwdRegsInfo = CalleesMap.find(CallMI); @@ -552,18 +778,21 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, if (CallFwdRegsInfo == CalleesMap.end()) return; - auto *MBB = CallMI->getParent(); - const auto &TRI = MF->getSubtarget().getRegisterInfo(); - const auto &TII = MF->getSubtarget().getInstrInfo(); - const auto &TLI = MF->getSubtarget().getTargetLowering(); + const MachineBasicBlock *MBB = CallMI->getParent(); // Skip the call instruction. auto I = std::next(CallMI->getReverseIterator()); - DenseSet<unsigned> ForwardedRegWorklist; + FwdRegWorklist ForwardedRegWorklist; + + const DIExpression *EmptyExpr = + DIExpression::get(MF->getFunction().getContext(), {}); + // Add all the forwarding registers into the ForwardedRegWorklist. for (auto ArgReg : CallFwdRegsInfo->second) { - bool InsertedReg = ForwardedRegWorklist.insert(ArgReg.Reg).second; + bool InsertedReg = + ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}}) + .second; assert(InsertedReg && "Single register used to forward two arguments?"); (void)InsertedReg; } @@ -573,107 +802,29 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, // the describeLoadedValue()). For those remaining arguments in the working // list, for which we do not describe a loaded value by // the describeLoadedValue(), we try to generate an entry value expression - // for their call site value desctipion, if the call is within the entry MBB. - // The RegsForEntryValues maps a forwarding register into the register holding - // the entry value. + // for their call site value description, if the call is within the entry MBB. // TODO: Handle situations when call site parameter value can be described - // as the entry value within basic blocks other then the first one. + // as the entry value within basic blocks other than the first one. bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin(); - DenseMap<unsigned, unsigned> RegsForEntryValues; - // If the MI is an instruction defining one or more parameters' forwarding - // registers, add those defines. We can currently only describe forwarded - // registers that are explicitly defined, but keep track of implicit defines - // also to remove those registers from the work list. - auto getForwardingRegsDefinedByMI = [&](const MachineInstr &MI, - SmallVectorImpl<unsigned> &Explicit, - SmallVectorImpl<unsigned> &Implicit) { - if (MI.isDebugInstr()) + // Search for a loading value in forwarding registers inside call delay slot. + if (CallMI->hasDelaySlot()) { + auto Suc = std::next(CallMI->getIterator()); + // Only one-instruction delay slot is supported. + auto BundleEnd = llvm::getBundleEnd(CallMI->getIterator()); + (void)BundleEnd; + assert(std::next(Suc) == BundleEnd && + "More than one instruction in call delay slot"); + // Try to interpret value loaded by instruction. + if (!interpretNextInstr(&*Suc, ForwardedRegWorklist, Params)) return; - - for (const MachineOperand &MO : MI.operands()) { - if (MO.isReg() && MO.isDef() && - Register::isPhysicalRegister(MO.getReg())) { - for (auto FwdReg : ForwardedRegWorklist) { - if (TRI->regsOverlap(FwdReg, MO.getReg())) { - if (MO.isImplicit()) - Implicit.push_back(FwdReg); - else - Explicit.push_back(FwdReg); - } - } - } - } - }; - - auto finishCallSiteParam = [&](DbgValueLoc DbgLocVal, unsigned Reg) { - unsigned FwdReg = Reg; - if (ShouldTryEmitEntryVals) { - auto EntryValReg = RegsForEntryValues.find(Reg); - if (EntryValReg != RegsForEntryValues.end()) - FwdReg = EntryValReg->second; - } - - DbgCallSiteParam CSParm(FwdReg, DbgLocVal); - Params.push_back(CSParm); - ++NumCSParams; - }; + } // Search for a loading value in forwarding registers. for (; I != MBB->rend(); ++I) { - // Skip bundle headers. - if (I->isBundle()) - continue; - - // If the next instruction is a call we can not interpret parameter's - // forwarding registers or we finished the interpretation of all parameters. - if (I->isCall()) + // Try to interpret values loaded by instruction. + if (!interpretNextInstr(&*I, ForwardedRegWorklist, Params)) return; - - if (ForwardedRegWorklist.empty()) - return; - - SmallVector<unsigned, 4> ExplicitFwdRegDefs; - SmallVector<unsigned, 4> ImplicitFwdRegDefs; - getForwardingRegsDefinedByMI(*I, ExplicitFwdRegDefs, ImplicitFwdRegDefs); - if (ExplicitFwdRegDefs.empty() && ImplicitFwdRegDefs.empty()) - continue; - - // If the MI clobbers more then one forwarding register we must remove - // all of them from the working list. - for (auto Reg : concat<unsigned>(ExplicitFwdRegDefs, ImplicitFwdRegDefs)) - ForwardedRegWorklist.erase(Reg); - - for (auto ParamFwdReg : ExplicitFwdRegDefs) { - if (auto ParamValue = TII->describeLoadedValue(*I, ParamFwdReg)) { - if (ParamValue->first.isImm()) { - int64_t Val = ParamValue->first.getImm(); - DbgValueLoc DbgLocVal(ParamValue->second, Val); - finishCallSiteParam(DbgLocVal, ParamFwdReg); - } else if (ParamValue->first.isReg()) { - Register RegLoc = ParamValue->first.getReg(); - // TODO: For now, there is no use of describing the value loaded into the - // register that is also the source registers (e.g. $r0 = add $r0, x). - if (ParamFwdReg == RegLoc) - continue; - - unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); - Register FP = TRI->getFrameRegister(*MF); - bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP); - if (TRI->isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) { - DbgValueLoc DbgLocVal(ParamValue->second, - MachineLocation(RegLoc, - /*IsIndirect=*/IsSPorFP)); - finishCallSiteParam(DbgLocVal, ParamFwdReg); - // TODO: Add support for entry value plus an expression. - } else if (ShouldTryEmitEntryVals && - ParamValue->second->getNumElements() == 0) { - ForwardedRegWorklist.insert(RegLoc); - RegsForEntryValues[RegLoc] = ParamFwdReg; - } - } - } - } } // Emit the call site parameter's value as an entry value. @@ -682,15 +833,8 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, DIExpression *EntryExpr = DIExpression::get( MF->getFunction().getContext(), {dwarf::DW_OP_LLVM_entry_value, 1}); for (auto RegEntry : ForwardedRegWorklist) { - unsigned FwdReg = RegEntry; - auto EntryValReg = RegsForEntryValues.find(RegEntry); - if (EntryValReg != RegsForEntryValues.end()) - FwdReg = EntryValReg->second; - - DbgValueLoc DbgLocVal(EntryExpr, MachineLocation(RegEntry)); - DbgCallSiteParam CSParm(FwdReg, DbgLocVal); - Params.push_back(CSParm); - ++NumCSParams; + MachineLocation MLoc(RegEntry.first); + finishCallSiteParams(MLoc, EntryExpr, RegEntry.second, Params); } } } @@ -711,7 +855,25 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); assert(TII && "TargetInstrInfo not found: cannot label tail calls"); - bool ApplyGNUExtensions = getDwarfVersion() == 4 && tuneForGDB(); + + // Delay slot support check. + auto delaySlotSupported = [&](const MachineInstr &MI) { + if (!MI.isBundledWithSucc()) + return false; + auto Suc = std::next(MI.getIterator()); + auto CallInstrBundle = getBundleStart(MI.getIterator()); + (void)CallInstrBundle; + auto DelaySlotBundle = getBundleStart(Suc); + (void)DelaySlotBundle; + // Ensure that label after call is following delay slot instruction. + // Ex. CALL_INSTRUCTION { + // DELAY_SLOT_INSTRUCTION } + // LABEL_AFTER_CALL + assert(getLabelAfterInsn(&*CallInstrBundle) == + getLabelAfterInsn(&*DelaySlotBundle) && + "Call and its successor instruction don't have same label after."); + return true; + }; // Emit call site entries for each call or tail call in the function. for (const MachineBasicBlock &MBB : MF) { @@ -724,11 +886,16 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, // Skip instructions which aren't calls. Both calls and tail-calling jump // instructions (e.g TAILJMPd64) are classified correctly here. - if (!MI.isCall()) + if (!MI.isCandidateForCallSiteEntry()) continue; - // TODO: Add support for targets with delay slots (see: beginInstruction). - if (MI.hasDelaySlot()) + // Skip instructions marked as frame setup, as they are not interesting to + // the user. + if (MI.getFlag(MachineInstr::FrameSetup)) + continue; + + // Check if delay slot support is enabled. + if (MI.hasDelaySlot() && !delaySlotSupported(*&MI)) return; // If this is a direct call, find the callee's subprogram. @@ -739,7 +906,7 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, continue; unsigned CallReg = 0; - const DISubprogram *CalleeSP = nullptr; + DIE *CalleeDIE = nullptr; const Function *CalleeDecl = nullptr; if (CalleeOp.isReg()) { CallReg = CalleeOp.getReg(); @@ -749,7 +916,19 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal()); if (!CalleeDecl || !CalleeDecl->getSubprogram()) continue; - CalleeSP = CalleeDecl->getSubprogram(); + const DISubprogram *CalleeSP = CalleeDecl->getSubprogram(); + + if (CalleeSP->isDefinition()) { + // Ensure that a subprogram DIE for the callee is available in the + // appropriate CU. + CalleeDIE = &constructSubprogramDefinitionDIE(CalleeSP); + } else { + // Create the declaration DIE if it is missing. This is required to + // support compilation of old bitcode with an incomplete list of + // retained metadata. + CalleeDIE = CU.getOrCreateSubprogramDIE(CalleeSP); + } + assert(CalleeDIE && "Must have a DIE for the callee"); } // TODO: Omit call site entries for runtime calls (objc_msgSend, etc). @@ -762,25 +941,21 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, const MachineInstr *TopLevelCallMI = MI.isInsideBundle() ? &*getBundleStart(MI.getIterator()) : &MI; - // For tail calls, for non-gdb tuning, no return PC information is needed. - // For regular calls (and tail calls in GDB tuning), the return PC - // is needed to disambiguate paths in the call graph which could lead to - // some target function. - const MCExpr *PCOffset = - (IsTail && !tuneForGDB()) - ? nullptr - : getFunctionLocalOffsetAfterInsn(TopLevelCallMI); - - // Return address of a call-like instruction for a normal call or a - // jump-like instruction for a tail call. This is needed for - // GDB + DWARF 4 tuning. + // For non-tail calls, the return PC is needed to disambiguate paths in + // the call graph which could lead to some target function. For tail + // calls, no return PC information is needed, unless tuning for GDB in + // DWARF4 mode in which case we fake a return PC for compatibility. const MCSymbol *PCAddr = - ApplyGNUExtensions + (!IsTail || CU.useGNUAnalogForDwarf5Feature()) ? const_cast<MCSymbol *>(getLabelAfterInsn(TopLevelCallMI)) : nullptr; - assert((IsTail || PCOffset || PCAddr) && - "Call without return PC information"); + // For tail calls, it's necessary to record the address of the branch + // instruction so that the debugger can show where the tail call occurred. + const MCSymbol *CallAddr = + IsTail ? getLabelBeforeInsn(TopLevelCallMI) : nullptr; + + assert((IsTail || PCAddr) && "Non-tail call without return PC"); LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> " << (CalleeDecl ? CalleeDecl->getName() @@ -789,13 +964,11 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, ->getName(CallReg))) << (IsTail ? " [IsTail]" : "") << "\n"); - DIE &CallSiteDIE = - CU.constructCallSiteEntryDIE(ScopeDIE, CalleeSP, IsTail, PCAddr, - PCOffset, CallReg); + DIE &CallSiteDIE = CU.constructCallSiteEntryDIE( + ScopeDIE, CalleeDIE, IsTail, PCAddr, CallAddr, CallReg); - // GDB and LLDB support call site parameter debug info. - if (Asm->TM.Options.EnableDebugEntryValues && - (tuneForGDB() || tuneForLLDB())) { + // Optionally emit call-site-param debug info. + if (emitDebugEntryValues()) { ParamSet Params; // Try to interpret values of call site parameters. collectCallSiteParameters(&MI, Params); @@ -828,6 +1001,12 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, DIUnit->getSourceLanguage()); NewCU.addString(Die, dwarf::DW_AT_name, FN); + StringRef SysRoot = DIUnit->getSysRoot(); + if (!SysRoot.empty()) + NewCU.addString(Die, dwarf::DW_AT_LLVM_sysroot, SysRoot); + StringRef SDK = DIUnit->getSDK(); + if (!SDK.empty()) + NewCU.addString(Die, dwarf::DW_AT_APPLE_sdk, SDK); // Add DW_str_offsets_base to the unit DIE, except for split units. if (useSegmentedStringOffsetsTable() && !useSplitDwarf()) @@ -840,7 +1019,6 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, // skeleton CU and so we don't need to duplicate it here. if (!CompilationDir.empty()) NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - addGnuPubAttributes(NewCU, Die); } @@ -905,11 +1083,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); } - // Create DIEs for function declarations used for call site debug info. - for (auto Scope : DIUnit->getRetainedTypes()) - if (auto *SP = dyn_cast_or_null<DISubprogram>(Scope)) - NewCU.getOrCreateSubprogramDIE(SP); - CUMap.insert({DIUnit, &NewCU}); CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); return NewCU; @@ -1161,8 +1334,7 @@ void DwarfDebug::finalizeModuleInfo() { // We don't keep track of which addresses are used in which CU so this // is a bit pessimistic under LTO. - if ((!AddrPool.isEmpty() || TheCU.hasRangeLists()) && - (getDwarfVersion() >= 5 || HasSplitUnit)) + if ((HasSplitUnit || getDwarfVersion() >= 5) && !AddrPool.isEmpty()) U.addAddrTableBase(); if (getDwarfVersion() >= 5) { @@ -1178,18 +1350,31 @@ void DwarfDebug::finalizeModuleInfo() { } auto *CUNode = cast<DICompileUnit>(P.first); - // If compile Unit has macros, emit "DW_AT_macro_info" attribute. + // If compile Unit has macros, emit "DW_AT_macro_info/DW_AT_macros" + // attribute. if (CUNode->getMacros()) { - if (useSplitDwarf()) - TheCU.addSectionDelta(TheCU.getUnitDie(), dwarf::DW_AT_macro_info, + if (getDwarfVersion() >= 5) { + if (useSplitDwarf()) + TheCU.addSectionDelta( + TheCU.getUnitDie(), dwarf::DW_AT_macros, U.getMacroLabelBegin(), + TLOF.getDwarfMacroDWOSection()->getBeginSymbol()); + else + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macros, U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoDWOSection()->getBeginSymbol()); - else - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, - U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + TLOF.getDwarfMacroSection()->getBeginSymbol()); + } else { + if (useSplitDwarf()) + TheCU.addSectionDelta( + TheCU.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoDWOSection()->getBeginSymbol()); + else + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + } + } } - } // Emit all frontend-produced Skeleton CUs, i.e., Clang modules. for (auto *CUNode : MMI->getModule()->debug_compile_units()) @@ -1221,8 +1406,6 @@ void DwarfDebug::endModule() { // Finalize the debug info for the module. finalizeModuleInfo(); - emitDebugStr(); - if (useSplitDwarf()) // Emit debug_loc.dwo/debug_loclists.dwo section. emitDebugLocDWO(); @@ -1247,9 +1430,11 @@ void DwarfDebug::endModule() { // Emit info into a debug macinfo.dwo section. emitDebugMacinfoDWO(); else - // Emit info into a debug macinfo section. + // Emit info into a debug macinfo/macro section. emitDebugMacinfo(); + emitDebugStr(); + if (useSplitDwarf()) { emitDebugStrDWO(); emitDebugInfoDWO(); @@ -1308,6 +1493,7 @@ void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, void DwarfDebug::collectVariableInfoFromMFTable( DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) { SmallDenseMap<InlinedEntity, DbgVariable *> MFVars; + LLVM_DEBUG(dbgs() << "DwarfDebug: collecting variables from MF side table\n"); for (const auto &VI : Asm->MF->getVariableDbgInfo()) { if (!VI.Var) continue; @@ -1319,13 +1505,18 @@ void DwarfDebug::collectVariableInfoFromMFTable( LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. - if (!Scope) + if (!Scope) { + LLVM_DEBUG(dbgs() << "Dropping debug info for " << VI.Var->getName() + << ", no variable scope found\n"); continue; + } ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode()); auto RegVar = std::make_unique<DbgVariable>( cast<DILocalVariable>(Var.first), Var.second); RegVar->initializeMMI(VI.Expr, VI.Slot); + LLVM_DEBUG(dbgs() << "Created DbgVariable for " << VI.Var->getName() + << "\n"); if (DbgVariable *DbgVar = MFVars.lookup(Var)) DbgVar->addMMIEntry(*RegVar); else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) { @@ -1353,11 +1544,20 @@ static bool validThroughout(LexicalScopes &LScopes, if (LSRange.size() == 0) return false; + // Determine if the DBG_VALUE is valid at the beginning of its lexical block. const MachineInstr *LScopeBegin = LSRange.front().first; // Early exit if the lexical scope begins outside of the current block. if (LScopeBegin->getParent() != MBB) return false; + + // If there are instructions belonging to our scope in another block, and + // we're not a constant (see DWARF2 comment below), then we can't be + // validThroughout. + const MachineInstr *LScopeEnd = LSRange.back().second; + if (RangeEnd && LScopeEnd->getParent() != MBB) + return false; + MachineBasicBlock::const_reverse_iterator Pred(DbgValue); for (++Pred; Pred != MBB->rend(); ++Pred) { if (Pred->getFlag(MachineInstr::FrameSetup)) @@ -1378,19 +1578,35 @@ static bool validThroughout(LexicalScopes &LScopes, if (!RangeEnd) return true; - // Fail if there are instructions belonging to our scope in another block. - const MachineInstr *LScopeEnd = LSRange.back().second; - if (LScopeEnd->getParent() != MBB) - return false; - // Single, constant DBG_VALUEs in the prologue are promoted to be live // throughout the function. This is a hack, presumably for DWARF v2 and not // necessarily correct. It would be much better to use a dbg.declare instead // if we know the constant is live throughout the scope. - if (DbgValue->getOperand(0).isImm() && MBB->pred_empty()) + if (DbgValue->getDebugOperand(0).isImm() && MBB->pred_empty()) return true; - return false; + // Now check for situations where an "open-ended" DBG_VALUE isn't enough to + // determine eligibility for a single location, e.g. nested scopes, inlined + // functions. + // FIXME: For now we just handle a simple (but common) case where the scope + // is contained in MBB. We could be smarter here. + // + // At this point we know that our scope ends in MBB. So, if RangeEnd exists + // outside of the block we can ignore it; the location is just leaking outside + // its scope. + assert(LScopeEnd->getParent() == MBB && "Scope ends outside MBB"); + if (RangeEnd->getParent() != DbgValue->getParent()) + return true; + + // The location range and variable's enclosing scope are both contained within + // MBB, test if location terminates before end of scope. + for (auto I = RangeEnd->getIterator(); I != MBB->end(); ++I) + if (&*I == LScopeEnd) + return false; + + // There's a single location which starts at the scope start, and ends at or + // after the scope end. + return true; } /// Build the location list for all DBG_VALUEs in the function that @@ -1426,8 +1642,10 @@ static bool validThroughout(LexicalScopes &LScopes, // [1-3) [(reg0, fragment 0, 32), (reg1, fragment 32, 32)] // [3-4) [(reg1, fragment 32, 32), (123, fragment 64, 32)] // [4-) [(@g, fragment 0, 96)] -bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, - const DbgValueHistoryMap::Entries &Entries) { +bool DwarfDebug::buildLocationList( + SmallVectorImpl<DebugLocEntry> &DebugLoc, + const DbgValueHistoryMap::Entries &Entries, + DenseSet<const MachineBasicBlock *> &VeryLargeBlocks) { using OpenRange = std::pair<DbgValueHistoryMap::EntryIndex, DbgValueLoc>; SmallVector<OpenRange, 4> OpenRanges; @@ -1453,7 +1671,8 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, const MCSymbol *EndLabel; if (std::next(EI) == Entries.end()) { - EndLabel = Asm->getFunctionEnd(); + const MachineBasicBlock &EndMBB = Asm->MF->back(); + EndLabel = Asm->MBBSectionRanges[EndMBB.getSectionIDNum()].EndLabel; if (EI->isClobber()) EndMI = EI->getInstr(); } @@ -1522,8 +1741,14 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, DebugLoc.pop_back(); } - return DebugLoc.size() == 1 && isSafeForSingleLocation && - validThroughout(LScopes, StartDebugMI, EndMI); + // If there's a single entry, safe for a single location, and not part of + // an over-sized basic block, then ask validThroughout whether this + // location can be represented as a single variable location. + if (DebugLoc.size() != 1 || !isSafeForSingleLocation) + return false; + if (VeryLargeBlocks.count(StartDebugMI->getParent())) + return false; + return validThroughout(LScopes, StartDebugMI, EndMI); } DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, @@ -1555,6 +1780,13 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMFTable(TheCU, Processed); + // Identify blocks that are unreasonably sized, so that we can later + // skip lexical scope analysis over them. + DenseSet<const MachineBasicBlock *> VeryLargeBlocks; + for (const auto &MBB : *CurFn) + if (MBB.size() > LocationAnalysisSizeLimit) + VeryLargeBlocks.insert(&MBB); + for (const auto &I : DbgValues) { InlinedEntity IV = I.first; if (Processed.count(IV)) @@ -1591,7 +1823,8 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, if (HistSize == 1 || SingleValueWithClobber) { const auto *End = SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr; - if (validThroughout(LScopes, MInsn, End)) { + if (VeryLargeBlocks.count(MInsn->getParent()) == 0 && + validThroughout(LScopes, MInsn, End)) { RegVar->initializeDbgValue(MInsn); continue; } @@ -1606,7 +1839,8 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Build the location list for this variable. SmallVector<DebugLocEntry, 8> Entries; - bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries); + bool isValidSingleLocation = + buildLocationList(Entries, HistoryMapEntries, VeryLargeBlocks); // Check whether buildLocationList managed to merge all locations to one // that is valid throughout the variable's scope. If so, produce single @@ -1675,11 +1909,45 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { + const MachineFunction &MF = *MI->getMF(); + const auto *SP = MF.getFunction().getSubprogram(); + bool NoDebug = + !SP || SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug; + + // Delay slot support check. + auto delaySlotSupported = [](const MachineInstr &MI) { + if (!MI.isBundledWithSucc()) + return false; + auto Suc = std::next(MI.getIterator()); + (void)Suc; + // Ensure that delay slot instruction is successor of the call instruction. + // Ex. CALL_INSTRUCTION { + // DELAY_SLOT_INSTRUCTION } + assert(Suc->isBundledWithPred() && + "Call bundle instructions are out of order"); + return true; + }; + + // When describing calls, we need a label for the call instruction. + if (!NoDebug && SP->areAllCallsDescribed() && + MI->isCandidateForCallSiteEntry(MachineInstr::AnyInBundle) && + (!MI->hasDelaySlot() || delaySlotSupported(*MI))) { + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + bool IsTail = TII->isTailCall(*MI); + // For tail calls, we need the address of the branch instruction for + // DW_AT_call_pc. + if (IsTail) + requestLabelBeforeInsn(MI); + // For non-tail calls, we need the return address for the call for + // DW_AT_call_return_pc. Under GDB tuning, this information is needed for + // tail calls as well. + requestLabelAfterInsn(MI); + } + DebugHandlerBase::beginInstruction(MI); assert(CurMI); - const auto *SP = MI->getMF()->getFunction().getSubprogram(); - if (!SP || SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) + if (NoDebug) return; // Check if source location changes, but ignore DBG_VALUE and CFI locations. @@ -1693,11 +1961,6 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { unsigned LastAsmLine = Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine(); - // Request a label after the call in order to emit AT_return_pc information - // in call site entries. TODO: Add support for targets with delay slots. - if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot()) - requestLabelAfterInsn(MI); - if (DL == PrevInstLoc) { // If we have an ongoing unspecified location, nothing to do here. if (!DL) @@ -1796,7 +2059,7 @@ static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col, FileNo = static_cast<DwarfCompileUnit &>(*DCUs[CUID]) .getOrCreateSourceID(Scope->getFile()); } - Asm.OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0, + Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0, Discriminator, Fn); } @@ -1828,9 +2091,6 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) { if (SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) return; - SectionLabels.insert(std::make_pair(&Asm->getFunctionBegin()->getSection(), - Asm->getFunctionBegin())); - DwarfCompileUnit &CU = getOrCreateDwarfCompileUnit(SP->getUnit()); // Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function @@ -1878,7 +2138,9 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { collectEntityInfo(TheCU, SP, Processed); // Add the range of this function to the list of ranges for the CU. - TheCU.addRange({Asm->getFunctionBegin(), Asm->getFunctionEnd()}); + // With basic block sections, add ranges for all basic block sections. + for (const auto &R : Asm->MBBSectionRanges) + TheCU.addRange({R.second.BeginLabel, R.second.EndLabel}); // Under -gmlt, skip building the subprogram if there are no inlined // subroutines inside it. But with -fdebug-info-for-profiling, the subprogram @@ -2107,7 +2369,7 @@ void DwarfDebug::emitDebugPubSections() { void DwarfDebug::emitSectionReference(const DwarfCompileUnit &CU) { if (useSectionsAsReferences()) - Asm->EmitDwarfOffset(CU.getSection()->getBeginSymbol(), + Asm->emitDwarfOffset(CU.getSection()->getBeginSymbol(), CU.getDebugSectionOffset()); else Asm->emitDwarfSymbolReference(CU.getLabelBegin()); @@ -2123,9 +2385,9 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, Asm->OutStreamer->AddComment("Length of Public " + Name + " Info"); MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + Name + "_begin"); MCSymbol *EndLabel = Asm->createTempSymbol("pub" + Name + "_end"); - Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); + Asm->emitLabelDifference(EndLabel, BeginLabel, 4); - Asm->OutStreamer->EmitLabel(BeginLabel); + Asm->OutStreamer->emitLabel(BeginLabel); Asm->OutStreamer->AddComment("DWARF Version"); Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); @@ -2153,12 +2415,12 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, } Asm->OutStreamer->AddComment("External Name"); - Asm->OutStreamer->EmitBytes(StringRef(Name, GI.getKeyLength() + 1)); + Asm->OutStreamer->emitBytes(StringRef(Name, GI.getKeyLength() + 1)); } Asm->OutStreamer->AddComment("End Mark"); Asm->emitInt32(0); - Asm->OutStreamer->EmitLabel(EndLabel); + Asm->OutStreamer->emitLabel(EndLabel); } /// Emit null-terminated strings into a debug str section. @@ -2189,7 +2451,7 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, DWARFDataExtractor Data(StringRef(DebugLocs.getBytes(Entry).data(), DebugLocs.getBytes(Entry).size()), Asm->getDataLayout().isLittleEndian(), PtrSize); - DWARFExpression Expr(Data, getDwarfVersion(), PtrSize); + DWARFExpression Expr(Data, PtrSize, Asm->OutContext.getDwarfFormat()); using Encoding = DWARFExpression::Operation::Encoding; uint64_t Offset = 0; @@ -2202,18 +2464,14 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, if (Op.getDescription().Op[I] == Encoding::SizeNA) continue; if (Op.getDescription().Op[I] == Encoding::BaseTypeRef) { - if (CU) { - uint64_t Offset = CU->ExprRefedBaseTypes[Op.getRawOperand(I)].Die->getOffset(); - assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); - Asm->EmitULEB128(Offset, nullptr, ULEB128PadSize); - } else { - // Emit a reference to the 'generic type'. - Asm->EmitULEB128(0, nullptr, ULEB128PadSize); - } - // Make sure comments stay aligned. - for (unsigned J = 0; J < ULEB128PadSize; ++J) - if (Comment != End) - Comment++; + uint64_t Offset = + CU->ExprRefedBaseTypes[Op.getRawOperand(I)].Die->getOffset(); + assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); + Streamer.emitULEB128(Offset, "", ULEB128PadSize); + // Make sure comments stay aligned. + for (unsigned J = 0; J < ULEB128PadSize; ++J) + if (Comment != End) + Comment++; } else { for (uint64_t J = Offset; J < Op.getOperandEndOffset(I); ++J) Streamer.EmitInt8(Data.getData()[J], Comment != End ? *(Comment++) : ""); @@ -2239,14 +2497,11 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, DwarfExpr.addUnsignedConstant(Value.getInt()); } else if (Value.isLocation()) { MachineLocation Location = Value.getLoc(); - if (Location.isIndirect()) - DwarfExpr.setMemoryLocationKind(); + DwarfExpr.setLocation(Location, DIExpr); DIExpressionCursor Cursor(DIExpr); - if (DIExpr->isEntryValue()) { - DwarfExpr.setEntryValueFlag(); + if (DIExpr->isEntryValue()) DwarfExpr.beginEntryValueExpression(Cursor); - } const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) @@ -2256,7 +2511,7 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, TargetIndexLocation Loc = Value.getTargetIndexLocation(); // TODO TargetIndexLocation is a target-independent. Currently only the WebAssembly-specific // encoding is supported. - DwarfExpr.addWasmLocation(Loc.Index, Loc.Offset); + DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset)); } else if (Value.isConstantFP()) { APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt(); DwarfExpr.addUnsignedConstant(RawBytes); @@ -2280,8 +2535,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, assert(llvm::all_of(Values, [](DbgValueLoc P) { return P.isFragment(); }) && "all values are expected to be fragments"); - assert(std::is_sorted(Values.begin(), Values.end()) && - "fragments are expected to be sorted"); + assert(llvm::is_sorted(Values) && "fragments are expected to be sorted"); for (auto Fragment : Values) DwarfDebug::emitDebugLocValue(AP, BT, Fragment, DwarfExpr); @@ -2300,7 +2554,7 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, // Emit the size. Asm->OutStreamer->AddComment("Loc expr size"); if (getDwarfVersion() >= 5) - Asm->EmitULEB128(DebugLocs.getBytes(Entry).size()); + Asm->emitULEB128(DebugLocs.getBytes(Entry).size()); else if (DebugLocs.getBytes(Entry).size() <= std::numeric_limits<uint16_t>::max()) Asm->emitInt16(DebugLocs.getBytes(Entry).size()); else { @@ -2314,41 +2568,19 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, emitDebugLocEntry(Streamer, Entry, CU); } -// Emit the common part of the DWARF 5 range/locations list tables header. -static void emitListsTableHeaderStart(AsmPrinter *Asm, - MCSymbol *TableStart, - MCSymbol *TableEnd) { - // Build the table header, which starts with the length field. - Asm->OutStreamer->AddComment("Length"); - Asm->EmitLabelDifference(TableEnd, TableStart, 4); - Asm->OutStreamer->EmitLabel(TableStart); - // Version number (DWARF v5 and later). - Asm->OutStreamer->AddComment("Version"); - Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); - // Address size. - Asm->OutStreamer->AddComment("Address size"); - Asm->emitInt8(Asm->MAI->getCodePointerSize()); - // Segment selector size. - Asm->OutStreamer->AddComment("Segment selector size"); - Asm->emitInt8(0); -} - // Emit the header of a DWARF 5 range list table list table. Returns the symbol // that designates the end of the table for the caller to emit when the table is // complete. static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, const DwarfFile &Holder) { - MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); - MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); - emitListsTableHeaderStart(Asm, TableStart, TableEnd); + MCSymbol *TableEnd = mcdwarf::emitListsTableHeaderStart(*Asm->OutStreamer); Asm->OutStreamer->AddComment("Offset entry count"); Asm->emitInt32(Holder.getRangeLists().size()); - Asm->OutStreamer->EmitLabel(Holder.getRnglistsTableBaseSym()); + Asm->OutStreamer->emitLabel(Holder.getRnglistsTableBaseSym()); for (const RangeSpanList &List : Holder.getRangeLists()) - Asm->EmitLabelDifference(List.Label, Holder.getRnglistsTableBaseSym(), - 4); + Asm->emitLabelDifference(List.Label, Holder.getRnglistsTableBaseSym(), 4); return TableEnd; } @@ -2358,18 +2590,16 @@ static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, // complete. static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm, const DwarfDebug &DD) { - MCSymbol *TableStart = Asm->createTempSymbol("debug_loclist_table_start"); - MCSymbol *TableEnd = Asm->createTempSymbol("debug_loclist_table_end"); - emitListsTableHeaderStart(Asm, TableStart, TableEnd); + MCSymbol *TableEnd = mcdwarf::emitListsTableHeaderStart(*Asm->OutStreamer); const auto &DebugLocs = DD.getDebugLocs(); Asm->OutStreamer->AddComment("Offset entry count"); Asm->emitInt32(DebugLocs.getLists().size()); - Asm->OutStreamer->EmitLabel(DebugLocs.getSym()); + Asm->OutStreamer->emitLabel(DebugLocs.getSym()); for (const auto &List : DebugLocs.getLists()) - Asm->EmitLabelDifference(List.Label, DebugLocs.getSym(), 4); + Asm->emitLabelDifference(List.Label, DebugLocs.getSym(), 4); return TableEnd; } @@ -2387,7 +2617,7 @@ static void emitRangeList( bool UseDwarf5 = DD.getDwarfVersion() >= 5; // Emit our symbol so we can find the beginning of the range. - Asm->OutStreamer->EmitLabel(Sym); + Asm->OutStreamer->emitLabel(Sym); // Gather all the ranges that apply to the same section so they can share // a base address entry. @@ -2406,9 +2636,9 @@ static void emitRangeList( if (!UseDwarf5) { Base = NewBase; BaseIsSet = true; - Asm->OutStreamer->EmitIntValue(-1, Size); + Asm->OutStreamer->emitIntValue(-1, Size); Asm->OutStreamer->AddComment(" base address"); - Asm->OutStreamer->EmitSymbolValue(Base, Size); + Asm->OutStreamer->emitSymbolValue(Base, Size); } else if (NewBase != Begin || P.second.size() > 1) { // Only use a base address if // * the existing pool address doesn't match (NewBase != Begin) @@ -2418,13 +2648,13 @@ static void emitRangeList( Asm->OutStreamer->AddComment(StringifyEnum(BaseAddressx)); Asm->emitInt8(BaseAddressx); Asm->OutStreamer->AddComment(" base address index"); - Asm->EmitULEB128(DD.getAddressPool().getIndex(Base)); + Asm->emitULEB128(DD.getAddressPool().getIndex(Base)); } } else if (BaseIsSet && !UseDwarf5) { BaseIsSet = false; assert(!Base); - Asm->OutStreamer->EmitIntValue(-1, Size); - Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->emitIntValue(-1, Size); + Asm->OutStreamer->emitIntValue(0, Size); } for (const auto *RS : P.second) { @@ -2438,23 +2668,23 @@ static void emitRangeList( Asm->OutStreamer->AddComment(StringifyEnum(OffsetPair)); Asm->emitInt8(OffsetPair); Asm->OutStreamer->AddComment(" starting offset"); - Asm->EmitLabelDifferenceAsULEB128(Begin, Base); + Asm->emitLabelDifferenceAsULEB128(Begin, Base); Asm->OutStreamer->AddComment(" ending offset"); - Asm->EmitLabelDifferenceAsULEB128(End, Base); + Asm->emitLabelDifferenceAsULEB128(End, Base); } else { - Asm->EmitLabelDifference(Begin, Base, Size); - Asm->EmitLabelDifference(End, Base, Size); + Asm->emitLabelDifference(Begin, Base, Size); + Asm->emitLabelDifference(End, Base, Size); } } else if (UseDwarf5) { Asm->OutStreamer->AddComment(StringifyEnum(StartxLength)); Asm->emitInt8(StartxLength); Asm->OutStreamer->AddComment(" start index"); - Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin)); + Asm->emitULEB128(DD.getAddressPool().getIndex(Begin)); Asm->OutStreamer->AddComment(" length"); - Asm->EmitLabelDifferenceAsULEB128(End, Begin); + Asm->emitLabelDifferenceAsULEB128(End, Begin); } else { - Asm->OutStreamer->EmitSymbolValue(Begin, Size); - Asm->OutStreamer->EmitSymbolValue(End, Size); + Asm->OutStreamer->emitSymbolValue(Begin, Size); + Asm->OutStreamer->emitSymbolValue(End, Size); } EmitPayload(*RS); } @@ -2465,8 +2695,8 @@ static void emitRangeList( Asm->emitInt8(EndOfList); } else { // Terminate the list with two 0 values. - Asm->OutStreamer->EmitIntValue(0, Size); - Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->emitIntValue(0, Size); + Asm->OutStreamer->emitIntValue(0, Size); } } @@ -2496,7 +2726,7 @@ void DwarfDebug::emitDebugLocImpl(MCSection *Sec) { emitLocList(*this, Asm, List); if (TableEnd) - Asm->OutStreamer->EmitLabel(TableEnd); + Asm->OutStreamer->emitLabel(TableEnd); } // Emit locations into the .debug_loc/.debug_loclists section. @@ -2519,7 +2749,7 @@ void DwarfDebug::emitDebugLocDWO() { for (const auto &List : DebugLocs.getLists()) { Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfLocDWOSection()); - Asm->OutStreamer->EmitLabel(List.Label); + Asm->OutStreamer->emitLabel(List.Label); for (const auto &Entry : DebugLocs.getEntries(List)) { // GDB only supports startx_length in pre-standard split-DWARF. @@ -2527,14 +2757,15 @@ void DwarfDebug::emitDebugLocDWO() { // offset_pair, so the implementations can't really share much since they // need to use different representations) // * as of October 2018, at least - // Ideally/in v5, this could use SectionLabels to reuse existing addresses - // in the address pool to minimize object size/relocations. + // + // In v5 (see emitLocList), this uses SectionLabels to reuse existing + // addresses in the address pool to minimize object size/relocations. Asm->emitInt8(dwarf::DW_LLE_startx_length); unsigned idx = AddrPool.getIndex(Entry.Begin); - Asm->EmitULEB128(idx); + Asm->emitULEB128(idx); // Also the pre-standard encoding is slightly different, emitting this as // an address-length entry here, but its a ULEB128 in DWARFv5 loclists. - Asm->EmitLabelDifference(Entry.End, Entry.Begin, 4); + Asm->emitLabelDifference(Entry.End, Entry.Begin, 4); emitDebugLocEntryLocation(Entry, List.CU); } Asm->emitInt8(dwarf::DW_LLE_end_of_list); @@ -2679,11 +2910,11 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer->emitFill(Padding, 0xff); for (const ArangeSpan &Span : List) { - Asm->EmitLabelReference(Span.Start, PtrSize); + Asm->emitLabelReference(Span.Start, PtrSize); // Calculate the size as being from the span start to it's end. if (Span.End) { - Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize); + Asm->emitLabelDifference(Span.End, Span.Start, PtrSize); } else { // For symbols without an end marker (e.g. common), we // write a single arange entry containing just that one symbol. @@ -2691,13 +2922,13 @@ void DwarfDebug::emitDebugARanges() { if (Size == 0) Size = 1; - Asm->OutStreamer->EmitIntValue(Size, PtrSize); + Asm->OutStreamer->emitIntValue(Size, PtrSize); } } Asm->OutStreamer->AddComment("ARange terminator"); - Asm->OutStreamer->EmitIntValue(0, PtrSize); - Asm->OutStreamer->EmitIntValue(0, PtrSize); + Asm->OutStreamer->emitIntValue(0, PtrSize); + Asm->OutStreamer->emitIntValue(0, PtrSize); } } @@ -2733,7 +2964,7 @@ void DwarfDebug::emitDebugRangesImpl(const DwarfFile &Holder, MCSection *Section emitRangeList(*this, Asm, List); if (TableEnd) - Asm->OutStreamer->EmitLabel(TableEnd); + Asm->OutStreamer->emitLabel(TableEnd); } /// Emit address ranges into the .debug_ranges section or into the DWARF v5 @@ -2752,6 +2983,27 @@ void DwarfDebug::emitDebugRangesDWO() { Asm->getObjFileLowering().getDwarfRnglistsDWOSection()); } +/// Emit the header of a DWARF 5 macro section. +static void emitMacroHeader(AsmPrinter *Asm, const DwarfDebug &DD, + const DwarfCompileUnit &CU) { + enum HeaderFlagMask { +#define HANDLE_MACRO_FLAG(ID, NAME) MACRO_FLAG_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" + }; + uint8_t Flags = 0; + Asm->OutStreamer->AddComment("Macro information version"); + Asm->emitInt16(5); + // We are setting Offset and line offset flags unconditionally here, + // since we're only supporting DWARF32 and line offset should be mostly + // present. + // FIXME: Add support for DWARF64. + Flags |= MACRO_FLAG_DEBUG_LINE_OFFSET; + Asm->OutStreamer->AddComment("Flags: 32 bit, debug_line_offset present"); + Asm->emitInt8(Flags); + Asm->OutStreamer->AddComment("debug_line_offset"); + Asm->OutStreamer->emitSymbolValue(CU.getLineTableStartSym(), /*Size=*/4); +} + void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { for (auto *MN : Nodes) { if (auto *M = dyn_cast<DIMacro>(MN)) @@ -2764,26 +3016,72 @@ void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { } void DwarfDebug::emitMacro(DIMacro &M) { - Asm->EmitULEB128(M.getMacinfoType()); - Asm->EmitULEB128(M.getLine()); StringRef Name = M.getName(); StringRef Value = M.getValue(); - Asm->OutStreamer->EmitBytes(Name); - if (!Value.empty()) { - // There should be one space between macro name and macro value. - Asm->emitInt8(' '); - Asm->OutStreamer->EmitBytes(Value); + bool UseMacro = getDwarfVersion() >= 5; + + if (UseMacro) { + unsigned Type = M.getMacinfoType() == dwarf::DW_MACINFO_define + ? dwarf::DW_MACRO_define_strx + : dwarf::DW_MACRO_undef_strx; + Asm->OutStreamer->AddComment(dwarf::MacroString(Type)); + Asm->emitULEB128(Type); + Asm->OutStreamer->AddComment("Line Number"); + Asm->emitULEB128(M.getLine()); + Asm->OutStreamer->AddComment("Macro String"); + if (!Value.empty()) + Asm->emitULEB128(this->InfoHolder.getStringPool() + .getIndexedEntry(*Asm, (Name + " " + Value).str()) + .getIndex()); + else + // DW_MACRO_undef_strx doesn't have a value, so just emit the macro + // string. + Asm->emitULEB128(this->InfoHolder.getStringPool() + .getIndexedEntry(*Asm, (Name).str()) + .getIndex()); + } else { + Asm->OutStreamer->AddComment(dwarf::MacinfoString(M.getMacinfoType())); + Asm->emitULEB128(M.getMacinfoType()); + Asm->OutStreamer->AddComment("Line Number"); + Asm->emitULEB128(M.getLine()); + Asm->OutStreamer->AddComment("Macro String"); + Asm->OutStreamer->emitBytes(Name); + if (!Value.empty()) { + // There should be one space between macro name and macro value. + Asm->emitInt8(' '); + Asm->OutStreamer->AddComment("Macro Value="); + Asm->OutStreamer->emitBytes(Value); + } + Asm->emitInt8('\0'); } - Asm->emitInt8('\0'); +} + +void DwarfDebug::emitMacroFileImpl( + DIMacroFile &F, DwarfCompileUnit &U, unsigned StartFile, unsigned EndFile, + StringRef (*MacroFormToString)(unsigned Form)) { + + Asm->OutStreamer->AddComment(MacroFormToString(StartFile)); + Asm->emitULEB128(StartFile); + Asm->OutStreamer->AddComment("Line Number"); + Asm->emitULEB128(F.getLine()); + Asm->OutStreamer->AddComment("File Number"); + Asm->emitULEB128(U.getOrCreateSourceID(F.getFile())); + handleMacroNodes(F.getElements(), U); + Asm->OutStreamer->AddComment(MacroFormToString(EndFile)); + Asm->emitULEB128(EndFile); } void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) { + // DWARFv5 macro and DWARFv4 macinfo share some common encodings, + // so for readibility/uniformity, We are explicitly emitting those. assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); - Asm->EmitULEB128(dwarf::DW_MACINFO_start_file); - Asm->EmitULEB128(F.getLine()); - Asm->EmitULEB128(U.getOrCreateSourceID(F.getFile())); - handleMacroNodes(F.getElements(), U); - Asm->EmitULEB128(dwarf::DW_MACINFO_end_file); + bool UseMacro = getDwarfVersion() >= 5; + if (UseMacro) + emitMacroFileImpl(F, U, dwarf::DW_MACRO_start_file, + dwarf::DW_MACRO_end_file, dwarf::MacroString); + else + emitMacroFileImpl(F, U, dwarf::DW_MACINFO_start_file, + dwarf::DW_MACINFO_end_file, dwarf::MacinfoString); } void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) { @@ -2796,20 +3094,28 @@ void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) { if (Macros.empty()) continue; Asm->OutStreamer->SwitchSection(Section); - Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); + Asm->OutStreamer->emitLabel(U.getMacroLabelBegin()); + if (getDwarfVersion() >= 5) + emitMacroHeader(Asm, *this, U); handleMacroNodes(Macros, U); Asm->OutStreamer->AddComment("End Of Macro List Mark"); Asm->emitInt8(0); } } -/// Emit macros into a debug macinfo section. +/// Emit macros into a debug macinfo/macro section. void DwarfDebug::emitDebugMacinfo() { - emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoSection()); + auto &ObjLower = Asm->getObjFileLowering(); + emitDebugMacinfoImpl(getDwarfVersion() >= 5 + ? ObjLower.getDwarfMacroSection() + : ObjLower.getDwarfMacinfoSection()); } void DwarfDebug::emitDebugMacinfoDWO() { - emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoDWOSection()); + auto &ObjLower = Asm->getObjFileLowering(); + emitDebugMacinfoImpl(getDwarfVersion() >= 5 + ? ObjLower.getDwarfMacroDWOSection() + : ObjLower.getDwarfMacinfoDWOSection()); } // DWARF5 Experimental Separate Dwarf emitters. @@ -2819,7 +3125,6 @@ void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, if (!CompilationDir.empty()) NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - addGnuPubAttributes(*NewU, Die); SkeletonHolder.addUnit(std::move(NewU)); @@ -3073,3 +3378,8 @@ uint16_t DwarfDebug::getDwarfVersion() const { const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) { return SectionLabels.find(S)->second; } +void DwarfDebug::insertSectionLabel(const MCSymbol *S) { + if (SectionLabels.insert(std::make_pair(&S->getSection(), S)).second) + if (useSplitDwarf() || getDwarfVersion() >= 5) + AddrPool.getIndex(S); +} diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index f90dd48458ea..ad2f2f3edd8e 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -49,7 +49,6 @@ namespace llvm { class AsmPrinter; class ByteStreamer; -class DebugLocEntry; class DIE; class DwarfCompileUnit; class DwarfExpression; @@ -59,7 +58,6 @@ class LexicalScope; class MachineFunction; class MCSection; class MCSymbol; -class MDNode; class Module; //===----------------------------------------------------------------------===// @@ -327,7 +325,7 @@ class DwarfDebug : public DebugHandlerBase { const MachineFunction *CurFn = nullptr; /// If nonnull, stores the CU in which the previous subprogram was contained. - const DwarfCompileUnit *PrevCU; + const DwarfCompileUnit *PrevCU = nullptr; /// As an optimization, there is no need to emit an entry in the directory /// table for the same directory as DW_AT_comp_dir. @@ -386,6 +384,11 @@ class DwarfDebug : public DebugHandlerBase { /// a monolithic sequence of string offsets. bool UseSegmentedStringOffsetsTable; + /// Enable production of call site parameters needed to print the debug entry + /// values. Useful for testing purposes when a debugger does not support the + /// feature yet. + bool EmitDebugEntryValues; + /// Separated Dwarf Variables /// In general these will all be for bits that are left in the /// original object file, rather than things that are meant @@ -442,6 +445,9 @@ class DwarfDebug : public DebugHandlerBase { /// Construct a DIE for this abstract scope. void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope); + /// Construct a DIE for the subprogram definition \p SP and return it. + DIE &constructSubprogramDefinitionDIE(const DISubprogram *SP); + /// Construct DIEs for call site entries describing the calls in \p MF. void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU, DIE &ScopeDIE, const MachineFunction &MF); @@ -520,6 +526,9 @@ class DwarfDebug : public DebugHandlerBase { void emitDebugMacinfoImpl(MCSection *Section); void emitMacro(DIMacro &M); void emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U); + void emitMacroFileImpl(DIMacroFile &F, DwarfCompileUnit &U, + unsigned StartFile, unsigned EndFile, + StringRef (*MacroFormToString)(unsigned Form)); void handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U); /// DWARF 5 Experimental Split Dwarf Emitters @@ -583,8 +592,10 @@ class DwarfDebug : public DebugHandlerBase { /// function that describe the same variable. If the resulting /// list has only one entry that is valid for entire variable's /// scope return true. - bool buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, - const DbgValueHistoryMap::Entries &Entries); + bool buildLocationList( + SmallVectorImpl<DebugLocEntry> &DebugLoc, + const DbgValueHistoryMap::Entries &Entries, + DenseSet<const MachineBasicBlock *> &VeryLargeBlocks); /// Collect variable information from the side table maintained by MF. void collectVariableInfoFromMFTable(DwarfCompileUnit &TheCU, @@ -631,7 +642,6 @@ public: void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, DIE &Die, const DICompositeType *CTy); - friend class NonTypeUnitContext; class NonTypeUnitContext { DwarfDebug *DD; decltype(DwarfDebug::TypeUnitsUnderConstruction) TypeUnitsUnderConstruction; @@ -705,6 +715,10 @@ public: return UseSegmentedStringOffsetsTable; } + bool emitDebugEntryValues() const { + return EmitDebugEntryValues; + } + bool shareAcrossDWOCUs() const; /// Returns the Dwarf Version. @@ -765,6 +779,7 @@ public: void addSectionLabel(const MCSymbol *Sym); const MCSymbol *getSectionLabel(const MCSection *S); + void insertSectionLabel(const MCSymbol *S); static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, const DbgValueLoc &Value, diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfException.h index 24bbf58b91ec..c2956380438f 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -66,6 +66,9 @@ public: void beginFragment(const MachineBasicBlock *MBB, ExceptionSymbolProvider ESP) override; + + void beginBasicBlock(const MachineBasicBlock &MBB) override; + void endBasicBlock(const MachineBasicBlock &MBB) override; }; class LLVM_LIBRARY_VISIBILITY ARMException : public DwarfCFIExceptionBase { diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 310647f15a5e..d4762121d105 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -40,12 +40,12 @@ void DwarfExpression::emitConstu(uint64_t Value) { } void DwarfExpression::addReg(int DwarfReg, const char *Comment) { - assert(DwarfReg >= 0 && "invalid negative dwarf register number"); - assert((isUnknownLocation() || isRegisterLocation()) && - "location description already locked down"); - LocationKind = Register; - if (DwarfReg < 32) { - emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment); + assert(DwarfReg >= 0 && "invalid negative dwarf register number"); + assert((isUnknownLocation() || isRegisterLocation()) && + "location description already locked down"); + LocationKind = Register; + if (DwarfReg < 32) { + emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment); } else { emitOp(dwarf::DW_OP_regx, Comment); emitUnsigned(DwarfReg); @@ -100,7 +100,7 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg, unsigned MaxSize) { if (!llvm::Register::isPhysicalRegister(MachineReg)) { if (isFrameRegister(TRI, MachineReg)) { - DwarfRegs.push_back({-1, 0, nullptr}); + DwarfRegs.push_back(Register::createRegister(-1, nullptr)); return true; } return false; @@ -110,7 +110,7 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, // If this is a valid register number, emit it. if (Reg >= 0) { - DwarfRegs.push_back({Reg, 0, nullptr}); + DwarfRegs.push_back(Register::createRegister(Reg, nullptr)); return true; } @@ -122,7 +122,7 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg); unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); - DwarfRegs.push_back({Reg, 0, "super-register"}); + DwarfRegs.push_back(Register::createRegister(Reg, "super-register")); // Use a DW_OP_bit_piece to describe the sub-register. setSubRegisterPiece(Size, RegOffset); return true; @@ -149,8 +149,8 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, if (Reg < 0) continue; - // Intersection between the bits we already emitted and the bits - // covered by this subregister. + // Used to build the intersection between the bits we already + // emitted and the bits covered by this subregister. SmallBitVector CurSubReg(RegSize, false); CurSubReg.set(Offset, Offset + Size); @@ -159,10 +159,13 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, if (Offset < MaxSize && CurSubReg.test(Coverage)) { // Emit a piece for any gap in the coverage. if (Offset > CurPos) - DwarfRegs.push_back( - {-1, Offset - CurPos, "no DWARF register encoding"}); - DwarfRegs.push_back( - {Reg, std::min<unsigned>(Size, MaxSize - Offset), "sub-register"}); + DwarfRegs.push_back(Register::createSubRegister( + -1, Offset - CurPos, "no DWARF register encoding")); + if (Offset == 0 && Size >= MaxSize) + DwarfRegs.push_back(Register::createRegister(Reg, "sub-register")); + else + DwarfRegs.push_back(Register::createSubRegister( + Reg, std::min<unsigned>(Size, MaxSize - Offset), "sub-register")); } // Mark it as emitted. Coverage.set(Offset, Offset + Size); @@ -173,7 +176,8 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, return false; // Found a partial or complete DWARF encoding. if (CurPos < RegSize) - DwarfRegs.push_back({-1, RegSize - CurPos, "no DWARF register encoding"}); + DwarfRegs.push_back(Register::createSubRegister( + -1, RegSize - CurPos, "no DWARF register encoding")); return true; } @@ -233,8 +237,17 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, // If the register can only be described by a complex expression (i.e., // multiple subregisters) it doesn't safely compose with another complex // expression. For example, it is not possible to apply a DW_OP_deref - // operation to multiple DW_OP_pieces. - if (HasComplexExpression && DwarfRegs.size() > 1) { + // operation to multiple DW_OP_pieces, since composite location descriptions + // do not push anything on the DWARF stack. + // + // DW_OP_entry_value operations can only hold a DWARF expression or a + // register location description, so we can't emit a single entry value + // covering a composite location description. In the future we may want to + // emit entry value operations for each register location in the composite + // location, but until that is supported do not emit anything. + if ((HasComplexExpression || IsEmittingEntryValue) && DwarfRegs.size() > 1) { + if (IsEmittingEntryValue) + cancelEntryValue(); DwarfRegs.clear(); LocationKind = Unknown; return false; @@ -244,18 +257,19 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, // a call site parameter expression and if that expression is just a register // location, emit it with addBReg and offset 0, because we should emit a DWARF // expression representing a value, rather than a location. - if (!isMemoryLocation() && !HasComplexExpression && (!isParameterValue() || - isEntryValue())) { + if (!isMemoryLocation() && !HasComplexExpression && + (!isParameterValue() || isEntryValue())) { for (auto &Reg : DwarfRegs) { if (Reg.DwarfRegNo >= 0) addReg(Reg.DwarfRegNo, Reg.Comment); - addOpPiece(Reg.Size); + addOpPiece(Reg.SubRegSize); } if (isEntryValue()) finalizeEntryValue(); - if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4) + if (isEntryValue() && !isIndirect() && !isParameterValue() && + DwarfVersion >= 4) emitOp(dwarf::DW_OP_stack_value); DwarfRegs.clear(); @@ -276,7 +290,7 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, auto Reg = DwarfRegs[0]; bool FBReg = isFrameRegister(TRI, MachineReg); int SignedOffset = 0; - assert(Reg.Size == 0 && "subregister has same size as superregister"); + assert(!Reg.isSubRegister() && "full register expected"); // Pattern-match combinations for which more efficient representations exist. // [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset]. @@ -314,6 +328,25 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, return true; } +void DwarfExpression::setEntryValueFlags(const MachineLocation &Loc) { + LocationFlags |= EntryValue; + if (Loc.isIndirect()) + LocationFlags |= Indirect; +} + +void DwarfExpression::setLocation(const MachineLocation &Loc, + const DIExpression *DIExpr) { + if (Loc.isIndirect()) + // Do not treat entry value descriptions of indirect parameters as memory + // locations. This allows DwarfExpression::addReg() to add DW_OP_regN to an + // entry value description. + if (!DIExpr->isEntryValue()) + setMemoryLocationKind(); + + if (DIExpr->isEntryValue()) + setEntryValueFlags(Loc); +} + void DwarfExpression::beginEntryValueExpression( DIExpressionCursor &ExprCursor) { auto Op = ExprCursor.take(); @@ -325,7 +358,6 @@ void DwarfExpression::beginEntryValueExpression( assert(Op->getArg(0) == 1 && "Can currently only emit entry values covering a single operation"); - emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value)); IsEmittingEntryValue = true; enableTemporaryBuffer(); } @@ -334,6 +366,8 @@ void DwarfExpression::finalizeEntryValue() { assert(IsEmittingEntryValue && "Entry value not open?"); disableTemporaryBuffer(); + emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value)); + // Emit the entry value's size operand. unsigned Size = getTemporaryBufferSize(); emitUnsigned(Size); @@ -344,7 +378,35 @@ void DwarfExpression::finalizeEntryValue() { IsEmittingEntryValue = false; } -/// Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?". +void DwarfExpression::cancelEntryValue() { + assert(IsEmittingEntryValue && "Entry value not open?"); + disableTemporaryBuffer(); + + // The temporary buffer can't be emptied, so for now just assert that nothing + // has been emitted to it. + assert(getTemporaryBufferSize() == 0 && + "Began emitting entry value block before cancelling entry value"); + + IsEmittingEntryValue = false; +} + +unsigned DwarfExpression::getOrCreateBaseType(unsigned BitSize, + dwarf::TypeKind Encoding) { + // Reuse the base_type if we already have one in this CU otherwise we + // create a new one. + unsigned I = 0, E = CU.ExprRefedBaseTypes.size(); + for (; I != E; ++I) + if (CU.ExprRefedBaseTypes[I].BitSize == BitSize && + CU.ExprRefedBaseTypes[I].Encoding == Encoding) + break; + + if (I == E) + CU.ExprRefedBaseTypes.emplace_back(BitSize, Encoding); + return I; +} + +/// Assuming a well-formed expression, match "DW_OP_deref* +/// DW_OP_LLVM_fragment?". static bool isMemoryLocation(DIExpressionCursor ExprCursor) { while (ExprCursor) { auto Op = ExprCursor.take(); @@ -361,6 +423,10 @@ static bool isMemoryLocation(DIExpressionCursor ExprCursor) { void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, unsigned FragmentOffsetInBits) { + // Entry values can currently only cover the initial register location, + // and not any other parts of the following DWARF expression. + assert(!IsEmittingEntryValue && "Can't emit entry value around expression"); + // If we need to mask out a subregister, do it now, unless the next // operation would emit an OpPiece anyway. auto N = ExprCursor.peek(); @@ -431,6 +497,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, case dwarf::DW_OP_lit0: case dwarf::DW_OP_not: case dwarf::DW_OP_dup: + case dwarf::DW_OP_push_object_address: emitOp(OpNum); break; case dwarf::DW_OP_deref: @@ -451,24 +518,13 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, dwarf::TypeKind Encoding = static_cast<dwarf::TypeKind>(Op->getArg(1)); if (DwarfVersion >= 5) { emitOp(dwarf::DW_OP_convert); - // Reuse the base_type if we already have one in this CU otherwise we - // create a new one. - unsigned I = 0, E = CU.ExprRefedBaseTypes.size(); - for (; I != E; ++I) - if (CU.ExprRefedBaseTypes[I].BitSize == BitSize && - CU.ExprRefedBaseTypes[I].Encoding == Encoding) - break; - - if (I == E) - CU.ExprRefedBaseTypes.emplace_back(BitSize, Encoding); - // If targeting a location-list; simply emit the index into the raw // byte stream as ULEB128, DwarfDebug::emitDebugLocEntry has been // fitted with means to extract it later. // If targeting a inlined DW_AT_location; insert a DIEBaseTypeRef // (containing the index and a resolve mechanism during emit) into the // DIE value list. - emitBaseTypeRef(I); + emitBaseTypeRef(getOrCreateBaseType(BitSize, Encoding)); } else { if (PrevConvertOp && PrevConvertOp->getArg(0) < BitSize) { if (Encoding == dwarf::DW_ATE_signed) @@ -573,10 +629,10 @@ void DwarfExpression::emitLegacyZExt(unsigned FromBits) { emitOp(dwarf::DW_OP_and); } -void DwarfExpression::addWasmLocation(unsigned Index, int64_t Offset) { +void DwarfExpression::addWasmLocation(unsigned Index, uint64_t Offset) { assert(LocationKind == Implicit || LocationKind == Unknown); LocationKind = Implicit; emitOp(dwarf::DW_OP_WASM_location); emitUnsigned(Index); - emitSigned(Offset); + emitUnsigned(Offset); } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 46c07b1d5b6b..757b17511453 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -30,6 +30,7 @@ class APInt; class DwarfCompileUnit; class DIELoc; class TargetRegisterInfo; +class MachineLocation; /// Holds a DIExpression and keeps track of how many operands have been consumed /// so far. @@ -107,8 +108,21 @@ protected: /// Holds information about all subregisters comprising a register location. struct Register { int DwarfRegNo; - unsigned Size; + unsigned SubRegSize; const char *Comment; + + /// Create a full register, no extra DW_OP_piece operators necessary. + static Register createRegister(int RegNo, const char *Comment) { + return {RegNo, 0, Comment}; + } + + /// Create a subregister that needs a DW_OP_piece operator with SizeInBits. + static Register createSubRegister(int RegNo, unsigned SizeInBits, + const char *Comment) { + return {RegNo, SizeInBits, Comment}; + } + + bool isSubRegister() const { return SubRegSize; } }; /// Whether we are currently emitting an entry value operation. @@ -129,37 +143,31 @@ protected: /// The kind of location description being produced. enum { Unknown = 0, Register, Memory, Implicit }; - /// The flags of location description being produced. - enum { EntryValue = 1, CallSiteParamValue }; + /// Additional location flags which may be combined with any location kind. + /// Currently, entry values are not supported for the Memory location kind. + enum { EntryValue = 1 << 0, Indirect = 1 << 1, CallSiteParamValue = 1 << 2 }; unsigned LocationKind : 3; - unsigned LocationFlags : 2; + unsigned LocationFlags : 3; unsigned DwarfVersion : 4; public: - bool isUnknownLocation() const { - return LocationKind == Unknown; - } + /// Set the location (\p Loc) and \ref DIExpression (\p DIExpr) to describe. + void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr); - bool isMemoryLocation() const { - return LocationKind == Memory; - } + bool isUnknownLocation() const { return LocationKind == Unknown; } - bool isRegisterLocation() const { - return LocationKind == Register; - } + bool isMemoryLocation() const { return LocationKind == Memory; } - bool isImplicitLocation() const { - return LocationKind == Implicit; - } + bool isRegisterLocation() const { return LocationKind == Register; } - bool isEntryValue() const { - return LocationFlags & EntryValue; - } + bool isImplicitLocation() const { return LocationKind == Implicit; } - bool isParameterValue() { - return LocationFlags & CallSiteParamValue; - } + bool isEntryValue() const { return LocationFlags & EntryValue; } + + bool isIndirect() const { return LocationFlags & Indirect; } + + bool isParameterValue() { return LocationFlags & CallSiteParamValue; } Optional<uint8_t> TagOffset; @@ -209,7 +217,8 @@ protected: /// Return whether the given machine register is the frame register in the /// current function. - virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0; + virtual bool isFrameRegister(const TargetRegisterInfo &TRI, + unsigned MachineReg) = 0; /// Emit a DW_OP_reg operation. Note that this is only legal inside a DWARF /// register location description. @@ -267,6 +276,9 @@ protected: /// DWARF block which has been emitted to the temporary buffer. void finalizeEntryValue(); + /// Cancel the emission of an entry value. + void cancelEntryValue(); + ~DwarfExpression() = default; public: @@ -294,14 +306,10 @@ public: } /// Lock this down to become an entry value location. - void setEntryValueFlag() { - LocationFlags |= EntryValue; - } + void setEntryValueFlags(const MachineLocation &Loc); /// Lock this down to become a call site parameter location. - void setCallSiteParamValueFlag() { - LocationFlags |= CallSiteParamValue; - } + void setCallSiteParamValueFlag() { LocationFlags |= CallSiteParamValue; } /// Emit a machine register location. As an optimization this may also consume /// the prefix of a DwarfExpression if a more efficient representation for @@ -323,6 +331,10 @@ public: /// any operands here. void beginEntryValueExpression(DIExpressionCursor &ExprCursor); + /// Return the index of a base type with the given properties and + /// create one if necessary. + unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding); + /// Emit all remaining operations in the DIExpressionCursor. /// /// \param FragmentOffsetInBits If this is one fragment out of multiple @@ -340,7 +352,7 @@ public: /// Emit location information expressed via WebAssembly location + offset /// The Index is an identifier for locals, globals or operand stack. - void addWasmLocation(unsigned Index, int64_t Offset); + void addWasmLocation(unsigned Index, uint64_t Offset); }; /// DwarfExpression implementation for .debug_loc entries. @@ -374,6 +386,7 @@ class DebugLocDwarfExpression final : public DwarfExpression { bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) override; + public: DebugLocDwarfExpression(unsigned DwarfVersion, BufferByteStreamer &BS, DwarfCompileUnit &CU) @@ -403,6 +416,7 @@ class DIEDwarfExpression final : public DwarfExpression { bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) override; + public: DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp index e5c4db58f477..812e6383288f 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -53,7 +53,7 @@ void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) { Asm->emitDwarfDIE(TheU->getUnitDie()); if (MCSymbol *EndLabel = TheU->getEndLabel()) - Asm->OutStreamer->EmitLabel(EndLabel); + Asm->OutStreamer->emitLabel(EndLabel); } // Compute the size and offset for each DIE. diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp index 2a76dcb1b082..a43929d8e8f7 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp @@ -71,7 +71,7 @@ void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm, // referenced by most unit headers via DW_AT_str_offsets_base. // Split units do not use the attribute. if (StartSym) - Asm.OutStreamer->EmitLabel(StartSym); + Asm.OutStreamer->emitLabel(StartSym); } void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection, @@ -100,12 +100,12 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection, // Emit a label for reference from debug information entries. if (ShouldCreateSymbols) - Asm.OutStreamer->EmitLabel(Entry->getValue().Symbol); + Asm.OutStreamer->emitLabel(Entry->getValue().Symbol); // Emit the string itself with a terminating null byte. Asm.OutStreamer->AddComment("string offset=" + Twine(Entry->getValue().Offset)); - Asm.OutStreamer->EmitBytes( + Asm.OutStreamer->emitBytes( StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1)); } @@ -125,6 +125,6 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection, if (UseRelativeOffsets) Asm.emitDwarfStringOffset(Entry->getValue()); else - Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size); + Asm.OutStreamer->emitIntValue(Entry->getValue().Offset, size); } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 53747aef77fd..e958f38e486b 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -188,8 +188,9 @@ int64_t DwarfUnit::getDefaultLowerBound() const { /// Check whether the DIE for this MDNode can be shared across CUs. bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const { - // When the MDNode can be part of the type system, the DIE can be shared - // across CUs. + // When the MDNode can be part of the type system (this includes subprogram + // declarations *and* subprogram definitions, even local definitions), the + // DIE must be shared across CUs. // Combining type units and cross-CU DIE sharing is lower value (since // cross-CU DIE sharing is used in LTO and removes type redundancy at that // level already) but may be implementable for some value in projects @@ -197,9 +198,7 @@ bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const { // together. if (isDwoUnit() && !DD->shareAcrossDWOCUs()) return false; - return (isa<DIType>(D) || - (isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) && - !DD->generateTypeUnits(); + return (isa<DIType>(D) || isa<DISubprogram>(D)) && !DD->generateTypeUnits(); } DIE *DwarfUnit::getDIE(const DINode *D) const { @@ -1046,6 +1045,8 @@ void DwarfUnit::constructTemplateTypeParameterDIE( addType(ParamDIE, TP->getType()); if (!TP->getName().empty()) addString(ParamDIE, dwarf::DW_AT_name, TP->getName()); + if (TP->isDefault() && (DD->getDwarfVersion() >= 5)) + addFlag(ParamDIE, dwarf::DW_AT_default_value); } void DwarfUnit::constructTemplateValueParameterDIE( @@ -1058,6 +1059,8 @@ void DwarfUnit::constructTemplateValueParameterDIE( addType(ParamDIE, VP->getType()); if (!VP->getName().empty()) addString(ParamDIE, dwarf::DW_AT_name, VP->getName()); + if (VP->isDefault() && (DD->getDwarfVersion() >= 5)) + addFlag(ParamDIE, dwarf::DW_AT_default_value); if (Metadata *Val = VP->getValue()) { if (ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Val)) addConstantValue(ParamDIE, CI, VP->getType()); @@ -1123,8 +1126,13 @@ DIE *DwarfUnit::getOrCreateModule(const DIModule *M) { M->getConfigurationMacros()); if (!M->getIncludePath().empty()) addString(MDie, dwarf::DW_AT_LLVM_include_path, M->getIncludePath()); - if (!M->getSysRoot().empty()) - addString(MDie, dwarf::DW_AT_LLVM_sysroot, M->getSysRoot()); + if (!M->getAPINotesFile().empty()) + addString(MDie, dwarf::DW_AT_LLVM_apinotes, M->getAPINotesFile()); + if (M->getFile()) + addUInt(MDie, dwarf::DW_AT_decl_file, None, + getOrCreateSourceID(M->getFile())); + if (M->getLineNo()) + addUInt(MDie, dwarf::DW_AT_decl_line, None, M->getLineNo()); return &MDie; } @@ -1166,6 +1174,14 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE *DeclDie = nullptr; StringRef DeclLinkageName; if (auto *SPDecl = SP->getDeclaration()) { + DITypeRefArray DeclArgs, DefinitionArgs; + DeclArgs = SPDecl->getType()->getTypeArray(); + DefinitionArgs = SP->getType()->getTypeArray(); + + if (DeclArgs.size() && DefinitionArgs.size()) + if (DefinitionArgs[0] != NULL && DeclArgs[0] != DefinitionArgs[0]) + addType(SPDie, DefinitionArgs[0]); + DeclDie = getDIE(SPDecl); assert(DeclDie && "This DIE should've already been constructed when the " "definition DIE was created in " @@ -1333,20 +1349,40 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, // C/C++. The Count value is the number of elements. Values are 64 bit. If // Count == -1 then the array is unbounded and we do not emit // DW_AT_lower_bound and DW_AT_count attributes. - int64_t LowerBound = SR->getLowerBound(); int64_t DefaultLowerBound = getDefaultLowerBound(); int64_t Count = -1; if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>()) Count = CI->getSExtValue(); - if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound) - addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound); + auto addBoundTypeEntry = [&](dwarf::Attribute Attr, + DISubrange::BoundType Bound) -> void { + if (auto *BV = Bound.dyn_cast<DIVariable *>()) { + if (auto *VarDIE = getDIE(BV)) + addDIEEntry(DW_Subrange, Attr, *VarDIE); + } else if (auto *BE = Bound.dyn_cast<DIExpression *>()) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc); + DwarfExpr.setMemoryLocationKind(); + DwarfExpr.addExpression(BE); + addBlock(DW_Subrange, Attr, DwarfExpr.finalize()); + } else if (auto *BI = Bound.dyn_cast<ConstantInt *>()) { + if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 || + BI->getSExtValue() != DefaultLowerBound) + addSInt(DW_Subrange, Attr, dwarf::DW_FORM_sdata, BI->getSExtValue()); + } + }; + + addBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound()); if (auto *CV = SR->getCount().dyn_cast<DIVariable*>()) { if (auto *CountVarDIE = getDIE(CV)) addDIEEntry(DW_Subrange, dwarf::DW_AT_count, *CountVarDIE); } else if (Count != -1) addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count); + + addBoundTypeEntry(dwarf::DW_AT_upper_bound, SR->getUpperBound()); + + addBoundTypeEntry(dwarf::DW_AT_byte_stride, SR->getStride()); } DIE *DwarfUnit::getIndexTyDie() { @@ -1398,6 +1434,17 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) { CTy->getSizeInBits() / CHAR_BIT); } + if (DIVariable *Var = CTy->getDataLocation()) { + if (auto *VarDIE = getDIE(Var)) + addDIEEntry(Buffer, dwarf::DW_AT_data_location, *VarDIE); + } else if (DIExpression *Expr = CTy->getDataLocationExp()) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc); + DwarfExpr.setMemoryLocationKind(); + DwarfExpr.addExpression(Expr); + addBlock(Buffer, dwarf::DW_AT_data_location, DwarfExpr.finalize()); + } + // Emit the element type. addType(Buffer, CTy->getBaseType()); @@ -1438,8 +1485,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) { DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer); StringRef Name = Enum->getName(); addString(Enumerator, dwarf::DW_AT_name, Name); - auto Value = static_cast<uint64_t>(Enum->getValue()); - addConstantValue(Enumerator, IsUnsigned, Value); + addConstantValue(Enumerator, Enum->getValue(), IsUnsigned); if (IndexEnumerators) addGlobalName(Name, Enumerator, Context); } @@ -1623,8 +1669,8 @@ void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) { StringRef Prefix = isDwoUnit() ? "debug_info_dwo_" : "debug_info_"; MCSymbol *BeginLabel = Asm->createTempSymbol(Prefix + "start"); EndLabel = Asm->createTempSymbol(Prefix + "end"); - Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); - Asm->OutStreamer->EmitLabel(BeginLabel); + Asm->emitLabelDifference(EndLabel, BeginLabel, 4); + Asm->OutStreamer->emitLabel(BeginLabel); } else Asm->emitInt32(getHeaderSize() + getUnitDie().getSize()); @@ -1662,10 +1708,10 @@ void DwarfTypeUnit::emitHeader(bool UseOffsets) { DD->useSplitDwarf() ? dwarf::DW_UT_split_type : dwarf::DW_UT_type); Asm->OutStreamer->AddComment("Type Signature"); - Asm->OutStreamer->EmitIntValue(TypeSignature, sizeof(TypeSignature)); + Asm->OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature)); Asm->OutStreamer->AddComment("Type DIE Offset"); // In a skeleton type unit there is no type DIE so emit a zero offset. - Asm->OutStreamer->EmitIntValue(Ty ? Ty->getOffset() : 0, + Asm->OutStreamer->emitIntValue(Ty ? Ty->getOffset() : 0, sizeof(Ty->getOffset())); } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index 46c52a1faf4b..34f3a34ed336 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -27,7 +27,6 @@ namespace llvm { -class MachineLocation; class MachineOperand; class ConstantInt; class ConstantFP; diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp index 31dfaaac836e..99ee4567fa58 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -426,18 +426,18 @@ MCSymbol *EHStreamer::emitExceptionTable() { // EHABI). In this case LSDASection will be NULL. if (LSDASection) Asm->OutStreamer->SwitchSection(LSDASection); - Asm->EmitAlignment(Align(4)); + Asm->emitAlignment(Align(4)); // Emit the LSDA. MCSymbol *GCCETSym = Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+ Twine(Asm->getFunctionNumber())); - Asm->OutStreamer->EmitLabel(GCCETSym); - Asm->OutStreamer->EmitLabel(Asm->getCurExceptionSym()); + Asm->OutStreamer->emitLabel(GCCETSym); + Asm->OutStreamer->emitLabel(Asm->getCurExceptionSym()); // Emit the LSDA header. - Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); - Asm->EmitEncodingByte(TTypeEncoding, "@TType"); + Asm->emitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); + Asm->emitEncodingByte(TTypeEncoding, "@TType"); MCSymbol *TTBaseLabel = nullptr; if (HaveTTData) { @@ -447,8 +447,8 @@ MCSymbol *EHStreamer::emitExceptionTable() { // the type table. See PR35809 or GNU as bug 4029. MCSymbol *TTBaseRefLabel = Asm->createTempSymbol("ttbaseref"); TTBaseLabel = Asm->createTempSymbol("ttbase"); - Asm->EmitLabelDifferenceAsULEB128(TTBaseLabel, TTBaseRefLabel); - Asm->OutStreamer->EmitLabel(TTBaseRefLabel); + Asm->emitLabelDifferenceAsULEB128(TTBaseLabel, TTBaseRefLabel); + Asm->OutStreamer->emitLabel(TTBaseRefLabel); } bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); @@ -456,9 +456,9 @@ MCSymbol *EHStreamer::emitExceptionTable() { // Emit the landing pad call site table. MCSymbol *CstBeginLabel = Asm->createTempSymbol("cst_begin"); MCSymbol *CstEndLabel = Asm->createTempSymbol("cst_end"); - Asm->EmitEncodingByte(CallSiteEncoding, "Call site"); - Asm->EmitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel); - Asm->OutStreamer->EmitLabel(CstBeginLabel); + Asm->emitEncodingByte(CallSiteEncoding, "Call site"); + Asm->emitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel); + Asm->OutStreamer->emitLabel(CstBeginLabel); // SjLj / Wasm Exception handling if (IsSJLJ || IsWasm) { @@ -472,7 +472,7 @@ MCSymbol *EHStreamer::emitExceptionTable() { Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<"); Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx)); } - Asm->EmitULEB128(idx); + Asm->emitULEB128(idx); // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of @@ -484,7 +484,7 @@ MCSymbol *EHStreamer::emitExceptionTable() { Asm->OutStreamer->AddComment(" Action: " + Twine((S.Action - 1) / 2 + 1)); } - Asm->EmitULEB128(S.Action); + Asm->emitULEB128(S.Action); } } else { // Itanium LSDA exception handling @@ -524,23 +524,23 @@ MCSymbol *EHStreamer::emitExceptionTable() { // Offset of the call site relative to the start of the procedure. if (VerboseAsm) Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<"); - Asm->EmitCallSiteOffset(BeginLabel, EHFuncBeginSym, CallSiteEncoding); + Asm->emitCallSiteOffset(BeginLabel, EHFuncBeginSym, CallSiteEncoding); if (VerboseAsm) Asm->OutStreamer->AddComment(Twine(" Call between ") + BeginLabel->getName() + " and " + EndLabel->getName()); - Asm->EmitCallSiteOffset(EndLabel, BeginLabel, CallSiteEncoding); + Asm->emitCallSiteOffset(EndLabel, BeginLabel, CallSiteEncoding); // Offset of the landing pad relative to the start of the procedure. if (!S.LPad) { if (VerboseAsm) Asm->OutStreamer->AddComment(" has no landing pad"); - Asm->EmitCallSiteValue(0, CallSiteEncoding); + Asm->emitCallSiteValue(0, CallSiteEncoding); } else { if (VerboseAsm) Asm->OutStreamer->AddComment(Twine(" jumps to ") + S.LPad->LandingPadLabel->getName()); - Asm->EmitCallSiteOffset(S.LPad->LandingPadLabel, EHFuncBeginSym, + Asm->emitCallSiteOffset(S.LPad->LandingPadLabel, EHFuncBeginSym, CallSiteEncoding); } @@ -554,10 +554,10 @@ MCSymbol *EHStreamer::emitExceptionTable() { Asm->OutStreamer->AddComment(" On action: " + Twine((S.Action - 1) / 2 + 1)); } - Asm->EmitULEB128(S.Action); + Asm->emitULEB128(S.Action); } } - Asm->OutStreamer->EmitLabel(CstEndLabel); + Asm->OutStreamer->emitLabel(CstEndLabel); // Emit the Action Table. int Entry = 0; @@ -584,7 +584,7 @@ MCSymbol *EHStreamer::emitExceptionTable() { else Asm->OutStreamer->AddComment(" Cleanup"); } - Asm->EmitSLEB128(Action.ValueForTypeID); + Asm->emitSLEB128(Action.ValueForTypeID); // Action Record // @@ -598,15 +598,15 @@ MCSymbol *EHStreamer::emitExceptionTable() { Asm->OutStreamer->AddComment(" Continue to action "+Twine(NextAction)); } } - Asm->EmitSLEB128(Action.NextAction); + Asm->emitSLEB128(Action.NextAction); } if (HaveTTData) { - Asm->EmitAlignment(Align(4)); + Asm->emitAlignment(Align(4)); emitTypeInfos(TTypeEncoding, TTBaseLabel); } - Asm->EmitAlignment(Align(4)); + Asm->emitAlignment(Align(4)); return GCCETSym; } @@ -629,10 +629,10 @@ void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) { TypeInfos.rend())) { if (VerboseAsm) Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); - Asm->EmitTTypeReference(GV, TTypeEncoding); + Asm->emitTTypeReference(GV, TTypeEncoding); } - Asm->OutStreamer->EmitLabel(TTBaseLabel); + Asm->OutStreamer->emitLabel(TTBaseLabel); // Emit the Exception Specifications. if (VerboseAsm && !FilterIds.empty()) { @@ -649,6 +649,6 @@ void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) { Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); } - Asm->EmitULEB128(TypeID); + Asm->emitULEB128(TypeID); } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp index 3849644d1584..59a84e6f2d7b 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp @@ -72,7 +72,7 @@ void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info, **/ // Align to address width. - AP.EmitAlignment(IntPtrSize == 4 ? Align(4) : Align(8)); + AP.emitAlignment(IntPtrSize == 4 ? Align(4) : Align(8)); // Emit PointCount. OS.AddComment("safe point count"); @@ -84,7 +84,7 @@ void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info, // Emit the address of the safe point. OS.AddComment("safe point address"); MCSymbol *Label = PI->Label; - AP.EmitLabelPlusOffset(Label /*Hi*/, 0 /*Offset*/, 4 /*Size*/); + AP.emitLabelPlusOffset(Label /*Hi*/, 0 /*Offset*/, 4 /*Size*/); } // Stack information never change in safe points! Only print info from the diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index b4eda5fa8c58..8fa83f515910 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -66,8 +66,8 @@ static void EmitCamlGlobal(const Module &M, AsmPrinter &AP, const char *Id) { MCSymbol *Sym = AP.OutContext.getOrCreateSymbol(TmpStr); - AP.OutStreamer->EmitSymbolAttribute(Sym, MCSA_Global); - AP.OutStreamer->EmitLabel(Sym); + AP.OutStreamer->emitSymbolAttribute(Sym, MCSA_Global); + AP.OutStreamer->emitLabel(Sym); } void OcamlGCMetadataPrinter::beginAssembly(Module &M, GCModuleInfo &Info, @@ -106,7 +106,7 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info, EmitCamlGlobal(M, AP, "data_end"); // FIXME: Why does ocaml emit this?? - AP.OutStreamer->EmitIntValue(0, IntPtrSize); + AP.OutStreamer->emitIntValue(0, IntPtrSize); AP.OutStreamer->SwitchSection(AP.getObjFileLowering().getDataSection()); EmitCamlGlobal(M, AP, "frametable"); @@ -129,7 +129,7 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info, report_fatal_error(" Too much descriptor for ocaml GC"); } AP.emitInt16(NumDescriptors); - AP.EmitAlignment(IntPtrSize == 4 ? Align(4) : Align(8)); + AP.emitAlignment(IntPtrSize == 4 ? Align(4) : Align(8)); for (GCModuleInfo::FuncInfoVec::iterator I = Info.funcinfo_begin(), IE = Info.funcinfo_end(); @@ -164,7 +164,7 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info, Twine(LiveCount) + " >= 65536."); } - AP.OutStreamer->EmitSymbolValue(J->Label, IntPtrSize); + AP.OutStreamer->emitSymbolValue(J->Label, IntPtrSize); AP.emitInt16(FrameSize); AP.emitInt16(LiveCount); @@ -180,7 +180,7 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info, AP.emitInt16(K->StackOffset); } - AP.EmitAlignment(IntPtrSize == 4 ? Align(4) : Align(8)); + AP.emitAlignment(IntPtrSize == 4 ? Align(4) : Align(8)); } } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp index 444b0ed17b6d..baef4d2cc849 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp @@ -27,7 +27,7 @@ void WasmException::endModule() { Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout()); if (Asm->OutContext.lookupSymbol(NameStr)) { MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception"); - Asm->OutStreamer->EmitLabel(ExceptionSym); + Asm->OutStreamer->emitLabel(ExceptionSym); } } @@ -58,7 +58,7 @@ void WasmException::endFunction(const MachineFunction *MF) { // end marker and set the size as the difference between the start end the end // marker. MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end"); - Asm->OutStreamer->EmitLabel(LSDAEndLabel); + Asm->OutStreamer->emitLabel(LSDAEndLabel); MCContext &OutContext = Asm->OutStreamer->getContext(); const MCExpr *SizeExp = MCBinaryExpr::createSub( MCSymbolRefExpr::create(LSDAEndLabel, OutContext), diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 0398675577cd..cd8077e7d548 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -203,11 +204,11 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB, // We want our funclet's entry point to be aligned such that no nops will be // present after the label. - Asm->EmitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()), + Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()), &F); // Now that we've emitted the alignment directive, point at our funclet. - Asm->OutStreamer->EmitLabel(Sym); + Asm->OutStreamer->emitLabel(Sym); } // Mark 'Sym' as starting our funclet. @@ -276,7 +277,7 @@ void WinException::endFuncletImpl() { StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName()); MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol( Twine("$cppxdata$", FuncLinkageName)); - Asm->OutStreamer->EmitValue(create32bitRef(FuncInfoXData), 4); + Asm->OutStreamer->emitValue(create32bitRef(FuncInfoXData), 4); } else if (Per == EHPersonality::MSVC_Win64SEH && MF->hasEHFunclets() && !CurrentFuncletEntry->isEHFuncletEntry()) { // If this is the parent function in Win64 SEH, emit the LSDA immediately @@ -336,7 +337,7 @@ const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf, int WinException::getFrameIndexOffset(int FrameIndex, const WinEHFuncInfo &FuncInfo) { const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering(); - unsigned UnusedReg; + Register UnusedReg; if (Asm->MAI->usesWindowsCFI()) { int Offset = TFI.getFrameIndexReferencePreferSP(*Asm->MF, FrameIndex, UnusedReg, @@ -566,7 +567,7 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); const MCExpr *MCOffset = MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx); - Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset); + Asm->OutStreamer->emitAssignment(ParentFrameOffset, MCOffset); } // Use the assembler to compute the number of table entries through label @@ -579,9 +580,9 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx); const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx); AddComment("Number of call sites"); - OS.EmitValue(EntryCount, 4); + OS.emitValue(EntryCount, 4); - OS.EmitLabel(TableBegin); + OS.emitLabel(TableBegin); // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only // models exceptions from invokes. LLVM also allows arbitrary reordering of @@ -609,7 +610,7 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { LastEHState = StateChange.NewState; } - OS.EmitLabel(TableEnd); + OS.emitLabel(TableEnd); } void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, @@ -641,14 +642,14 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, } AddComment("LabelStart"); - OS.EmitValue(getLabel(BeginLabel), 4); + OS.emitValue(getLabel(BeginLabel), 4); AddComment("LabelEnd"); - OS.EmitValue(getLabel(EndLabel), 4); + OS.emitValue(getLabel(EndLabel), 4); AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction" : "CatchAll"); - OS.EmitValue(FilterOrFinally, 4); + OS.emitValue(FilterOrFinally, 4); AddComment(UME.IsFinally ? "Null" : "ExceptionHandler"); - OS.EmitValue(ExceptOrNull, 4); + OS.emitValue(ExceptOrNull, 4); assert(UME.ToState < State && "states should decrease"); State = UME.ToState; @@ -713,55 +714,55 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { // EHFlags & 1 -> Synchronous exceptions only, no async exceptions. // EHFlags & 2 -> ??? // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue. - OS.EmitValueToAlignment(4); - OS.EmitLabel(FuncInfoXData); + OS.emitValueToAlignment(4); + OS.emitLabel(FuncInfoXData); AddComment("MagicNumber"); - OS.EmitIntValue(0x19930522, 4); + OS.emitInt32(0x19930522); AddComment("MaxState"); - OS.EmitIntValue(FuncInfo.CxxUnwindMap.size(), 4); + OS.emitInt32(FuncInfo.CxxUnwindMap.size()); AddComment("UnwindMap"); - OS.EmitValue(create32bitRef(UnwindMapXData), 4); + OS.emitValue(create32bitRef(UnwindMapXData), 4); AddComment("NumTryBlocks"); - OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); + OS.emitInt32(FuncInfo.TryBlockMap.size()); AddComment("TryBlockMap"); - OS.EmitValue(create32bitRef(TryBlockMapXData), 4); + OS.emitValue(create32bitRef(TryBlockMapXData), 4); AddComment("IPMapEntries"); - OS.EmitIntValue(IPToStateTable.size(), 4); + OS.emitInt32(IPToStateTable.size()); AddComment("IPToStateXData"); - OS.EmitValue(create32bitRef(IPToStateXData), 4); + OS.emitValue(create32bitRef(IPToStateXData), 4); if (Asm->MAI->usesWindowsCFI()) { AddComment("UnwindHelp"); - OS.EmitIntValue(UnwindHelpOffset, 4); + OS.emitInt32(UnwindHelpOffset); } AddComment("ESTypeList"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); AddComment("EHFlags"); - OS.EmitIntValue(1, 4); + OS.emitInt32(1); // UnwindMapEntry { // int32_t ToState; // void (*Action)(); // }; if (UnwindMapXData) { - OS.EmitLabel(UnwindMapXData); + OS.emitLabel(UnwindMapXData); for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) { MCSymbol *CleanupSym = getMCSymbolForMBB(Asm, UME.Cleanup.dyn_cast<MachineBasicBlock *>()); AddComment("ToState"); - OS.EmitIntValue(UME.ToState, 4); + OS.emitInt32(UME.ToState); AddComment("Action"); - OS.EmitValue(create32bitRef(CleanupSym), 4); + OS.emitValue(create32bitRef(CleanupSym), 4); } } @@ -773,7 +774,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { // HandlerType *HandlerArray; // }; if (TryBlockMapXData) { - OS.EmitLabel(TryBlockMapXData); + OS.emitLabel(TryBlockMapXData); SmallVector<MCSymbol *, 1> HandlerMaps; for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) { const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; @@ -795,19 +796,19 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { "bad trymap interval"); AddComment("TryLow"); - OS.EmitIntValue(TBME.TryLow, 4); + OS.emitInt32(TBME.TryLow); AddComment("TryHigh"); - OS.EmitIntValue(TBME.TryHigh, 4); + OS.emitInt32(TBME.TryHigh); AddComment("CatchHigh"); - OS.EmitIntValue(TBME.CatchHigh, 4); + OS.emitInt32(TBME.CatchHigh); AddComment("NumCatches"); - OS.EmitIntValue(TBME.HandlerArray.size(), 4); + OS.emitInt32(TBME.HandlerArray.size()); AddComment("HandlerArray"); - OS.EmitValue(create32bitRef(HandlerMapXData), 4); + OS.emitValue(create32bitRef(HandlerMapXData), 4); } // All funclets use the same parent frame offset currently. @@ -829,7 +830,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { // void (*Handler)(); // int32_t ParentFrameOffset; // x64 and AArch64 only // }; - OS.EmitLabel(HandlerMapXData); + OS.emitLabel(HandlerMapXData); for (const WinEHHandlerType &HT : TBME.HandlerArray) { // Get the frame escape label with the offset of the catch object. If // the index is INT_MAX, then there is no catch object, and we should @@ -847,20 +848,20 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { getMCSymbolForMBB(Asm, HT.Handler.dyn_cast<MachineBasicBlock *>()); AddComment("Adjectives"); - OS.EmitIntValue(HT.Adjectives, 4); + OS.emitInt32(HT.Adjectives); AddComment("Type"); - OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); + OS.emitValue(create32bitRef(HT.TypeDescriptor), 4); AddComment("CatchObjOffset"); - OS.EmitValue(FrameAllocOffsetRef, 4); + OS.emitValue(FrameAllocOffsetRef, 4); AddComment("Handler"); - OS.EmitValue(create32bitRef(HandlerSym), 4); + OS.emitValue(create32bitRef(HandlerSym), 4); if (shouldEmitPersonality) { AddComment("ParentFrameOffset"); - OS.EmitIntValue(ParentFrameOffset, 4); + OS.emitInt32(ParentFrameOffset); } } } @@ -871,12 +872,12 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { // int32_t State; // }; if (IPToStateXData) { - OS.EmitLabel(IPToStateXData); + OS.emitLabel(IPToStateXData); for (auto &IPStatePair : IPToStateTable) { AddComment("IP"); - OS.EmitValue(IPStatePair.first, 4); + OS.emitValue(IPStatePair.first, 4); AddComment("ToState"); - OS.EmitIntValue(IPStatePair.second, 4); + OS.emitInt32(IPStatePair.second); } } } @@ -956,7 +957,7 @@ void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo, MCContext &Ctx = Asm->OutContext; MCSymbol *ParentFrameOffset = Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); - Asm->OutStreamer->EmitAssignment(ParentFrameOffset, + Asm->OutStreamer->emitAssignment(ParentFrameOffset, MCConstantExpr::create(Offset, Ctx)); } @@ -979,8 +980,8 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { // Emit the __ehtable label that we use for llvm.x86.seh.lsda. MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName); - OS.EmitValueToAlignment(4); - OS.EmitLabel(LSDALabel); + OS.emitValueToAlignment(4); + OS.emitLabel(LSDALabel); const auto *Per = cast<Function>(F.getPersonalityFn()->stripPointerCasts()); StringRef PerName = Per->getName(); @@ -1011,7 +1012,7 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { int GSCookieOffset = -2; const MachineFrameInfo &MFI = MF->getFrameInfo(); if (MFI.hasStackProtectorIndex()) { - unsigned UnusedReg; + Register UnusedReg; const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); int SSPIdx = MFI.getStackProtectorIndex(); GSCookieOffset = TFI->getFrameIndexReference(*MF, SSPIdx, UnusedReg); @@ -1021,20 +1022,20 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { // TODO(etienneb): Get rid of this value and change it for and assertion. int EHCookieOffset = 9999; if (FuncInfo.EHGuardFrameIndex != INT_MAX) { - unsigned UnusedReg; + Register UnusedReg; const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); int EHGuardIdx = FuncInfo.EHGuardFrameIndex; EHCookieOffset = TFI->getFrameIndexReference(*MF, EHGuardIdx, UnusedReg); } AddComment("GSCookieOffset"); - OS.EmitIntValue(GSCookieOffset, 4); + OS.emitInt32(GSCookieOffset); AddComment("GSCookieXOROffset"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); AddComment("EHCookieOffset"); - OS.EmitIntValue(EHCookieOffset, 4); + OS.emitInt32(EHCookieOffset); AddComment("EHCookieXOROffset"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); BaseState = -2; } @@ -1047,11 +1048,11 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { // _except_handler4 it's -2. Do that replacement here if necessary. int ToState = UME.ToState == -1 ? BaseState : UME.ToState; AddComment("ToState"); - OS.EmitIntValue(ToState, 4); + OS.emitInt32(ToState); AddComment(UME.IsFinally ? "Null" : "FilterFunction"); - OS.EmitValue(create32bitRef(UME.Filter), 4); + OS.emitValue(create32bitRef(UME.Filter), 4); AddComment(UME.IsFinally ? "FinallyFunclet" : "ExceptionHandler"); - OS.EmitValue(create32bitRef(ExceptOrFinally), 4); + OS.emitValue(create32bitRef(ExceptOrFinally), 4); } } @@ -1124,9 +1125,9 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { // Write out a sentinel indicating the end of the standard (Windows) xdata // and the start of the additional (CLR) info. - OS.EmitIntValue(0xffffffff, 4); + OS.emitInt32(0xffffffff); // Write out the number of funclets - OS.EmitIntValue(NumStates, 4); + OS.emitInt32(NumStates); // Walk the machine blocks/instrs, computing and emitting a few things: // 1. Emit a list of the offsets to each handler entry, in lexical order. @@ -1164,7 +1165,7 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { } // Emit the function/funclet end and, if this is a funclet (and not the // root function), record it in the EndSymbolMap. - OS.EmitValue(getOffset(EndSymbol, FuncBeginSym), 4); + OS.emitValue(getOffset(EndSymbol, FuncBeginSym), 4); if (FuncletState != NullState) { // Record the end of the handler. EndSymbolMap[FuncletState] = EndSymbol; @@ -1217,7 +1218,7 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { } // Now emit the clause info, starting with the number of clauses. - OS.EmitIntValue(Clauses.size(), 4); + OS.emitInt32(Clauses.size()); for (ClrClause &Clause : Clauses) { // Emit a CORINFO_EH_CLAUSE : /* @@ -1299,18 +1300,18 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { assert(Clause.EnclosingState > MinClauseMap[Clause.State]); Flags |= 8; } - OS.EmitIntValue(Flags, 4); + OS.emitInt32(Flags); // Write the clause start/end - OS.EmitValue(ClauseBegin, 4); - OS.EmitValue(ClauseEnd, 4); + OS.emitValue(ClauseBegin, 4); + OS.emitValue(ClauseEnd, 4); // Write out the handler start/end - OS.EmitValue(HandlerBegin, 4); - OS.EmitValue(HandlerEnd, 4); + OS.emitValue(HandlerBegin, 4); + OS.emitValue(HandlerEnd, 4); // Write out the type token or filter offset assert(Entry.HandlerType != ClrHandlerType::Filter && "NYI: filters"); - OS.EmitIntValue(Entry.TypeToken, 4); + OS.emitInt32(Entry.TypeToken); } } diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.h b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.h index dc5036302131..8bd5d1bc6d2a 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.h +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/WinException.h @@ -16,12 +16,10 @@ #include "EHStreamer.h" namespace llvm { -class Function; class GlobalValue; class MachineFunction; class MCExpr; class MCSection; -class Value; struct WinEHFuncInfo; class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { |