diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter')
24 files changed, 719 insertions, 408 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp index 22ecc5199742..aab3c2681339 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -194,8 +194,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter { uint32_t CompUnitCount; uint32_t LocalTypeUnitCount = 0; uint32_t ForeignTypeUnitCount = 0; - uint32_t BucketCount; - uint32_t NameCount; + uint32_t BucketCount = 0; + uint32_t NameCount = 0; uint32_t AbbrevTableSize = 0; uint32_t AugmentationStringSize = sizeof(AugmentationString); char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'}; @@ -549,9 +549,13 @@ void llvm::emitDWARF5AccelTable( SmallVector<unsigned, 1> CUIndex(CUs.size()); int Count = 0; for (const auto &CU : enumerate(CUs)) { - if (CU.value()->getCUNode()->getNameTableKind() != - DICompileUnit::DebugNameTableKind::Default) + switch (CU.value()->getCUNode()->getNameTableKind()) { + case DICompileUnit::DebugNameTableKind::Default: + case DICompileUnit::DebugNameTableKind::Apple: + break; + default: continue; + } CUIndex[CU.index()] = Count++; assert(CU.index() == CU.value()->getUniqueID()); const DwarfCompileUnit *MainCU = @@ -660,9 +664,9 @@ void AccelTableBase::HashData::print(raw_ostream &OS) const { void AccelTableBase::print(raw_ostream &OS) const { // Print Content. OS << "Entries: \n"; - for (const auto &Entry : Entries) { - OS << "Name: " << Entry.first() << "\n"; - for (auto *V : Entry.second.Values) + for (const auto &[Name, Data] : Entries) { + OS << "Name: " << Name << "\n"; + for (auto *V : Data.Values) V->print(OS); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp b/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp index 32d8dc793510..00ee4e1b47a8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/IR/DataLayout.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include <utility> @@ -24,7 +25,7 @@ unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) { } MCSymbol *AddressPool::emitHeader(AsmPrinter &Asm, MCSection *Section) { - static const uint8_t AddrSize = Asm.getDataLayout().getPointerSize(); + static const uint8_t AddrSize = Asm.MAI->getCodePointerSize(); MCSymbol *EndLabel = Asm.emitDwarfUnitLength("debug_addr", "Length of contribution"); @@ -65,7 +66,7 @@ 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.MAI->getCodePointerSize()); if (EndLabel) Asm.OutStreamer->emitLabel(EndLabel); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 8c126d20fc9a..5381dfdd184c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -26,12 +26,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Analysis/ConstantFolding.h" -#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/BinaryFormat/COFF.h" @@ -39,6 +38,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" +#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineDominators.h" @@ -67,6 +67,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/EHPersonalities.h" #include "llvm/IR/Function.h" #include "llvm/IR/GCStrategy.h" #include "llvm/IR/GlobalAlias.h" @@ -99,6 +100,7 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/SectionKind.h" +#include "llvm/Object/ELFTypes.h" #include "llvm/Pass.h" #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Support/Casting.h" @@ -113,6 +115,7 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cassert> #include <cinttypes> @@ -128,6 +131,13 @@ using namespace llvm; #define DEBUG_TYPE "asm-printer" +static cl::opt<std::string> BasicBlockProfileDump( + "mbb-profile-dump", cl::Hidden, + cl::desc("Basic block profile dump for external cost modelling. If " + "matching up BBs with afterwards, the compilation must be " + "performed with -basic-block-sections=labels. Enabling this " + "flag during in-process ThinLTO is not supported.")); + const char DWARFGroupName[] = "dwarf"; const char DWARFGroupDescription[] = "DWARF Emission"; const char DbgTimerName[] = "emit"; @@ -414,6 +424,7 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); AU.addRequired<MachineOptimizationRemarkEmitterPass>(); AU.addRequired<GCModuleInfo>(); + AU.addRequired<LazyMachineBlockFrequencyInfoPass>(); } bool AsmPrinter::doInitialization(Module &M) { @@ -475,6 +486,11 @@ bool AsmPrinter::doInitialization(Module &M) { } } + // On AIX, emit bytes for llvm.commandline metadata after .file so that the + // C_INFO symbol is preserved if any csect is kept by the linker. + if (TM.getTargetTriple().isOSBinFormatXCOFF()) + emitModuleCommandLines(M); + GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (const auto &I : *MI) @@ -531,7 +547,7 @@ bool AsmPrinter::doInitialization(Module &M) { break; } assert(MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI || - ModuleCFISection != CFISection::EH); + usesCFIWithoutEH() || ModuleCFISection != CFISection::EH); break; default: break; @@ -540,7 +556,7 @@ bool AsmPrinter::doInitialization(Module &M) { EHStreamer *ES = nullptr; switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::None: - if (!needsCFIForDebug()) + if (!usesCFIWithoutEH()) break; [[fallthrough]]; case ExceptionHandling::SjLj: @@ -585,6 +601,16 @@ bool AsmPrinter::doInitialization(Module &M) { HI.Handler->beginModule(&M); } + if (!BasicBlockProfileDump.empty()) { + std::error_code PossibleFileError; + MBBProfileDumpFileOutput = std::make_unique<raw_fd_ostream>( + BasicBlockProfileDump, PossibleFileError); + if (PossibleFileError) { + M.getContext().emitError("Failed to open file for MBB Profile Dump: " + + PossibleFileError.message() + "\n"); + } + } + return false; } @@ -704,8 +730,8 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (T.getArch() != Triple::aarch64 || !T.isAndroid()) OutContext.reportError(SMLoc(), - "Tagged symbols (-fsanitize=memtag-globals) are " - "only supported on aarch64 + Android."); + "tagged symbols (-fsanitize=memtag-globals) are " + "only supported on AArch64 Android"); OutStreamer->emitSymbolAttribute(EmittedSym, MAI->getMemtagAttr()); } @@ -908,13 +934,6 @@ void AsmPrinter::emitFunctionHeader() { if (F.hasFnAttribute(Attribute::Cold)) OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_Cold); - if (isVerbose()) { - F.printAsOperand(OutStreamer->getCommentOS(), - /*PrintType=*/false, F.getParent()); - emitFunctionHeaderComment(); - OutStreamer->getCommentOS() << '\n'; - } - // Emit the prefix data. if (F.hasPrefixData()) { if (MAI->hasSubsectionsViaSymbols()) { @@ -958,6 +977,23 @@ void AsmPrinter::emitFunctionHeader() { CurrentPatchableFunctionEntrySym = CurrentFnBegin; } + // Emit the function prologue data for the indirect call sanitizer. + if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) { + assert(MD->getNumOperands() == 2); + + auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0)); + auto *TypeHash = mdconst::extract<Constant>(MD->getOperand(1)); + emitGlobalConstant(F.getParent()->getDataLayout(), PrologueSig); + emitGlobalConstant(F.getParent()->getDataLayout(), TypeHash); + } + + if (isVerbose()) { + F.printAsOperand(OutStreamer->getCommentOS(), + /*PrintType=*/false, F.getParent()); + emitFunctionHeaderComment(); + OutStreamer->getCommentOS() << '\n'; + } + // Emit the function descriptor. This is a virtual function to allow targets // 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 @@ -1005,24 +1041,6 @@ void AsmPrinter::emitFunctionHeader() { // Emit the prologue data. if (F.hasPrologueData()) emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); - - // Emit the function prologue data for the indirect call sanitizer. - if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) { - assert(TM.getTargetTriple().getArch() == Triple::x86 || - TM.getTargetTriple().getArch() == Triple::x86_64); - assert(MD->getNumOperands() == 2); - - auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0)); - auto *FTRTTIProxy = mdconst::extract<Constant>(MD->getOperand(1)); - assert(PrologueSig && FTRTTIProxy); - emitGlobalConstant(F.getParent()->getDataLayout(), PrologueSig); - - const MCExpr *Proxy = lowerConstant(FTRTTIProxy); - const MCExpr *FnExp = MCSymbolRefExpr::create(CurrentFnSym, OutContext); - const MCExpr *PCRel = MCBinaryExpr::createSub(Proxy, FnExp, OutContext); - // Use 32 bit since only small code model is supported. - OutStreamer->emitValue(PCRel, 4u); - } } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the @@ -1254,6 +1272,10 @@ AsmPrinter::getFunctionCFISectionType(const Function &F) const { F.needsUnwindTableEntry()) return CFISection::EH; + if (MAI->usesCFIWithoutEH() && F.hasUWTable()) + return CFISection::EH; + + assert(MMI != nullptr && "Invalid machine module info"); if (MMI->hasDebugInfo() || TM.Options.ForceDwarfFrameSection) return CFISection::Debug; @@ -1269,14 +1291,13 @@ bool AsmPrinter::needsSEHMoves() { return MAI->usesWindowsCFI() && MF->getFunction().needsUnwindTableEntry(); } -bool AsmPrinter::needsCFIForDebug() const { - return MAI->getExceptionHandlingType() == ExceptionHandling::None && - MAI->doesUseCFIForDebug() && ModuleCFISection == CFISection::Debug; +bool AsmPrinter::usesCFIWithoutEH() const { + return MAI->usesCFIWithoutEH() && ModuleCFISection != CFISection::None; } void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) { ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType(); - if (!needsCFIForDebug() && + if (!usesCFIWithoutEH() && ExceptionHandlingType != ExceptionHandling::DwarfCFI && ExceptionHandlingType != ExceptionHandling::ARM) return; @@ -1310,21 +1331,16 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) { MCConstantExpr::create(FrameOffset, OutContext)); } -/// Returns the BB metadata to be emitted in the .llvm_bb_addr_map section for a -/// given basic block. This can be used to capture more precise profile -/// information. We use the last 4 bits (LSBs) to encode the following -/// information: -/// * (1): set if return block (ret or tail call). -/// * (2): set if ends with a tail call. -/// * (3): set if exception handling (EH) landing pad. -/// * (4): set if the block can fall through to its next. -/// The remaining bits are zero. -static unsigned getBBAddrMapMetadata(const MachineBasicBlock &MBB) { +/// Returns the BB metadata to be emitted in the SHT_LLVM_BB_ADDR_MAP section +/// for a given basic block. This can be used to capture more precise profile +/// information. +static uint32_t getBBAddrMapMetadata(const MachineBasicBlock &MBB) { const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); - return ((unsigned)MBB.isReturnBlock()) | - ((!MBB.empty() && TII->isTailCall(MBB.back())) << 1) | - (MBB.isEHPad() << 2) | - (const_cast<MachineBasicBlock &>(MBB).canFallThrough() << 3); + return object::BBAddrMap::BBEntry::Metadata{ + MBB.isReturnBlock(), !MBB.empty() && TII->isTailCall(MBB.back()), + MBB.isEHPad(), const_cast<MachineBasicBlock &>(MBB).canFallThrough(), + !MBB.empty() && MBB.rbegin()->isIndirectBranch()} + .encode(); } void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { @@ -1346,7 +1362,7 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { OutStreamer->AddComment("number of basic blocks"); OutStreamer->emitULEB128IntValue(MF.size()); const MCSymbol *PrevMBBEndSymbol = FunctionSymbol; - // Emit BB Information for each basic block in the funciton. + // Emit BB Information for each basic block in the function. for (const MachineBasicBlock &MBB : MF) { const MCSymbol *MBBSymbol = MBB.isEntryBlock() ? FunctionSymbol : MBB.getSymbol(); @@ -1496,9 +1512,22 @@ void AsmPrinter::emitPCSections(const MachineFunction &MF) { // constants may appear, which will simply be emitted into the current // section (the user of MD_pcsections decides the format of encoded data). assert(isa<MDString>(MD.getOperand(0)) && "first operand not a string"); + bool ConstULEB128 = false; for (const MDOperand &MDO : MD.operands()) { if (auto *S = dyn_cast<MDString>(MDO)) { - SwitchSection(S->getString()); + // Found string, start of new section! + // Find options for this section "<section>!<opts>" - supported options: + // C = Compress constant integers of size 2-8 bytes as ULEB128. + const StringRef SecWithOpt = S->getString(); + const size_t OptStart = SecWithOpt.find('!'); // likely npos + const StringRef Sec = SecWithOpt.substr(0, OptStart); + const StringRef Opts = SecWithOpt.substr(OptStart); // likely empty + ConstULEB128 = Opts.find('C') != StringRef::npos; +#ifndef NDEBUG + for (char O : Opts) + assert((O == '!' || O == 'C') && "Invalid !pcsections options"); +#endif + SwitchSection(Sec); const MCSymbol *Prev = Syms.front(); for (const MCSymbol *Sym : Syms) { if (Sym == Prev || !Deltas) { @@ -1510,17 +1539,30 @@ void AsmPrinter::emitPCSections(const MachineFunction &MF) { // `base + addr`. emitLabelDifference(Sym, Base, RelativeRelocSize); } else { - emitLabelDifference(Sym, Prev, 4); + // Emit delta between symbol and previous symbol. + if (ConstULEB128) + emitLabelDifferenceAsULEB128(Sym, Prev); + else + emitLabelDifference(Sym, Prev, 4); } Prev = Sym; } } else { + // Emit auxiliary data after PC. assert(isa<MDNode>(MDO) && "expecting either string or tuple"); const auto *AuxMDs = cast<MDNode>(MDO); for (const MDOperand &AuxMDO : AuxMDs->operands()) { assert(isa<ConstantAsMetadata>(AuxMDO) && "expecting a constant"); - const auto *C = cast<ConstantAsMetadata>(AuxMDO); - emitGlobalConstant(F.getParent()->getDataLayout(), C->getValue()); + const Constant *C = cast<ConstantAsMetadata>(AuxMDO)->getValue(); + const DataLayout &DL = F.getParent()->getDataLayout(); + const uint64_t Size = DL.getTypeStoreSize(C->getType()); + + if (auto *CI = dyn_cast<ConstantInt>(C); + CI && ConstULEB128 && Size > 1 && Size <= 8) { + emitULEB128(CI->getZExtValue()); + } else { + emitGlobalConstant(DL, C); + } } } } @@ -1582,6 +1624,7 @@ void AsmPrinter::emitFunctionBody() { // Print out code for the function. bool HasAnyRealCode = false; int NumInstsInFunction = 0; + bool IsEHa = MMI->getModule()->getModuleFlag("eh-asynch"); bool CanDoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE); for (auto &MBB : *MF) { @@ -1620,10 +1663,25 @@ void AsmPrinter::emitFunctionBody() { emitFrameAlloc(MI); break; case TargetOpcode::ANNOTATION_LABEL: - case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol()); break; + case TargetOpcode::EH_LABEL: + OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol()); + // For AsynchEH, insert a Nop if followed by a trap inst + // Or the exception won't be caught. + // (see MCConstantExpr::create(1,..) in WinException.cpp) + // Ignore SDiv/UDiv because a DIV with Const-0 divisor + // must have being turned into an UndefValue. + // Div with variable opnds won't be the first instruction in + // an EH region as it must be led by at least a Load + { + auto MI2 = std::next(MI.getIterator()); + if (IsEHa && MI2 != MBB.end() && + (MI2->mayLoadOrStore() || MI2->mayRaiseFPException())) + emitNops(1); + } + break; case TargetOpcode::INLINEASM: case TargetOpcode::INLINEASM_BR: emitInlineAsm(&MI); @@ -1862,6 +1920,23 @@ void AsmPrinter::emitFunctionBody() { OutStreamer->getCommentOS() << "-- End function\n"; OutStreamer->addBlankLine(); + + // Output MBB ids, function names, and frequencies if the flag to dump + // MBB profile information has been set + if (MBBProfileDumpFileOutput) { + if (!MF->hasBBLabels()) + MF->getContext().reportError( + SMLoc(), + "Unable to find BB labels for MBB profile dump. -mbb-profile-dump " + "must be called with -basic-block-sections=labels"); + MachineBlockFrequencyInfo &MBFI = + getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI(); + for (const auto &MBB : *MF) { + *MBBProfileDumpFileOutput.get() + << MF->getName() << "," << MBB.getBBID() << "," + << MBFI.getBlockFreqRelativeToEntryBlock(&MBB) << "\n"; + } + } } /// Compute the number of Global Variables that uses a Constant. @@ -2235,6 +2310,8 @@ bool AsmPrinter::doFinalization(Module &M) { SmallVector<const GlobalAlias *, 16> AliasStack; SmallPtrSet<const GlobalAlias *, 16> AliasVisited; for (const auto &Alias : M.aliases()) { + if (Alias.hasAvailableExternallyLinkage()) + continue; for (const GlobalAlias *Cur = &Alias; Cur; Cur = dyn_cast<GlobalAlias>(Cur->getAliasee())) { if (!AliasVisited.insert(Cur).second) @@ -2258,7 +2335,9 @@ bool AsmPrinter::doFinalization(Module &M) { emitModuleIdents(M); // Emit bytes for llvm.commandline metadata. - emitModuleCommandLines(M); + // The command line metadata is emitted earlier on XCOFF. + if (!TM.getTargetTriple().isOSBinFormatXCOFF()) + emitModuleCommandLines(M); // Emit .note.GNU-split-stack and .note.GNU-no-split-stack sections if // split-stack is used. @@ -2786,6 +2865,22 @@ void AsmPrinter::emitInt16(int Value) const { OutStreamer->emitInt16(Value); } /// Emit a long directive and value. void AsmPrinter::emitInt32(int Value) const { OutStreamer->emitInt32(Value); } +/// EmitSLEB128 - emit the specified signed leb128 value. +void AsmPrinter::emitSLEB128(int64_t Value, const char *Desc) const { + if (isVerbose() && Desc) + OutStreamer->AddComment(Desc); + + OutStreamer->emitSLEB128IntValue(Value); +} + +void AsmPrinter::emitULEB128(uint64_t Value, const char *Desc, + unsigned PadTo) const { + if (isVerbose() && Desc) + OutStreamer->AddComment(Desc); + + OutStreamer->emitULEB128IntValue(Value, PadTo); +} + /// Emit a long long directive and value. void AsmPrinter::emitInt64(uint64_t Value) const { OutStreamer->emitInt64(Value); @@ -2799,6 +2894,12 @@ void AsmPrinter::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size); } +/// Emit something like ".uleb128 Hi-Lo". +void AsmPrinter::emitLabelDifferenceAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo) const { + OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, 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. @@ -3288,7 +3389,8 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { ExtraBitsSize = alignTo(ExtraBitsSize, 8); ExtraBits = Realigned.getRawData()[0] & (((uint64_t)-1) >> (64 - ExtraBitsSize)); - Realigned.lshrInPlace(ExtraBitsSize); + if (BitWidth >= 64) + Realigned.lshrInPlace(ExtraBitsSize); } else ExtraBits = Realigned.getRawData()[BitWidth / 64]; } @@ -3917,16 +4019,18 @@ void AsmPrinter::emitXRayTable() { Flags, 0, GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym); - if (!TM.Options.XRayOmitFunctionIndex) + if (TM.Options.XRayFunctionIndex) FnSledIndex = OutContext.getELFSection( - "xray_fn_idx", ELF::SHT_PROGBITS, Flags | ELF::SHF_WRITE, 0, - GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym); + "xray_fn_idx", ELF::SHT_PROGBITS, Flags, 0, GroupName, F.hasComdat(), + MCSection::NonUniqueID, LinkedToSym); } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) { - InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map", 0, + InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map", + MachO::S_ATTR_LIVE_SUPPORT, SectionKind::getReadOnlyWithRel()); - if (!TM.Options.XRayOmitFunctionIndex) - FnSledIndex = OutContext.getMachOSection( - "__DATA", "xray_fn_idx", 0, SectionKind::getReadOnlyWithRel()); + if (TM.Options.XRayFunctionIndex) + FnSledIndex = OutContext.getMachOSection("__DATA", "xray_fn_idx", + MachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); } else { llvm_unreachable("Unsupported target"); } @@ -3937,7 +4041,8 @@ void AsmPrinter::emitXRayTable() { // 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); + MCSymbol *SledsStart = + OutContext.createLinkerPrivateSymbol("xray_sleds_start"); OutStreamer->switchSection(InstMap); OutStreamer->emitLabel(SledsStart); for (const auto &Sled : Sleds) { @@ -3968,8 +4073,17 @@ void AsmPrinter::emitXRayTable() { OutStreamer->switchSection(FnSledIndex); OutStreamer->emitCodeAlignment(Align(2 * WordSizeBytes), &getSubtargetInfo()); - OutStreamer->emitSymbolValue(SledsStart, WordSizeBytes, false); - OutStreamer->emitSymbolValue(SledsEnd, WordSizeBytes, false); + // For Mach-O, use an "l" symbol as the atom of this subsection. The label + // difference uses a SUBTRACTOR external relocation which references the + // symbol. + MCSymbol *Dot = Ctx.createLinkerPrivateSymbol("xray_fn_idx"); + OutStreamer->emitLabel(Dot); + OutStreamer->emitValueImpl( + MCBinaryExpr::createSub(MCSymbolRefExpr::create(SledsStart, Ctx), + MCSymbolRefExpr::create(Dot, Ctx), Ctx), + WordSizeBytes); + OutStreamer->emitValueImpl(MCConstantExpr::create(Sleds.size(), Ctx), + WordSizeBytes); OutStreamer->switchSection(PrevSection); } Sleds.clear(); @@ -4041,7 +4155,7 @@ unsigned int AsmPrinter::getDwarfOffsetByteSize() const { } dwarf::FormParams AsmPrinter::getDwarfFormParams() const { - return {getDwarfVersion(), uint8_t(getPointerSize()), + return {getDwarfVersion(), uint8_t(MAI->getCodePointerSize()), OutStreamer->getContext().getDwarfFormat(), doesDwarfUseRelocationsAcrossSections()}; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index ecaa64afab4d..21d0d070c247 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -32,28 +32,6 @@ using namespace llvm; // Dwarf Emission Helper Routines //===----------------------------------------------------------------------===// -/// EmitSLEB128 - emit the specified signed leb128 value. -void AsmPrinter::emitSLEB128(int64_t Value, const char *Desc) const { - if (isVerbose() && Desc) - OutStreamer->AddComment(Desc); - - OutStreamer->emitSLEB128IntValue(Value); -} - -void AsmPrinter::emitULEB128(uint64_t Value, const char *Desc, - unsigned PadTo) const { - if (isVerbose() && Desc) - OutStreamer->AddComment(Desc); - - OutStreamer->emitULEB128IntValue(Value, PadTo); -} - -/// Emit something like ".uleb128 Hi-Lo". -void AsmPrinter::emitLabelDifferenceAsULEB128(const MCSymbol *Hi, - const MCSymbol *Lo) const { - OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); -} - static const char *DecodeDWARFEncoding(unsigned Encoding) { switch (Encoding) { case dwarf::DW_EH_PE_absptr: @@ -130,7 +108,7 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { default: llvm_unreachable("Invalid encoded value."); case dwarf::DW_EH_PE_absptr: - return MF->getDataLayout().getPointerSize(); + return MAI->getCodePointerSize(); case dwarf::DW_EH_PE_udata2: return 2; case dwarf::DW_EH_PE_udata4: @@ -226,58 +204,59 @@ void AsmPrinter::emitCallSiteValue(uint64_t Value, unsigned Encoding) const { //===----------------------------------------------------------------------===// void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { + SMLoc Loc = Inst.getLoc(); switch (Inst.getOperation()) { default: llvm_unreachable("Unexpected instruction"); case MCCFIInstruction::OpDefCfaOffset: - OutStreamer->emitCFIDefCfaOffset(Inst.getOffset()); + OutStreamer->emitCFIDefCfaOffset(Inst.getOffset(), Loc); break; case MCCFIInstruction::OpAdjustCfaOffset: - OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset()); + OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset(), Loc); break; case MCCFIInstruction::OpDefCfa: - OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset()); + OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset(), Loc); break; case MCCFIInstruction::OpDefCfaRegister: - OutStreamer->emitCFIDefCfaRegister(Inst.getRegister()); + OutStreamer->emitCFIDefCfaRegister(Inst.getRegister(), Loc); break; case MCCFIInstruction::OpLLVMDefAspaceCfa: OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(), - Inst.getAddressSpace()); + Inst.getAddressSpace(), Loc); break; case MCCFIInstruction::OpOffset: - OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset()); + OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset(), Loc); break; case MCCFIInstruction::OpRegister: - OutStreamer->emitCFIRegister(Inst.getRegister(), Inst.getRegister2()); + OutStreamer->emitCFIRegister(Inst.getRegister(), Inst.getRegister2(), Loc); break; case MCCFIInstruction::OpWindowSave: - OutStreamer->emitCFIWindowSave(); + OutStreamer->emitCFIWindowSave(Loc); break; case MCCFIInstruction::OpNegateRAState: - OutStreamer->emitCFINegateRAState(); + OutStreamer->emitCFINegateRAState(Loc); break; case MCCFIInstruction::OpSameValue: - OutStreamer->emitCFISameValue(Inst.getRegister()); + OutStreamer->emitCFISameValue(Inst.getRegister(), Loc); break; case MCCFIInstruction::OpGnuArgsSize: - OutStreamer->emitCFIGnuArgsSize(Inst.getOffset()); + OutStreamer->emitCFIGnuArgsSize(Inst.getOffset(), Loc); break; case MCCFIInstruction::OpEscape: OutStreamer->AddComment(Inst.getComment()); - OutStreamer->emitCFIEscape(Inst.getValues()); + OutStreamer->emitCFIEscape(Inst.getValues(), Loc); break; case MCCFIInstruction::OpRestore: - OutStreamer->emitCFIRestore(Inst.getRegister()); + OutStreamer->emitCFIRestore(Inst.getRegister(), Loc); break; case MCCFIInstruction::OpUndefined: - OutStreamer->emitCFIUndefined(Inst.getRegister()); + OutStreamer->emitCFIUndefined(Inst.getRegister(), Loc); break; case MCCFIInstruction::OpRememberState: - OutStreamer->emitCFIRememberState(); + OutStreamer->emitCFIRememberState(Loc); break; case MCCFIInstruction::OpRestoreState: - OutStreamer->emitCFIRestoreState(); + OutStreamer->emitCFIRestoreState(Loc); break; } } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index c1588aaea05e..32674bbeb061 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineBasicBlock.h" diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 0a67c4b6beb6..8161de57b58e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -16,7 +16,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -65,6 +64,7 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cassert> #include <cctype> @@ -488,10 +488,10 @@ void CodeViewDebug::recordLocalVariable(LocalVariable &&Var, // This variable was inlined. Associate it with the InlineSite. const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram(); InlineSite &Site = getInlineSite(InlinedAt, Inlinee); - Site.InlinedLocals.emplace_back(Var); + Site.InlinedLocals.emplace_back(std::move(Var)); } else { // This variable goes into the corresponding lexical scope. - ScopeVariables[LS].emplace_back(Var); + ScopeVariables[LS].emplace_back(std::move(Var)); } } @@ -569,7 +569,6 @@ static SourceLanguage MapDWLangToCVLang(unsigned DWLang) { case dwarf::DW_LANG_C89: case dwarf::DW_LANG_C99: case dwarf::DW_LANG_C11: - case dwarf::DW_LANG_ObjC: return SourceLanguage::C; case dwarf::DW_LANG_C_plus_plus: case dwarf::DW_LANG_C_plus_plus_03: @@ -595,6 +594,10 @@ static SourceLanguage MapDWLangToCVLang(unsigned DWLang) { return SourceLanguage::Swift; case dwarf::DW_LANG_Rust: return SourceLanguage::Rust; + case dwarf::DW_LANG_ObjC: + return SourceLanguage::ObjC; + case dwarf::DW_LANG_ObjC_plus_plus: + return SourceLanguage::ObjCpp; default: // There's no CodeView representation for this language, and CV doesn't // have an "unknown" option for the language field, so we'll use MASM, @@ -788,7 +791,6 @@ void CodeViewDebug::emitObjName() { // Don't emit the filename if we're writing to stdout or to /dev/null. PathRef = {}; } else { - llvm::sys::path::remove_dots(PathStore, /*remove_dot_dot=*/true); PathRef = PathStore; } @@ -1158,7 +1160,14 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.AddComment("Function section index"); OS.emitCOFFSectionIndex(Fn); OS.AddComment("Flags"); - OS.emitInt8(0); + ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo; + if (FI.HasFramePointer) + ProcFlags |= ProcSymFlags::HasFP; + if (GV->hasFnAttribute(Attribute::NoReturn)) + ProcFlags |= ProcSymFlags::IsNoReturn; + if (GV->hasFnAttribute(Attribute::NoInline)) + ProcFlags |= ProcSymFlags::IsNoInline; + OS.emitInt8(static_cast<uint8_t>(ProcFlags)); // 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. @@ -1262,7 +1271,8 @@ void CodeViewDebug::collectVariableInfoFromMFTable( const TargetFrameLowering *TFI = TSI.getFrameLowering(); const TargetRegisterInfo *TRI = TSI.getRegisterInfo(); - for (const MachineFunction::VariableDbgInfo &VI : MF.getVariableDbgInfo()) { + for (const MachineFunction::VariableDbgInfo &VI : + MF.getInStackSlotVariableDbgInfo()) { if (!VI.Var) continue; assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) && @@ -1290,7 +1300,8 @@ void CodeViewDebug::collectVariableInfoFromMFTable( // Get the frame register used and the offset. Register FrameReg; - StackOffset FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg); + StackOffset FrameOffset = + TFI->getFrameIndexReference(*Asm->MF, VI.getStackSlot(), FrameReg); uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg); assert(!FrameOffset.getScalable() && @@ -1476,6 +1487,7 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr; CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr; } else { + CurFn->HasFramePointer = true; // If there is an FP, parameters are always relative to it. CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr; if (CurFn->HasStackRealignment) { @@ -1717,12 +1729,13 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { // Otherwise, if it has an upperboud, use (upperbound - lowerbound + 1), // where lowerbound is from the LowerBound field of the Subrange, // or the language default lowerbound if that field is unspecified. - if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt *>()) + if (auto *CI = dyn_cast_if_present<ConstantInt *>(Subrange->getCount())) Count = CI->getSExtValue(); - else if (auto *UI = Subrange->getUpperBound().dyn_cast<ConstantInt *>()) { + else if (auto *UI = dyn_cast_if_present<ConstantInt *>( + Subrange->getUpperBound())) { // Fortran uses 1 as the default lowerbound; other languages use 0. int64_t Lowerbound = (moduleIsInFortran()) ? 1 : 0; - auto *LI = Subrange->getLowerBound().dyn_cast<ConstantInt *>(); + auto *LI = dyn_cast_if_present<ConstantInt *>(Subrange->getLowerBound()); Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound; Count = UI->getSExtValue() - Lowerbound + 1; } @@ -1793,12 +1806,14 @@ TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) { } break; case dwarf::DW_ATE_complex_float: + // The CodeView size for a complex represents the size of + // an individual component. switch (ByteSize) { - case 2: STK = SimpleTypeKind::Complex16; break; - case 4: STK = SimpleTypeKind::Complex32; break; - case 8: STK = SimpleTypeKind::Complex64; break; - case 10: STK = SimpleTypeKind::Complex80; break; - case 16: STK = SimpleTypeKind::Complex128; break; + case 4: STK = SimpleTypeKind::Complex16; break; + case 8: STK = SimpleTypeKind::Complex32; break; + case 16: STK = SimpleTypeKind::Complex64; break; + case 20: STK = SimpleTypeKind::Complex80; break; + case 32: STK = SimpleTypeKind::Complex128; break; } break; case dwarf::DW_ATE_float: @@ -3279,7 +3294,7 @@ void CodeViewDebug::emitDebugInfoForGlobals() { // Second, emit each global that is in a comdat into its own .debug$S // section along with its own symbol substream. for (const CVGlobalVariable &CVGV : ComdatVariables) { - const GlobalVariable *GV = CVGV.GVInfo.get<const GlobalVariable *>(); + const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo); MCSymbol *GVSym = Asm->getSymbol(GV); OS.AddComment("Symbol subsection for " + Twine(GlobalValue::dropLLVMManglingEscape(GV->getName()))); @@ -3388,7 +3403,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { : getFullyQualifiedName(Scope, DIGV->getName()); if (const GlobalVariable *GV = - CVGV.GVInfo.dyn_cast<const GlobalVariable *>()) { + dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) { // DataSym record, see SymbolRecord.h for more info. Thread local data // happens to have the same format as global data. MCSymbol *GVSym = Asm->getSymbol(GV); @@ -3403,7 +3418,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { OS.AddComment("DataOffset"); uint64_t Offset = 0; - if (CVGlobalVariableOffsets.find(DIGV) != CVGlobalVariableOffsets.end()) + if (CVGlobalVariableOffsets.contains(DIGV)) // Use the offset seen while collecting info on globals. Offset = CVGlobalVariableOffsets[DIGV]; OS.emitCOFFSecRel32(GVSym, Offset); @@ -3415,7 +3430,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord); endSymbolRecord(DataEnd); } else { - const DIExpression *DIE = CVGV.GVInfo.get<const DIExpression *>(); + const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo); assert(DIE->isConstant() && "Global constant variables must contain a constant expression."); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 495822a6e653..1455ac417824 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H #define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" @@ -191,6 +192,8 @@ private: bool HasStackRealignment = false; bool HaveLineInfo = false; + + bool HasFramePointer = false; }; FunctionInfo *CurFn = nullptr; diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index 308d4b1b5d61..619155cafe92 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -173,9 +173,7 @@ void DIEAbbrevSet::Emit(const AsmPrinter *AP, MCSection *Section) const { // DIE Implementation //===----------------------------------------------------------------------===// -DIE *DIE::getParent() const { - return Owner.dyn_cast<DIE*>(); -} +DIE *DIE::getParent() const { return dyn_cast_if_present<DIE *>(Owner); } DIEAbbrev DIE::generateAbbrev() const { DIEAbbrev Abbrev(Tag, hasChildren()); @@ -209,7 +207,7 @@ const DIE *DIE::getUnitDie() const { DIEUnit *DIE::getUnit() const { const DIE *UnitDie = getUnitDie(); if (UnitDie) - return UnitDie->Owner.dyn_cast<DIEUnit*>(); + return dyn_cast_if_present<DIEUnit *>(UnitDie->Owner); return nullptr; } @@ -385,6 +383,7 @@ void DIEInteger::emitValue(const AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_strx2: case dwarf::DW_FORM_addrx2: case dwarf::DW_FORM_strx3: + case dwarf::DW_FORM_addrx3: case dwarf::DW_FORM_strp: case dwarf::DW_FORM_ref4: case dwarf::DW_FORM_data4: diff --git a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 0b40cdb0c3cc..55a0afcf7a33 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -138,6 +138,9 @@ void DbgValueHistoryMap::trimLocationRanges( // references if any entries are removed. SmallVector<size_t, 4> Offsets; + LLVM_DEBUG(dbgs() << "Trimming location ranges for function '" << MF.getName() + << "'\n"); + for (auto &Record : VarEntries) { auto &HistoryMapEntries = Record.second; if (HistoryMapEntries.empty()) @@ -213,6 +216,8 @@ void DbgValueHistoryMap::trimLocationRanges( // count of the closing entry, if one exists. if (EndIndex != NoEntry) ReferenceCount[EndIndex] -= 1; + LLVM_DEBUG(dbgs() << "Dropping value outside scope range of variable: "; + StartMI->print(llvm::dbgs());); } } @@ -253,6 +258,8 @@ void DbgValueHistoryMap::trimLocationRanges( // ToRemove indices are valid after each erase. for (EntryIndex Idx : llvm::reverse(ToRemove)) HistoryMapEntries.erase(HistoryMapEntries.begin() + Idx); + LLVM_DEBUG(llvm::dbgs() << "New HistoryMap('" << LocalVar->getName() + << "') size: " << HistoryMapEntries.size() << "\n"); } } @@ -555,8 +562,8 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const { - dbgs() << "DbgValueHistoryMap:\n"; +LLVM_DUMP_METHOD void DbgValueHistoryMap::dump(StringRef FuncName) const { + dbgs() << "DbgValueHistoryMap('" << FuncName << "'):\n"; for (const auto &VarRangePair : *this) { const InlinedEntity &Var = VarRangePair.first; const Entries &Entries = VarRangePair.second; diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index 858a3e75e515..eb2d992c7e75 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -223,6 +223,7 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) { Encoding == dwarf::DW_ATE_signed_char || Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean || + Encoding == dwarf::DW_ATE_complex_float || (Ty->getTag() == dwarf::DW_TAG_unspecified_type && Ty->getName() == "decltype(nullptr)")) && "Unsupported encoding"); @@ -273,7 +274,7 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) { InstOrdering.initialize(*MF); if (TrimVarLocs) DbgValues.trimLocationRanges(*MF, LScopes, InstOrdering); - LLVM_DEBUG(DbgValues.dump()); + LLVM_DEBUG(DbgValues.dump(MF->getName())); // Request labels for the full history. for (const auto &I : DbgValues) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index 2008aa39ff87..726aba18bb80 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -126,7 +126,7 @@ public: : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()), IsVariadic(IsVariadic) { #ifndef NDEBUG - assert(cast<DIExpression>(Expr)->isValid() || + assert(Expr->isValid() || !any_of(Locs, [](auto LE) { return LE.isLocation(); })); if (!IsVariadic) { assert(ValueLocEntries.size() == 1); diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h index 0515173b4a24..a96bdd034918 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h @@ -49,7 +49,7 @@ private: SmallVector<Entry, 32> Entries; SmallString<256> DWARFBytes; std::vector<std::string> Comments; - MCSymbol *Sym; + MCSymbol *Sym = nullptr; /// Only verbose textual output needs comments. This will be set to /// true for that case, and false otherwise. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index df4fe8d49806..10c844ddb14a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -94,7 +94,7 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) { shouldEmitCFI = MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); else - shouldEmitCFI = Asm->needsCFIForDebug() && shouldEmitMoves; + shouldEmitCFI = Asm->usesCFIWithoutEH() && shouldEmitMoves; } void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 6dde50375a60..58ed21379d29 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -266,7 +267,7 @@ void DwarfCompileUnit::addLocationAttribute( // 16-bit platforms like MSP430 and AVR take this path, so sink this // assert to platforms that use it. auto GetPointerSizedFormAndOp = [this]() { - unsigned PointerSize = Asm->getDataLayout().getPointerSize(); + unsigned PointerSize = Asm->MAI->getCodePointerSize(); assert((PointerSize == 4 || PointerSize == 8) && "Add support for other sizes if necessary"); struct FormAndOp { @@ -278,7 +279,16 @@ void DwarfCompileUnit::addLocationAttribute( : FormAndOp{dwarf::DW_FORM_data8, dwarf::DW_OP_const8u}; }; if (Global->isThreadLocal()) { - if (Asm->TM.useEmulatedTLS()) { + if (Asm->TM.getTargetTriple().isWasm()) { + // FIXME This is not guaranteed, but in practice, in static linking, + // if present, __tls_base's index is 1. This doesn't hold for dynamic + // linking, so TLS variables used in dynamic linking won't have + // correct debug info for now. See + // https://github.com/llvm/llvm-project/blob/19afbfe33156d211fa959dadeea46cd17b9c723c/lld/wasm/Driver.cpp#L786-L823 + addWasmRelocBaseGlobal(Loc, "__tls_base", 1); + addOpAddress(*Loc, Sym); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + } else if (Asm->TM.useEmulatedTLS()) { // TODO: add debug info for emulated thread local mode. } else { // FIXME: Make this work with -gsplit-dwarf. @@ -301,6 +311,14 @@ void DwarfCompileUnit::addLocationAttribute( DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address : dwarf::DW_OP_form_tls_address); } + } else if (Asm->TM.getTargetTriple().isWasm() && + Asm->TM.getRelocationModel() == Reloc::PIC_) { + // FIXME This is not guaranteed, but in practice, if present, + // __memory_base's index is 1. See + // https://github.com/llvm/llvm-project/blob/19afbfe33156d211fa959dadeea46cd17b9c723c/lld/wasm/Driver.cpp#L786-L823 + addWasmRelocBaseGlobal(Loc, "__memory_base", 1); + addOpAddress(*Loc, Sym); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); } else if ((Asm->TM.getRelocationModel() == Reloc::RWPI || Asm->TM.getRelocationModel() == Reloc::ROPI_RWPI) && !Asm->getObjFileLowering() @@ -449,6 +467,39 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { return ContextCU->updateSubprogramScopeDIEImpl(SP, SPDie); } +// Add info for Wasm-global-based relocation. +// 'GlobalIndex' is used for split dwarf, which currently relies on a few +// assumptions that are not guaranteed in a formal way but work in practice. +void DwarfCompileUnit::addWasmRelocBaseGlobal(DIELoc *Loc, StringRef GlobalName, + uint64_t GlobalIndex) { + // 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; + unsigned PointerSize = Asm->getDataLayout().getPointerSize(); + auto *Sym = cast<MCSymbolWasm>(Asm->GetExternalSymbolSymbol(GlobalName)); + // FIXME: this repeats what WebAssemblyMCInstLower:: + // GetExternalSymbolSymbol does, since if there's no code that + // refers to this symbol, we have to set it here. + Sym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); + Sym->setGlobalType(wasm::WasmGlobalType{ + static_cast<uint8_t>(PointerSize == 4 ? wasm::WASM_TYPE_I32 + : wasm::WASM_TYPE_I64), + true}); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_WASM_location); + addSInt(*Loc, dwarf::DW_FORM_sdata, TI_GLOBAL_RELOC); + if (!isDwoUnit()) { + addLabel(*Loc, dwarf::DW_FORM_data4, Sym); + } else { + // FIXME: when writing dwo, we need to avoid relocations. Probably + // the "right" solution is to treat globals the way func and data + // symbols are (with entries in .debug_addr). + // For now we hardcode the indices in the callsites. Global indices are not + // fixed, but in practice a few are fixed; for example, __stack_pointer is + // always index 0. + addUInt(*Loc, dwarf::DW_FORM_data4, GlobalIndex); + } +} + DIE &DwarfCompileUnit::updateSubprogramScopeDIEImpl(const DISubprogram *SP, DIE *SPDie) { SmallVector<RangeSpan, 2> BB_List; @@ -480,40 +531,24 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIEImpl(const DISubprogram *SP, case TargetFrameLowering::DwarfFrameBase::CFA: { DIELoc *Loc = new (DIEValueAllocator) DIELoc; addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa); + if (FrameBase.Location.Offset != 0) { + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_consts); + addSInt(*Loc, dwarf::DW_FORM_sdata, FrameBase.Location.Offset); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + } addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc); 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, TI_GLOBAL_RELOC); - if (!isDwoUnit()) { - addLabel(*Loc, dwarf::DW_FORM_data4, SPSym); - } else { - // FIXME: when writing dwo, we need to avoid relocations. Probably - // the "right" solution is to treat globals the way func and data - // symbols are (with entries in .debug_addr). - // For now, since we only ever use index 0, this should work as-is. - addUInt(*Loc, dwarf::DW_FORM_data4, FrameBase.Location.WasmLoc.Index); - } + assert(FrameBase.Location.WasmLoc.Index == 0); // Only SP so far. + // For now, since we only ever use index 0, this should work as-is. + addWasmRelocBaseGlobal(Loc, "__stack_pointer", + FrameBase.Location.WasmLoc.Index); addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc); } else { @@ -608,7 +643,7 @@ void DwarfCompileUnit::attachRangesOrLowHighPC( assert(!Ranges.empty()); if (!DD->useRangesSection() || (Ranges.size() == 1 && - (!DD->alwaysUseRanges() || + (!DD->alwaysUseRanges(*this) || DD->getSectionLabel(&Ranges.front().Begin->getSection()) == Ranges.front().Begin))) { const RangeSpan &Front = Ranges.front(); @@ -659,7 +694,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope, auto *InlinedSP = getDISubprogram(DS); // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram // was inlined from another compile unit. - DIE *OriginDIE = getAbstractSPDies()[InlinedSP]; + DIE *OriginDIE = getAbstractScopeDIEs()[InlinedSP]; assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine); @@ -691,10 +726,20 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope, DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) { if (DD->isLexicalScopeDIENull(Scope)) return nullptr; + const auto *DS = Scope->getScopeNode(); auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); - if (Scope->isAbstractScope()) + if (Scope->isAbstractScope()) { + assert(!getAbstractScopeDIEs().count(DS) && + "Abstract DIE for this scope exists!"); + getAbstractScopeDIEs()[DS] = ScopeDIE; return ScopeDIE; + } + if (!Scope->getInlinedAt()) { + assert(!LexicalBlockDIEs.count(DS) && + "Concrete out-of-line DIE for this scope exists!"); + LexicalBlockDIEs[DS] = ScopeDIE; + } attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); @@ -929,29 +974,29 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) { for (auto *El : Array->getElements()) { if (auto *Subrange = dyn_cast<DISubrange>(El)) { if (auto Count = Subrange->getCount()) - if (auto *Dependency = Count.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Count)) Result.push_back(Dependency); if (auto LB = Subrange->getLowerBound()) - if (auto *Dependency = LB.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(LB)) Result.push_back(Dependency); if (auto UB = Subrange->getUpperBound()) - if (auto *Dependency = UB.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(UB)) Result.push_back(Dependency); if (auto ST = Subrange->getStride()) - if (auto *Dependency = ST.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(ST)) Result.push_back(Dependency); } else if (auto *GenericSubrange = dyn_cast<DIGenericSubrange>(El)) { if (auto Count = GenericSubrange->getCount()) - if (auto *Dependency = Count.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Count)) Result.push_back(Dependency); if (auto LB = GenericSubrange->getLowerBound()) - if (auto *Dependency = LB.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(LB)) Result.push_back(Dependency); if (auto UB = GenericSubrange->getUpperBound()) - if (auto *Dependency = UB.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(UB)) Result.push_back(Dependency); if (auto ST = GenericSubrange->getStride()) - if (auto *Dependency = ST.dyn_cast<DIVariable *>()) + if (auto *Dependency = dyn_cast_if_present<DIVariable *>(ST)) Result.push_back(Dependency); } } @@ -1062,35 +1107,35 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, for (DbgVariable *DV : Locals) ScopeDIE.addChild(constructVariableDIE(*DV, *Scope, ObjectPointer)); - // Emit imported entities (skipped in gmlt-like data). - if (!includeMinimalInlineScopes()) { - for (const auto *IE : ImportedEntities[Scope->getScopeNode()]) - ScopeDIE.addChild(constructImportedEntityDIE(cast<DIImportedEntity>(IE))); - } - // Emit labels. for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope)) ScopeDIE.addChild(constructLabelDIE(*DL, *Scope)); + // Track other local entities (skipped in gmlt-like data). + // This creates mapping between CU and a set of local declarations that + // should be emitted for subprograms in this CU. + if (!includeMinimalInlineScopes() && !Scope->getInlinedAt()) { + auto &LocalDecls = DD->getLocalDeclsForScope(Scope->getScopeNode()); + DeferredLocalDecls.insert(LocalDecls.begin(), LocalDecls.end()); + } + // Emit inner lexical scopes. - auto needToEmitLexicalScope = [this](LexicalScope *LS) { - if (isa<DISubprogram>(LS->getScopeNode())) - return true; - auto Vars = DU->getScopeVariables().lookup(LS); + auto skipLexicalScope = [this](LexicalScope *S) -> bool { + if (isa<DISubprogram>(S->getScopeNode())) + return false; + auto Vars = DU->getScopeVariables().lookup(S); if (!Vars.Args.empty() || !Vars.Locals.empty()) - return true; - if (!includeMinimalInlineScopes() && - !ImportedEntities[LS->getScopeNode()].empty()) - return true; - return false; + return false; + return includeMinimalInlineScopes() || + DD->getLocalDeclsForScope(S->getScopeNode()).empty(); }; for (LexicalScope *LS : Scope->getChildren()) { // If the lexical block doesn't have non-scope children, skip // its emission and put its children directly to the parent scope. - if (needToEmitLexicalScope(LS)) - constructScopeDIE(LS, ScopeDIE); - else + if (skipLexicalScope(LS)) createAndAddScopeChildren(LS, ScopeDIE); + else + constructScopeDIE(LS, ScopeDIE); } return ObjectPointer; @@ -1098,11 +1143,9 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( LexicalScope *Scope) { - DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()]; - if (AbsDef) - return; - auto *SP = cast<DISubprogram>(Scope->getScopeNode()); + if (getAbstractScopeDIEs().count(SP)) + return; DIE *ContextDIE; DwarfCompileUnit *ContextCU = this; @@ -1126,14 +1169,19 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( // Passing null as the associated node because the abstract definition // shouldn't be found by lookup. - AbsDef = &ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr); - ContextCU->applySubprogramAttributesToDefinition(SP, *AbsDef); - ContextCU->addSInt(*AbsDef, dwarf::DW_AT_inline, + DIE &AbsDef = ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, + *ContextDIE, nullptr); + + // Store the DIE before creating children. + ContextCU->getAbstractScopeDIEs()[SP] = &AbsDef; + + ContextCU->applySubprogramAttributesToDefinition(SP, AbsDef); + ContextCU->addSInt(AbsDef, dwarf::DW_AT_inline, DD->getDwarfVersion() <= 4 ? std::optional<dwarf::Form>() : dwarf::DW_FORM_implicit_const, dwarf::DW_INL_inlined); - if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef)) - ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); + if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, AbsDef)) + ContextCU->addDIEEntry(AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const { @@ -1277,21 +1325,37 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE( EntityDie = getOrCreateNameSpace(NS); else if (auto *M = dyn_cast<DIModule>(Entity)) EntityDie = getOrCreateModule(M); - else if (auto *SP = dyn_cast<DISubprogram>(Entity)) - EntityDie = getOrCreateSubprogramDIE(SP); - else if (auto *T = dyn_cast<DIType>(Entity)) + else if (auto *SP = dyn_cast<DISubprogram>(Entity)) { + // If there is an abstract subprogram, refer to it. Note that this assumes + // that all the abstract subprograms have been already created (which is + // correct until imported entities get emitted in DwarfDebug::endModule()). + if (auto *AbsSPDie = getAbstractScopeDIEs().lookup(SP)) + EntityDie = AbsSPDie; + else + EntityDie = getOrCreateSubprogramDIE(SP); + } else if (auto *T = dyn_cast<DIType>(Entity)) EntityDie = getOrCreateTypeDIE(T); else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity)) EntityDie = getOrCreateGlobalVariableDIE(GV, {}); + else if (auto *IE = dyn_cast<DIImportedEntity>(Entity)) + EntityDie = getOrCreateImportedEntityDIE(IE); else EntityDie = getDIE(Entity); assert(EntityDie); addSourceLine(*IMDie, Module->getLine(), Module->getFile()); addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); StringRef Name = Module->getName(); - if (!Name.empty()) + if (!Name.empty()) { addString(*IMDie, dwarf::DW_AT_name, Name); + // FIXME: if consumers ever start caring about handling + // unnamed import declarations such as `using ::nullptr_t` + // or `using namespace std::ranges`, we could add the + // import declaration into the accelerator table with the + // name being the one of the entity being imported. + DD->addAccelNamespace(*CUNode, Name, *IMDie); + } + // This is for imported module with renamed entities (such as variables and // subprograms). DINodeArray Elements = Module->getElements(); @@ -1305,9 +1369,24 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE( return IMDie; } +DIE *DwarfCompileUnit::getOrCreateImportedEntityDIE( + const DIImportedEntity *IE) { + + // Check for pre-existence. + if (DIE *Die = getDIE(IE)) + return Die; + + DIE *ContextDIE = getOrCreateContextDIE(IE->getScope()); + assert(ContextDIE && "Empty scope for the imported entity!"); + + DIE *IMDie = constructImportedEntityDIE(IE); + ContextDIE->addChild(IMDie); + return IMDie; +} + void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) { DIE *D = getDIE(SP); - if (DIE *AbsSPDIE = getAbstractSPDies().lookup(SP)) { + if (DIE *AbsSPDIE = getAbstractScopeDIEs().lookup(SP)) { if (D) // If this subprogram has an abstract definition, reference that addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); @@ -1356,8 +1435,8 @@ void DwarfCompileUnit::createAbstractEntity(const DINode *Node, assert(Scope && Scope->isAbstractScope()); auto &Entity = getAbstractEntities()[Node]; if (isa<const DILocalVariable>(Node)) { - Entity = std::make_unique<DbgVariable>( - cast<const DILocalVariable>(Node), nullptr /* IA */);; + Entity = std::make_unique<DbgVariable>(cast<const DILocalVariable>(Node), + nullptr /* IA */); DU->addScopeVariable(Scope, cast<DbgVariable>(Entity.get())); } else if (isa<const DILabel>(Node)) { Entity = std::make_unique<DbgLabel>( @@ -1389,6 +1468,8 @@ bool DwarfCompileUnit::hasDwarfPubSections() const { // generated for things like Gold's gdb_index generation. case DICompileUnit::DebugNameTableKind::GNU: return true; + case DICompileUnit::DebugNameTableKind::Apple: + return false; case DICompileUnit::DebugNameTableKind::Default: return DD->tuneForGDB() && !includeMinimalInlineScopes() && !CUNode->isDebugDirectivesOnly() && @@ -1599,3 +1680,29 @@ void DwarfCompileUnit::createBaseTypeDIEs() { Btr.Die = &Die; } } + +DIE *DwarfCompileUnit::getLexicalBlockDIE(const DILexicalBlock *LB) { + // Assume if there is an abstract tree all the DIEs are already emitted. + bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram()); + if (isAbstract && getAbstractScopeDIEs().count(LB)) + return getAbstractScopeDIEs()[LB]; + assert(!isAbstract && "Missed lexical block DIE in abstract tree!"); + + // Return a concrete DIE if it exists or nullptr otherwise. + return LexicalBlockDIEs.lookup(LB); +} + +DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) { + if (isa_and_nonnull<DILocalScope>(Context)) { + if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Context)) + Context = LFScope->getNonLexicalBlockFileScope(); + if (auto *LScope = dyn_cast<DILexicalBlock>(Context)) + return getLexicalBlockDIE(LScope); + + // Otherwise the context must be a DISubprogram. + auto *SPScope = cast<DISubprogram>(Context); + if (getAbstractScopeDIEs().count(SPScope)) + return getAbstractScopeDIEs()[SPScope]; + } + return DwarfUnit::getOrCreateContextDIE(Context); +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 7d87f35021bb..6ef73ebd4f7f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -61,11 +61,6 @@ class DwarfCompileUnit final : public DwarfUnit { /// The start of the unit macro info within macro section. MCSymbol *MacroLabelBegin; - using ImportedEntityList = SmallVector<const MDNode *, 8>; - using ImportedEntityMap = DenseMap<const MDNode *, ImportedEntityList>; - - ImportedEntityMap ImportedEntities; - /// GlobalNames - A map of globally visible named entities for this unit. StringMap<const DIE *> GlobalNames; @@ -79,7 +74,20 @@ class DwarfCompileUnit final : public DwarfUnit { // ranges/locs. const MCSymbol *BaseAddress = nullptr; - DenseMap<const MDNode *, DIE *> AbstractSPDies; + using MDNodeSetVector = + SetVector<const MDNode *, SmallVector<const MDNode *, 4>, + SmallPtrSet<const MDNode *, 4>>; + + // List of entities (either static locals, types or imports) that + // belong to subprograms within this CU. + MDNodeSetVector DeferredLocalDecls; + + // List of concrete lexical block scopes belong to subprograms within this CU. + DenseMap<const DILocalScope *, DIE *> LexicalBlockDIEs; + + // List of abstract local scopes (either DISubprogram or DILexicalBlock). + DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs; + DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities; /// DWO ID for correlating skeleton and split units. @@ -94,10 +102,10 @@ class DwarfCompileUnit final : public DwarfUnit { bool isDwoUnit() const override; - DenseMap<const MDNode *, DIE *> &getAbstractSPDies() { + DenseMap<const DILocalScope *, DIE *> &getAbstractScopeDIEs() { if (isDwoUnit() && !DD->shareAcrossDWOCUs()) - return AbstractSPDies; - return DU->getAbstractSPDies(); + return AbstractLocalScopeDIEs; + return DU->getAbstractScopeDIEs(); } DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() { @@ -108,6 +116,10 @@ class DwarfCompileUnit final : public DwarfUnit { void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override; + /// Add info for Wasm-global-based relocation. + void addWasmRelocBaseGlobal(DIELoc *Loc, StringRef GlobalName, + uint64_t GlobalIndex); + public: DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, @@ -171,17 +183,6 @@ public: unsigned getOrCreateSourceID(const DIFile *File) override; - void addImportedEntity(const DIImportedEntity* IE) { - DIScope *Scope = IE->getScope(); - assert(Scope && "Invalid Scope encoding!"); - if (!isa<DILocalScope>(Scope)) - // No need to add imported enities that are not local declaration. - return; - - auto *LocalScope = cast<DILocalScope>(Scope)->getNonLexicalBlockFileScope(); - ImportedEntities[LocalScope].push_back(IE); - } - /// addRange - Add an address range to the list of ranges for this unit. void addRange(RangeSpan Range); @@ -213,6 +214,11 @@ public: /// attach DW_AT_low_pc/DW_AT_high_pc labels. DIE *constructLexicalScopeDIE(LexicalScope *Scope); + /// Get a DIE for the given DILexicalBlock. + /// Note that this function assumes that the DIE has been already created + /// and it's an error, if it hasn't. + DIE *getLexicalBlockDIE(const DILexicalBlock *LB); + /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false); @@ -224,6 +230,10 @@ public: void createBaseTypeDIEs(); + /// Construct a DIE for a given scope. + /// This instance of 'getOrCreateContextDIE()' can handle DILocalScope. + DIE *getOrCreateContextDIE(const DIScope *Ty) override; + /// Construct a DIE for this subprogram scope. DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope); @@ -262,8 +272,9 @@ public: void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE, SmallVector<DbgCallSiteParam, 4> &Params); - /// Construct import_module DIE. - DIE *constructImportedEntityDIE(const DIImportedEntity *Module); + /// Get or create a DIE for an imported entity. + DIE *getOrCreateImportedEntityDIE(const DIImportedEntity *IE); + DIE *constructImportedEntityDIE(const DIImportedEntity *IE); void finishSubprogramDefinition(const DISubprogram *SP); void finishEntityDefinition(const DbgEntity *Entity); @@ -360,6 +371,8 @@ public: bool hasDwarfPubSections() const; void addBaseTypeRef(DIEValueList &Die, int64_t Idx); + + MDNodeSetVector &getDeferredLocalDecls() { return DeferredLocalDecls; } }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index cde790cc77fb..1ae17ec9b874 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -18,7 +18,7 @@ #include "DwarfUnit.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/Triple.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" @@ -53,6 +53,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cstddef> #include <iterator> @@ -452,14 +453,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A) // Split DWARF would benefit object size significantly by trading reductions // in address pool usage for slightly increased range list encodings. - if (DwarfVersion >= 5) { + if (DwarfVersion >= 5) MinimizeAddr = MinimizeAddrInV5Option; - // FIXME: In the future, enable this by default for Split DWARF where the - // tradeoff is more pronounced due to being able to offload the range - // lists to the dwo file and shrink object files/reduce relocations there. - if (MinimizeAddr == MinimizeAddrInV5::Default) - MinimizeAddr = MinimizeAddrInV5::Disabled; - } Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); Asm->OutStreamer->getContext().setDwarfFormat(Dwarf64 ? dwarf::DWARF64 @@ -500,6 +495,7 @@ static StringRef getObjCMethodName(StringRef In) { void DwarfDebug::addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP, DIE &Die) { if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Apple && CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) return; @@ -513,7 +509,7 @@ void DwarfDebug::addSubprogramNames(const DICompileUnit &CU, // well into the name table. Only do that if we are going to actually emit // that name. if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() && - (useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP))) + (useAllLinkageNames() || InfoHolder.getAbstractScopeDIEs().lookup(SP))) addAccelName(CU, SP->getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator @@ -710,13 +706,13 @@ static void interpretValues(const MachineInstr *CurMI, if (MI.isDebugInstr()) return; - for (const MachineOperand &MO : MI.operands()) { - if (MO.isReg() && MO.isDef() && MO.getReg().isPhysical()) { + for (const MachineOperand &MO : MI.all_defs()) { + if (MO.getReg().isPhysical()) { for (auto &FwdReg : ForwardedRegWorklist) if (TRI.regsOverlap(FwdReg.first, MO.getReg())) Defs.insert(FwdReg.first); - for (MCRegUnitIterator Units(MO.getReg(), &TRI); Units.isValid(); ++Units) - NewClobberedRegUnits.insert(*Units); + for (MCRegUnit Unit : TRI.regunits(MO.getReg())) + NewClobberedRegUnits.insert(Unit); } } }; @@ -1050,11 +1046,11 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, 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()) - NewCU.addStringOffsetsStart(); - if (!useSplitDwarf()) { + // Add DW_str_offsets_base to the unit DIE, except for split units. + if (useSegmentedStringOffsetsTable()) + NewCU.addStringOffsetsStart(); + NewCU.initStmtList(); // If we're using split dwarf the compilation dir is going to be in the @@ -1097,6 +1093,13 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { if (auto *CU = CUMap.lookup(DIUnit)) return *CU; + if (useSplitDwarf() && + !shareAcrossDWOCUs() && + (!DIUnit->getSplitDebugInlining() || + DIUnit->getEmissionKind() == DICompileUnit::FullDebug) && + !CUMap.empty()) { + return *CUMap.begin()->second; + } CompilationDir = DIUnit->getDirectory(); auto OwnedUnit = std::make_unique<DwarfCompileUnit>( @@ -1104,9 +1107,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { DwarfCompileUnit &NewCU = *OwnedUnit; InfoHolder.addUnit(std::move(OwnedUnit)); - for (auto *IE : DIUnit->getImportedEntities()) - NewCU.addImportedEntity(IE); - // LTO with assembly output shares a single line table amongst multiple CUs. // To avoid the compilation directory being ambiguous, let the line table // explicitly describe the directory of all files, never relying on the @@ -1129,14 +1129,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { return NewCU; } -void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity *N) { - if (isa<DILocalScope>(N->getScope())) - return; - if (DIE *D = TheCU.getOrCreateContextDIE(N->getScope())) - D->addChild(TheCU.constructImportedEntityDIE(N)); -} - /// Sort and unique GVEs by comparing their fragment offset. static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> & sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) { @@ -1214,16 +1206,8 @@ void DwarfDebug::beginModule(Module *M) { DebugLocs.setSym(Asm->createTempSymbol("loclists_table_base")); for (DICompileUnit *CUNode : M->debug_compile_units()) { - // FIXME: Move local imported entities into a list attached to the - // subprogram, then this search won't be needed and a - // getImportedEntities().empty() test should go below with the rest. - bool HasNonLocalImportedEntities = llvm::any_of( - CUNode->getImportedEntities(), [](const DIImportedEntity *IE) { - return !isa<DILocalScope>(IE->getScope()); - }); - - if (!HasNonLocalImportedEntities && CUNode->getEnumTypes().empty() && - CUNode->getRetainedTypes().empty() && + if (CUNode->getImportedEntities().empty() && + CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() && CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty()) continue; @@ -1257,10 +1241,6 @@ void DwarfDebug::beginModule(Module *M) { // There is no point in force-emitting a forward declaration. CU.getOrCreateTypeDIE(RT); } - // Emit imported_modules last so that the relevant context is already - // available. - for (auto *IE : CUNode->getImportedEntities()) - constructAndAddImportedEntityDIE(CU, IE); } } @@ -1300,6 +1280,8 @@ void DwarfDebug::finalizeModuleInfo() { if (CUMap.size() > 1) DWOName = Asm->TM.Options.MCOptions.SplitDwarfFile; + bool HasEmittedSplitCU = false; + // Handle anything that needs to be done on a per-unit basis after // all other generation. for (const auto &P : CUMap) { @@ -1318,6 +1300,10 @@ void DwarfDebug::finalizeModuleInfo() { bool HasSplitUnit = SkCU && !TheCU.getUnitDie().children().empty(); if (HasSplitUnit) { + (void)HasEmittedSplitCU; + assert((shareAcrossDWOCUs() || !HasEmittedSplitCU) && + "Multiple CUs emitted into a single dwo file"); + HasEmittedSplitCU = true; dwarf::Attribute attrDWOName = getDwarfVersion() >= 5 ? dwarf::DW_AT_dwo_name : dwarf::DW_AT_GNU_dwo_name; @@ -1377,11 +1363,10 @@ void DwarfDebug::finalizeModuleInfo() { if (U.hasRangeLists()) U.addRnglistsBase(); - if (!DebugLocs.getLists().empty()) { - if (!useSplitDwarf()) - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base, - DebugLocs.getSym(), - TLOF.getDwarfLoclistsSection()->getBeginSymbol()); + if (!DebugLocs.getLists().empty() && !useSplitDwarf()) { + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base, + DebugLocs.getSym(), + TLOF.getDwarfLoclistsSection()->getBeginSymbol()); } } @@ -1436,8 +1421,24 @@ void DwarfDebug::endModule() { assert(CurMI == nullptr); for (const auto &P : CUMap) { - auto &CU = *P.second; - CU.createBaseTypeDIEs(); + const auto *CUNode = cast<DICompileUnit>(P.first); + DwarfCompileUnit *CU = &*P.second; + + // Emit imported entities. + for (auto *IE : CUNode->getImportedEntities()) { + assert(!isa_and_nonnull<DILocalScope>(IE->getScope()) && + "Unexpected function-local entity in 'imports' CU field."); + CU->getOrCreateImportedEntityDIE(IE); + } + for (const auto *D : CU->getDeferredLocalDecls()) { + if (auto *IE = dyn_cast<DIImportedEntity>(D)) + CU->getOrCreateImportedEntityDIE(IE); + else + llvm_unreachable("Unexpected local retained node!"); + } + + // Emit base types. + CU->createBaseTypeDIEs(); } // If we aren't actually generating debug info (check beginModule - @@ -1511,16 +1512,6 @@ void DwarfDebug::endModule() { // FIXME: AbstractVariables.clear(); } -void DwarfDebug::ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, - const DINode *Node, - const MDNode *ScopeNode) { - if (CU.getExistingAbstractEntity(Node)) - return; - - CU.createAbstractEntity(Node, LScopes.getOrCreateAbstractScope( - cast<DILocalScope>(ScopeNode))); -} - void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, const DINode *Node, const MDNode *ScopeNode) { if (CU.getExistingAbstractEntity(Node)) @@ -1531,6 +1522,21 @@ void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, CU.createAbstractEntity(Node, Scope); } +static const DILocalScope *getRetainedNodeScope(const MDNode *N) { + const DIScope *S; + if (const auto *LV = dyn_cast<DILocalVariable>(N)) + S = LV->getScope(); + else if (const auto *L = dyn_cast<DILabel>(N)) + S = L->getScope(); + else if (const auto *IE = dyn_cast<DIImportedEntity>(N)) + S = IE->getScope(); + else + llvm_unreachable("Unexpected retained node!"); + + // Ensure the scope is not a DILexicalBlockFile. + return cast<DILocalScope>(S)->getNonLexicalBlockFileScope(); +} + // Collect variable information from side table maintained by MF. void DwarfDebug::collectVariableInfoFromMFTable( DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) { @@ -1556,13 +1562,24 @@ void DwarfDebug::collectVariableInfoFromMFTable( ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode()); auto RegVar = std::make_unique<DbgVariable>( cast<DILocalVariable>(Var.first), Var.second); - RegVar->initializeMMI(VI.Expr, VI.Slot); + if (VI.inStackSlot()) + RegVar->initializeMMI(VI.Expr, VI.getStackSlot()); + else { + MachineLocation MLoc(VI.getEntryValueRegister(), /*IsIndirect*/ true); + auto LocEntry = DbgValueLocEntry(MLoc); + RegVar->initializeDbgValue(DbgValueLoc(VI.Expr, LocEntry)); + } 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())) { + if (DbgVariable *DbgVar = MFVars.lookup(Var)) { + if (DbgVar->getValueLoc()) + LLVM_DEBUG(dbgs() << "Dropping repeated entry value debug info for " + "variable " + << VI.Var->getName() << "\n"); + else + DbgVar->addMMIEntry(*RegVar); + } else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) { MFVars.insert({Var, RegVar.get()}); ConcreteEntities.push_back(std::move(RegVar)); } @@ -1964,19 +1981,18 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym); } - // Collect info for variables/labels that were optimized out. + // Collect info for retained nodes. for (const DINode *DN : SP->getRetainedNodes()) { - if (!Processed.insert(InlinedEntity(DN, nullptr)).second) - continue; - LexicalScope *Scope = nullptr; - if (auto *DV = dyn_cast<DILocalVariable>(DN)) { - Scope = LScopes.findLexicalScope(DV->getScope()); - } else if (auto *DL = dyn_cast<DILabel>(DN)) { - Scope = LScopes.findLexicalScope(DL->getScope()); + const auto *LS = getRetainedNodeScope(DN); + if (isa<DILocalVariable>(DN) || isa<DILabel>(DN)) { + if (!Processed.insert(InlinedEntity(DN, nullptr)).second) + continue; + LexicalScope *LexS = LScopes.findLexicalScope(LS); + if (LexS) + createConcreteEntity(TheCU, *LexS, DN, nullptr); + } else { + LocalDeclsPerLS[LS].insert(DN); } - - if (Scope) - createConcreteEntity(TheCU, *Scope, DN, nullptr); } } @@ -2046,7 +2062,10 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { unsigned LastAsmLine = Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine(); - if (DL == PrevInstLoc) { + bool PrevInstInSameSection = + (!PrevInstBB || + PrevInstBB->getSectionIDNum() == MI->getParent()->getSectionIDNum()); + if (DL == PrevInstLoc && PrevInstInSameSection) { // If we have an ongoing unspecified location, nothing to do here. if (!DL) return; @@ -2114,25 +2133,35 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { PrevInstLoc = DL; } -static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { +static std::pair<DebugLoc, bool> findPrologueEndLoc(const MachineFunction *MF) { // First known non-DBG_VALUE and non-frame setup location marks // the beginning of the function body. DebugLoc LineZeroLoc; + const Function &F = MF->getFunction(); + + // Some instructions may be inserted into prologue after this function. Must + // keep prologue for these cases. + bool IsEmptyPrologue = + !(F.hasPrologueData() || F.getMetadata(LLVMContext::MD_func_sanitize)); for (const auto &MBB : *MF) { for (const auto &MI : MBB) { - if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) && - MI.getDebugLoc()) { - // Scan forward to try to find a non-zero line number. The prologue_end - // marks the first breakpoint in the function after the frame setup, and - // a compiler-generated line 0 location is not a meaningful breakpoint. - // If none is found, return the first location after the frame setup. - if (MI.getDebugLoc().getLine()) - return MI.getDebugLoc(); - LineZeroLoc = MI.getDebugLoc(); + if (!MI.isMetaInstruction()) { + if (!MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) { + // Scan forward to try to find a non-zero line number. The + // prologue_end marks the first breakpoint in the function after the + // frame setup, and a compiler-generated line 0 location is not a + // meaningful breakpoint. If none is found, return the first + // location after the frame setup. + if (MI.getDebugLoc().getLine()) + return std::make_pair(MI.getDebugLoc(), IsEmptyPrologue); + + LineZeroLoc = MI.getDebugLoc(); + } + IsEmptyPrologue = false; } } } - return LineZeroLoc; + return std::make_pair(LineZeroLoc, IsEmptyPrologue); } /// Register a source line with debug info. Returns the unique label that was @@ -2159,8 +2188,16 @@ static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col, DebugLoc DwarfDebug::emitInitialLocDirective(const MachineFunction &MF, unsigned CUID) { + std::pair<DebugLoc, bool> PrologEnd = findPrologueEndLoc(&MF); + DebugLoc PrologEndLoc = PrologEnd.first; + bool IsEmptyPrologue = PrologEnd.second; + // Get beginning of function. - if (DebugLoc PrologEndLoc = findPrologueEndLoc(&MF)) { + if (PrologEndLoc) { + // If the prolog is empty, no need to generate scope line for the proc. + if (IsEmptyPrologue) + return PrologEndLoc; + // Ensure the compile unit is created if the function is called before // beginFunction(). (void)getOrCreateDwarfCompileUnit( @@ -2239,7 +2276,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); assert(!FnScope || SP == FnScope->getScopeNode()); - DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit()); + DwarfCompileUnit &TheCU = getOrCreateDwarfCompileUnit(SP->getUnit()); if (TheCU.getCUNode()->isDebugDirectivesOnly()) { PrevLabel = nullptr; CurFn = nullptr; @@ -2260,6 +2297,9 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { if (!TheCU.getCUNode()->getDebugInfoForProfiling() && TheCU.getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly && LScopes.getAbstractScopesList().empty() && !IsDarwin) { + for (const auto &R : Asm->MBBSectionRanges) + addArangeLabel(SymbolCU(&TheCU, R.second.BeginLabel)); + assert(InfoHolder.getScopeVariables().empty()); PrevLabel = nullptr; CurFn = nullptr; @@ -2267,27 +2307,28 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { } #ifndef NDEBUG - size_t NumAbstractScopes = LScopes.getAbstractScopesList().size(); + size_t NumAbstractSubprograms = LScopes.getAbstractScopesList().size(); #endif - // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { const auto *SP = cast<DISubprogram>(AScope->getScopeNode()); for (const DINode *DN : SP->getRetainedNodes()) { - if (!Processed.insert(InlinedEntity(DN, nullptr)).second) - continue; - - const MDNode *Scope = nullptr; - if (auto *DV = dyn_cast<DILocalVariable>(DN)) - Scope = DV->getScope(); - else if (auto *DL = dyn_cast<DILabel>(DN)) - Scope = DL->getScope(); - else - llvm_unreachable("Unexpected DI type!"); - - // Collect info for variables/labels that were optimized out. - ensureAbstractEntityIsCreated(TheCU, DN, Scope); - assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes - && "ensureAbstractEntityIsCreated inserted abstract scopes"); + const auto *LS = getRetainedNodeScope(DN); + // Ensure LexicalScope is created for the scope of this node. + auto *LexS = LScopes.getOrCreateAbstractScope(LS); + assert(LexS && "Expected the LexicalScope to be created."); + if (isa<DILocalVariable>(DN) || isa<DILabel>(DN)) { + // Collect info for variables/labels that were optimized out. + if (!Processed.insert(InlinedEntity(DN, nullptr)).second || + TheCU.getExistingAbstractEntity(DN)) + continue; + TheCU.createAbstractEntity(DN, LexS); + } else { + // Remember the node if this is a local declarations. + LocalDeclsPerLS[LS].insert(DN); + } + assert( + LScopes.getAbstractScopesList().size() == NumAbstractSubprograms && + "getOrCreateAbstractScope() inserted an abstract subprogram scope"); } constructAbstractSubprogramScopeDIE(TheCU, AScope); } @@ -2308,6 +2349,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { // can be used cross-function) InfoHolder.getScopeVariables().clear(); InfoHolder.getScopeLabels().clear(); + LocalDeclsPerLS.clear(); PrevLabel = nullptr; CurFn = nullptr; } @@ -2507,10 +2549,13 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, Asm->emitDwarfLengthOrOffset(TheU->getLength()); // Emit the pubnames for this compilation unit. - for (const auto &GI : Globals) { - const char *Name = GI.getKeyData(); - const DIE *Entity = GI.second; - + SmallVector<std::pair<StringRef, const DIE *>, 0> Vec; + for (const auto &GI : Globals) + Vec.emplace_back(GI.first(), GI.second); + llvm::sort(Vec, [](auto &A, auto &B) { + return A.second->getOffset() < B.second->getOffset(); + }); + for (const auto &[Name, Entity] : Vec) { Asm->OutStreamer->AddComment("DIE offset"); Asm->emitDwarfLengthOrOffset(Entity->getOffset()); @@ -2523,7 +2568,7 @@ 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.data(), Name.size() + 1)); } Asm->OutStreamer->AddComment("End Mark"); @@ -2566,11 +2611,10 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, for (const auto &Op : Expr) { assert(Op.getCode() != dwarf::DW_OP_const_type && "3 operand ops not yet supported"); + assert(!Op.getSubCode() && "SubOps not yet supported"); Streamer.emitInt8(Op.getCode(), Comment != End ? *(Comment++) : ""); Offset++; - for (unsigned I = 0; I < 2; ++I) { - if (Op.getDescription().Op[I] == Encoding::SizeNA) - continue; + for (unsigned I = 0; I < Op.getDescription().Op.size(); ++I) { if (Op.getDescription().Op[I] == Encoding::BaseTypeRef) { unsigned Length = Streamer.emitDIERef(*CU->ExprRefedBaseTypes[Op.getRawOperand(I)].Die); @@ -3495,10 +3539,11 @@ template <typename DataT> void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel, StringRef Name, const DIE &Die) { - if (getAccelTableKind() == AccelTableKind::None) + if (getAccelTableKind() == AccelTableKind::None || Name.empty()) return; if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Apple && CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Default) return; @@ -3555,11 +3600,9 @@ dwarf::Form DwarfDebug::getDwarfSectionOffsetForm() const { } const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) { - auto I = SectionLabels.find(S); - if (I == SectionLabels.end()) - return nullptr; - return I->second; + return SectionLabels.lookup(S); } + void DwarfDebug::insertSectionLabel(const MCSymbol *S) { if (SectionLabels.insert(std::make_pair(&S->getSection(), S)).second) if (useSplitDwarf() || getDwarfVersion() >= 5) @@ -3583,3 +3626,13 @@ DwarfDebug::getMD5AsBytes(const DIFile *File) const { std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.data()); return CKMem; } + +bool DwarfDebug::alwaysUseRanges(const DwarfCompileUnit &CU) const { + if (MinimizeAddr == MinimizeAddrInV5::Ranges) + return true; + if (MinimizeAddr != MinimizeAddrInV5::Default) + return false; + if (useSplitDwarf()) + return true; + return false; +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index 5d2ef8ee79a7..1af4b643eb17 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -318,9 +318,14 @@ class DwarfDebug : public DebugHandlerBase { /// This is a collection of subprogram MDNodes that are processed to /// create DIEs. - SetVector<const DISubprogram *, SmallVector<const DISubprogram *, 16>, - SmallPtrSet<const DISubprogram *, 16>> - ProcessedSPNodes; + SmallSetVector<const DISubprogram *, 16> ProcessedSPNodes; + + /// Map function-local imported entities to their parent local scope + /// (either DILexicalBlock or DISubprogram) for a processed function + /// (including inlined subprograms). + using MDNodeSet = SetVector<const MDNode *, SmallVector<const MDNode *, 2>, + SmallPtrSet<const MDNode *, 2>>; + DenseMap<const DILocalScope *, MDNodeSet> LocalDeclsPerLS; /// If nonnull, stores the current machine function we're processing. const MachineFunction *CurFn = nullptr; @@ -456,9 +461,6 @@ private: using InlinedEntity = DbgValueHistoryMap::InlinedEntity; - void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, - const DINode *Node, - const MDNode *Scope); void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, const DINode *Node, const MDNode *Scope); @@ -598,10 +600,6 @@ private: void finishUnitAttributes(const DICompileUnit *DIUnit, DwarfCompileUnit &NewCU); - /// Construct imported_module or imported_declaration DIE. - void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity *N); - /// Register a source line with debug info. Returns the unique /// label that was emitted and which provides correspondence to the /// source line list. @@ -696,9 +694,7 @@ public: /// Returns whether range encodings should be used for single entry range /// lists. - bool alwaysUseRanges() const { - return MinimizeAddr == MinimizeAddrInV5::Ranges; - } + bool alwaysUseRanges(const DwarfCompileUnit &) const; // Returns whether novel exprloc addrx+offset encodings should be used to // reduce debug_addr size. @@ -842,6 +838,10 @@ public: /// If the \p File has an MD5 checksum, return it as an MD5Result /// allocated in the MCContext. std::optional<MD5::MD5Result> getMD5AsBytes(const DIFile *File) const; + + MDNodeSet &getLocalDeclsForScope(const DILocalScope *S) { + return LocalDeclsPerLS[S]; + } }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index ab6967f50e30..7623b7fb7c5d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -117,10 +117,10 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, // Walk up the super-register chain until we find a valid number. // For example, EAX on x86_64 is a 32-bit fragment of RAX with offset 0. - for (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) { - Reg = TRI.getDwarfRegNum(*SR, false); + for (MCPhysReg SR : TRI.superregs(MachineReg)) { + Reg = TRI.getDwarfRegNum(SR, false); if (Reg >= 0) { - unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg); + unsigned Idx = TRI.getSubRegIndex(SR, MachineReg); unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); DwarfRegs.push_back(Register::createRegister(Reg, "super-register")); @@ -142,11 +142,11 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, // this doesn't find a combination of subregisters that fully cover // the register (even though one may exist). SmallBitVector Coverage(RegSize, false); - for (MCSubRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) { - unsigned Idx = TRI.getSubRegIndex(MachineReg, *SR); + for (MCPhysReg SR : TRI.subregs(MachineReg)) { + unsigned Idx = TRI.getSubRegIndex(MachineReg, SR); unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned Offset = TRI.getSubRegIdxOffset(Idx); - Reg = TRI.getDwarfRegNum(*SR, false); + Reg = TRI.getDwarfRegNum(SR, false); if (Reg < 0) continue; @@ -566,6 +566,12 @@ bool DwarfExpression::addExpression( case dwarf::DW_OP_dup: case dwarf::DW_OP_push_object_address: case dwarf::DW_OP_over: + case dwarf::DW_OP_eq: + case dwarf::DW_OP_ne: + case dwarf::DW_OP_gt: + case dwarf::DW_OP_ge: + case dwarf::DW_OP_lt: + case dwarf::DW_OP_le: emitOp(OpNum); break; case dwarf::DW_OP_deref: diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h index 79a6ce7801b7..464f4f048016 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h @@ -26,6 +26,7 @@ class DbgEntity; class DbgVariable; class DbgLabel; class DINode; +class DILocalScope; class DwarfCompileUnit; class DwarfUnit; class LexicalScope; @@ -87,7 +88,7 @@ class DwarfFile { DenseMap<LexicalScope *, LabelList> ScopeLabels; // Collection of abstract subprogram DIEs. - DenseMap<const MDNode *, DIE *> AbstractSPDies; + DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs; DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities; /// Maps MDNodes for type system with the corresponding DIEs. These DIEs can @@ -162,8 +163,8 @@ public: return ScopeLabels; } - DenseMap<const MDNode *, DIE *> &getAbstractSPDies() { - return AbstractSPDies; + DenseMap<const DILocalScope *, DIE *> &getAbstractScopeDIEs() { + return AbstractLocalScopeDIEs; } DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index c2ff899c04ab..d30f0ef7af34 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -543,7 +543,7 @@ void DwarfUnit::addAccess(DIE &Die, DINode::DIFlags Flags) { } DIE *DwarfUnit::getOrCreateContextDIE(const DIScope *Context) { - if (!Context || isa<DIFile>(Context)) + if (!Context || isa<DIFile>(Context) || isa<DICompileUnit>(Context)) return &getUnitDie(); if (auto *T = dyn_cast<DIType>(Context)) return getOrCreateTypeDIE(T); @@ -1223,7 +1223,7 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, "decl has a linkage name and it is different"); if (DeclLinkageName.empty() && // Always emit it for abstract subprograms. - (DD->useAllLinkageNames() || DU->getAbstractSPDies().lookup(SP))) + (DD->useAllLinkageNames() || DU->getAbstractScopeDIEs().lookup(SP))) addLinkageName(SPDie, LinkageName); if (!DeclDie) @@ -1362,16 +1362,16 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, auto AddBoundTypeEntry = [&](dwarf::Attribute Attr, DISubrange::BoundType Bound) -> void { - if (auto *BV = Bound.dyn_cast<DIVariable *>()) { + if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) { if (auto *VarDIE = getDIE(BV)) addDIEEntry(DW_Subrange, Attr, *VarDIE); - } else if (auto *BE = Bound.dyn_cast<DIExpression *>()) { + } else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) { 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 *>()) { + } else if (auto *BI = dyn_cast_if_present<ConstantInt *>(Bound)) { if (Attr == dwarf::DW_AT_count) { if (BI->getSExtValue() != -1) addUInt(DW_Subrange, Attr, std::nullopt, BI->getSExtValue()); @@ -1401,10 +1401,10 @@ void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer, auto AddBoundTypeEntry = [&](dwarf::Attribute Attr, DIGenericSubrange::BoundType Bound) -> void { - if (auto *BV = Bound.dyn_cast<DIVariable *>()) { + if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) { if (auto *VarDIE = getDIE(BV)) addDIEEntry(DwGenericSubrange, Attr, *VarDIE); - } else if (auto *BE = Bound.dyn_cast<DIExpression *>()) { + } else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) { if (BE->isConstant() && DIExpression::SignedOrUnsignedConstant::SignedConstant == *BE->isConstant()) { @@ -1463,7 +1463,7 @@ static bool hasVectorBeenPadded(const DICompositeType *CTy) { const auto Subrange = cast<DISubrange>(Elements[0]); const auto NumVecElements = Subrange->getCount() - ? Subrange->getCount().get<ConstantInt *>()->getSExtValue() + ? cast<ConstantInt *>(Subrange->getCount())->getSExtValue() : 0; // Ensure we found the element count and that the actual size is wide diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index 0caa6adbfa62..8f17e94c2d1c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -245,10 +245,10 @@ public: DIE *createTypeDIE(const DIScope *Context, DIE &ContextDIE, const DIType *Ty); /// Find existing DIE or create new DIE for the given type. - DIE *getOrCreateTypeDIE(const MDNode *TyNode); + virtual DIE *getOrCreateTypeDIE(const MDNode *TyNode); /// Get context owner's DIE. - DIE *getOrCreateContextDIE(const DIScope *Context); + virtual DIE *getOrCreateContextDIE(const DIScope *Context); /// Construct DIEs for types that contain vtables. void constructContainingTypeDIEs(); diff --git a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp index 67e2c0e07095..eef6b1d93f36 100644 --- a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -410,7 +410,7 @@ MCSymbol *EHStreamer::emitExceptionTable() { computeActionsTable(LandingPads, Actions, FirstActions); // Compute the call-site table and call-site ranges. Normally, there is only - // one call-site-range which covers the whole funciton. With + // one call-site-range which covers the whole function. With // -basic-block-sections, there is one call-site-range per basic block // section. SmallVector<CallSiteEntry, 64> CallSites; diff --git a/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp index 3e75b4371033..59c3fa15885e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp @@ -32,11 +32,7 @@ void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index, SmallVector<InlineSite, 8> ReversedInlineStack; auto *InlinedAt = DebugLoc ? DebugLoc->getInlinedAt() : nullptr; while (InlinedAt) { - const DISubprogram *SP = InlinedAt->getScope()->getSubprogram(); - // Use linkage name for C++ if possible. - auto Name = SP->getLinkageName(); - if (Name.empty()) - Name = SP->getName(); + auto Name = InlinedAt->getSubprogramLinkageName(); // Use caching to avoid redundant md5 computation for build speed. uint64_t &CallerGuid = NameGuidMap[Name]; if (!CallerGuid) @@ -46,8 +42,15 @@ void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index, ReversedInlineStack.emplace_back(CallerGuid, CallerProbeId); InlinedAt = InlinedAt->getInlinedAt(); } - + uint64_t Discriminator = 0; + // For now only block probes have FS discriminators. See + // MIRFSDiscriminator.cpp for more details. + if (EnableFSDiscriminator && DebugLoc && + (Type == (uint64_t)PseudoProbeType::Block)) + Discriminator = DebugLoc->getDiscriminator(); + assert((EnableFSDiscriminator || Discriminator == 0) && + "Discriminator should not be set in non-FSAFDO mode"); SmallVector<InlineSite, 8> InlineStack(llvm::reverse(ReversedInlineStack)); - Asm->OutStreamer->emitPseudoProbe(Guid, Index, Type, Attr, InlineStack, - Asm->CurrentFnSym); + Asm->OutStreamer->emitPseudoProbe(Guid, Index, Type, Attr, Discriminator, + InlineStack, Asm->CurrentFnSym); } diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 7a800438592c..6d6432b61f2d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -638,7 +638,7 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State]; const MCExpr *FilterOrFinally; const MCExpr *ExceptOrNull; - auto *Handler = UME.Handler.get<MachineBasicBlock *>(); + auto *Handler = cast<MachineBasicBlock *>(UME.Handler); if (UME.IsFinally) { FilterOrFinally = create32bitRef(getMCSymbolForMBB(Asm, Handler)); ExceptOrNull = MCConstantExpr::create(0, Ctx); @@ -762,7 +762,11 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { OS.emitInt32(0); AddComment("EHFlags"); - OS.emitInt32(1); + if (MMI->getModule()->getModuleFlag("eh-asynch")) { + OS.emitInt32(0); + } else { + OS.emitInt32(1); + } // UnwindMapEntry { // int32_t ToState; @@ -771,8 +775,8 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { if (UnwindMapXData) { OS.emitLabel(UnwindMapXData); for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) { - MCSymbol *CleanupSym = - getMCSymbolForMBB(Asm, UME.Cleanup.dyn_cast<MachineBasicBlock *>()); + MCSymbol *CleanupSym = getMCSymbolForMBB( + Asm, dyn_cast_if_present<MachineBasicBlock *>(UME.Cleanup)); AddComment("ToState"); OS.emitInt32(UME.ToState); @@ -859,8 +863,8 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext); } - MCSymbol *HandlerSym = - getMCSymbolForMBB(Asm, HT.Handler.dyn_cast<MachineBasicBlock *>()); + MCSymbol *HandlerSym = getMCSymbolForMBB( + Asm, dyn_cast_if_present<MachineBasicBlock *>(HT.Handler)); AddComment("Adjectives"); OS.emitInt32(HT.Adjectives); @@ -1065,7 +1069,7 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { assert(!FuncInfo.SEHUnwindMap.empty()); for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { - auto *Handler = UME.Handler.get<MachineBasicBlock *>(); + auto *Handler = cast<MachineBasicBlock *>(UME.Handler); const MCSymbol *ExceptOrFinally = UME.IsFinally ? getMCSymbolForMBB(Asm, Handler) : Handler->getSymbol(); // -1 is usually the base state for "unwind to caller", but for @@ -1136,7 +1140,7 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { DenseMap<const MachineBasicBlock *, int> HandlerStates; for (int State = 0; State < NumStates; ++State) { MachineBasicBlock *HandlerBlock = - FuncInfo.ClrEHUnwindMap[State].Handler.get<MachineBasicBlock *>(); + cast<MachineBasicBlock *>(FuncInfo.ClrEHUnwindMap[State].Handler); HandlerStates[HandlerBlock] = State; // Use this loop through all handlers to verify our assumption (used in // the MinEnclosingState computation) that enclosing funclets have lower @@ -1297,7 +1301,7 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym); const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State]; - MachineBasicBlock *HandlerBlock = Entry.Handler.get<MachineBasicBlock *>(); + MachineBasicBlock *HandlerBlock = cast<MachineBasicBlock *>(Entry.Handler); MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock); const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym); MCSymbol *EndSym = EndSymbolMap[Clause.State]; |