diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter')
21 files changed, 592 insertions, 302 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 73c53d6c4af5..6f9aa4dd79fd 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -31,13 +31,16 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -52,6 +55,7 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/CodeGen/MachineSizeOpts.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -81,7 +85,6 @@ #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodePadder.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" @@ -139,18 +142,13 @@ static const char *const DbgTimerDescription = "Debug Info Emission"; static const char *const EHTimerName = "write_exception"; static const char *const EHTimerDescription = "DWARF Exception Writer"; static const char *const CFGuardName = "Control Flow Guard"; -static const char *const CFGuardDescription = "Control Flow Guard Tables"; +static const char *const CFGuardDescription = "Control Flow Guard"; static const char *const CodeViewLineTablesGroupName = "linetables"; static const char *const CodeViewLineTablesGroupDescription = "CodeView Line Tables"; STATISTIC(EmittedInsts, "Number of machine instrs printed"); -static cl::opt<bool> EnableRemarksSection( - "remarks-section", - cl::desc("Emit a section containing remark diagnostics metadata"), - cl::init(false)); - char AsmPrinter::ID = 0; using gcp_map_type = DenseMap<GCStrategy *, std::unique_ptr<GCMetadataPrinter>>; @@ -253,6 +251,8 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<MachineModuleInfoWrapperPass>(); AU.addRequired<MachineOptimizationRemarkEmitterPass>(); AU.addRequired<GCModuleInfo>(); + AU.addRequired<LazyMachineBlockFrequencyInfoPass>(); + AU.addRequired<ProfileSummaryInfoWrapperPass>(); } bool AsmPrinter::doInitialization(Module &M) { @@ -381,12 +381,12 @@ bool AsmPrinter::doInitialization(Module &M) { EHTimerDescription, DWARFGroupName, DWARFGroupDescription); + // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2). if (mdconst::extract_or_null<ConstantInt>( - MMI->getModule()->getModuleFlag("cfguardtable"))) + MMI->getModule()->getModuleFlag("cfguard"))) Handlers.emplace_back(std::make_unique<WinCFGuard>(this), CFGuardName, CFGuardDescription, DWARFGroupName, DWARFGroupDescription); - return false; } @@ -879,6 +879,10 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { OS << MI->getOperand(0).getImm(); } else if (MI->getOperand(0).isCImm()) { MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); + } else if (MI->getOperand(0).isTargetIndex()) { + auto Op = MI->getOperand(0); + OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; + return true; } else { unsigned Reg; if (MI->getOperand(0).isReg()) { @@ -940,7 +944,7 @@ AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const { MF->getFunction().needsUnwindTableEntry()) return CFI_M_EH; - if (MMI->hasDebugInfo()) + if (MMI->hasDebugInfo() || MF->getTarget().Options.ForceDwarfFrameSection) return CFI_M_Debug; return CFI_M_None; @@ -1065,13 +1069,9 @@ void AsmPrinter::EmitFunctionBody() { ++NumInstsInFunction; } - // If there is a pre-instruction symbol, emit a label for it here. If the - // instruction was duplicated and the label has already been emitted, - // don't re-emit the same label. - // FIXME: Consider strengthening that to an assertion. + // If there is a pre-instruction symbol, emit a label for it here. if (MCSymbol *S = MI.getPreInstrSymbol()) - if (S->isUndefined()) - OutStreamer->EmitLabel(S); + OutStreamer->EmitLabel(S); if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { @@ -1124,13 +1124,9 @@ void AsmPrinter::EmitFunctionBody() { break; } - // If there is a post-instruction symbol, emit a label for it here. If - // the instruction was duplicated and the label has already been emitted, - // don't re-emit the same label. - // FIXME: Consider strengthening that to an assertion. + // If there is a post-instruction symbol, emit a label for it here. if (MCSymbol *S = MI.getPostInstrSymbol()) - if (S->isUndefined()) - OutStreamer->EmitLabel(S); + OutStreamer->EmitLabel(S); if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { @@ -1226,6 +1222,8 @@ void AsmPrinter::EmitFunctionBody() { // Emit section containing stack size metadata. emitStackSizeSection(*MF); + emitPatchableFunctionEntries(); + if (isVerbose()) OutStreamer->GetCommentOS() << "-- End function\n"; @@ -1365,14 +1363,14 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, } } -void AsmPrinter::emitRemarksSection(Module &M) { - RemarkStreamer *RS = M.getContext().getRemarkStreamer(); - if (!RS) +void AsmPrinter::emitRemarksSection(RemarkStreamer &RS) { + if (!RS.needsSection()) return; - remarks::RemarkSerializer &RemarkSerializer = RS->getSerializer(); + + remarks::RemarkSerializer &RemarkSerializer = RS.getSerializer(); Optional<SmallString<128>> Filename; - if (Optional<StringRef> FilenameRef = RS->getFilename()) { + if (Optional<StringRef> FilenameRef = RS.getFilename()) { Filename = *FilenameRef; sys::fs::make_absolute(*Filename); assert(!Filename->empty() && "The filename can't be empty."); @@ -1385,7 +1383,7 @@ void AsmPrinter::emitRemarksSection(Module &M) { : RemarkSerializer.metaSerializer(OS); MetaSerializer->emit(); - // Switch to the right section: .remarks/__remarks. + // Switch to the remarks section. MCSection *RemarksSection = OutContext.getObjectFileInfo()->getRemarksSection(); OutStreamer->SwitchSection(RemarksSection); @@ -1427,8 +1425,8 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit the remarks section contents. // FIXME: Figure out when is the safest time to emit this section. It should // not come after debug info. - if (EnableRemarksSection) - emitRemarksSection(M); + if (RemarkStreamer *RS = M.getContext().getRemarkStreamer()) + emitRemarksSection(*RS); const TargetLoweringObjectFile &TLOF = getObjFileLowering(); @@ -1503,8 +1501,6 @@ bool AsmPrinter::doFinalization(Module &M) { } } - OutStreamer->AddBlankLine(); - // Print aliases in topological order, that is, for each alias a = b, // b must be printed before a. // This is because on some targets (e.g. PowerPC) linker expects aliases in @@ -1666,6 +1662,7 @@ MCSymbol *AsmPrinter::getCurExceptionSym() { void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { this->MF = &MF; + const Function &F = MF.getFunction(); // Get the function symbol. if (MAI->needsFunctionDescriptors()) { @@ -1678,7 +1675,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { CurrentFnSym = OutContext.getOrCreateSymbol("." + CurrentFnDescSym->getName()); - const Function &F = MF.getFunction(); MCSectionXCOFF *FnEntryPointSec = cast<MCSectionXCOFF>(getObjFileLowering().SectionForGlobal(&F, TM)); // Set the containing csect. @@ -1691,7 +1687,8 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { CurrentFnBegin = nullptr; CurExceptionSym = nullptr; bool NeedsLocalForSize = MAI->needsLocalForSize(); - if (needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize || + if (F.hasFnAttribute("patchable-function-entry") || + needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize || MF.getTarget().Options.EmitStackSizeSection) { CurrentFnBegin = createTempSymbol("func_begin"); if (NeedsLocalForSize) @@ -1699,6 +1696,13 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { } ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); + PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(); + MBFI = (PSI && PSI->hasProfileSummary()) ? + // ORE conditionally computes MBFI. If available, use it, otherwise + // request it. + (ORE->getBFI() ? ORE->getBFI() : + &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()) : + nullptr; } namespace { @@ -1769,6 +1773,11 @@ void AsmPrinter::EmitConstantPool() { if (!Sym->isUndefined()) continue; + if (TM.getTargetTriple().isOSBinFormatXCOFF()) { + cast<MCSymbolXCOFF>(Sym)->setContainingCsect( + cast<MCSectionXCOFF>(CPSections[i].S)); + } + if (CurSection != CPSections[i].S) { OutStreamer->SwitchSection(CPSections[i].S); EmitAlignment(Align(CPSections[i].Alignment)); @@ -1858,10 +1867,16 @@ void AsmPrinter::EmitJumpTableInfo() { // second label is actually referenced by the code. if (JTInDiffSection && DL.hasLinkerPrivateGlobalPrefix()) // FIXME: This doesn't have to have any specific name, just any randomly - // named and numbered 'l' label would work. Simplify GetJTISymbol. + // named and numbered local label started with 'l' would work. Simplify + // GetJTISymbol. OutStreamer->EmitLabel(GetJTISymbol(JTI, true)); - OutStreamer->EmitLabel(GetJTISymbol(JTI)); + MCSymbol* JTISymbol = GetJTISymbol(JTI); + if (TM.getTargetTriple().isOSBinFormatXCOFF()) { + cast<MCSymbolXCOFF>(JTISymbol)->setContainingCsect( + cast<MCSectionXCOFF>(TLOF.getSectionForJumpTable(F, TM))); + } + OutStreamer->EmitLabel(JTISymbol); for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); @@ -2914,19 +2929,6 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); } -void AsmPrinter::setupCodePaddingContext(const MachineBasicBlock &MBB, - MCCodePaddingContext &Context) const { - assert(MF != nullptr && "Machine function must be valid"); - Context.IsPaddingActive = !MF->hasInlineAsm() && - !MF->getFunction().hasOptSize() && - TM.getOptLevel() != CodeGenOpt::None; - Context.IsBasicBlockReachableViaFallthrough = - std::find(MBB.pred_begin(), MBB.pred_end(), MBB.getPrevNode()) != - MBB.pred_end(); - Context.IsBasicBlockReachableViaBranch = - MBB.pred_size() > 0 && !isBlockOnlyReachableByFallthrough(&MBB); -} - /// EmitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. @@ -2943,9 +2945,6 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { const Align Alignment = MBB.getAlignment(); if (Alignment != Align::None()) EmitAlignment(Alignment); - MCCodePaddingContext Context; - setupCodePaddingContext(MBB, Context); - OutStreamer->EmitCodePaddingBasicBlockStart(Context); // If the block has its address taken, emit any labels that were used to // reference the block. It is possible that there is more than one label @@ -2993,11 +2992,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { } } -void AsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { - MCCodePaddingContext Context; - setupCodePaddingContext(MBB, Context); - OutStreamer->EmitCodePaddingBasicBlockEnd(Context); -} +void AsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition) const { @@ -3202,6 +3197,41 @@ void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI, AlwaysInstrument, &F, Version}); } +void AsmPrinter::emitPatchableFunctionEntries() { + const Function &F = MF->getFunction(); + if (!F.hasFnAttribute("patchable-function-entry")) + return; + const unsigned PointerSize = getPointerSize(); + if (TM.getTargetTriple().isOSBinFormatELF()) { + auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC; + + // As of binutils 2.33, GNU as does not support section flag "o" or linkage + // field "unique". Use SHF_LINK_ORDER if we are using the integrated + // assembler. + if (MAI->useIntegratedAssembler()) { + Flags |= ELF::SHF_LINK_ORDER; + std::string GroupName; + if (F.hasComdat()) { + Flags |= ELF::SHF_GROUP; + GroupName = F.getComdat()->getName(); + } + MCSection *Section = getObjFileLowering().SectionForGlobal(&F, TM); + unsigned UniqueID = + PatchableFunctionEntryID + .try_emplace(Section, PatchableFunctionEntryID.size()) + .first->second; + OutStreamer->SwitchSection(OutContext.getELFSection( + "__patchable_function_entries", ELF::SHT_PROGBITS, Flags, 0, + GroupName, UniqueID, cast<MCSymbolELF>(CurrentFnSym))); + } else { + OutStreamer->SwitchSection(OutContext.getELFSection( + "__patchable_function_entries", ELF::SHT_PROGBITS, Flags)); + } + EmitAlignment(Align(PointerSize)); + OutStreamer->EmitSymbolValue(CurrentFnBegin, PointerSize); + } +} + uint16_t AsmPrinter::getDwarfVersion() const { return OutStreamer->getContext().getDwarfVersion(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 420df26a2b8b..c631cc5360b8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -207,11 +207,17 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, } if (Done) break; + bool HasCurlyBraces = false; + if (*LastEmitted == '{') { // ${variable} + ++LastEmitted; // Consume '{' character. + HasCurlyBraces = true; + } + // If we have ${:foo}, then this is not a real operand reference, it is a // "magic" string reference, just like in .td files. Arrange to call // PrintSpecial. - if (LastEmitted[0] == '{' && LastEmitted[1] == ':') { - LastEmitted += 2; + if (HasCurlyBraces && LastEmitted[0] == ':') { + ++LastEmitted; const char *StrStart = LastEmitted; const char *StrEnd = strchr(StrStart, '}'); if (!StrEnd) @@ -238,6 +244,27 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, report_fatal_error("Invalid $ operand number in inline asm string: '" + Twine(AsmStr) + "'"); + char Modifier[2] = { 0, 0 }; + + if (HasCurlyBraces) { + // If we have curly braces, check for a modifier character. This + // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. + if (*LastEmitted == ':') { + ++LastEmitted; // Consume ':' character. + if (*LastEmitted == 0) + report_fatal_error("Bad ${:} expression in inline asm string: '" + + Twine(AsmStr) + "'"); + + Modifier[0] = *LastEmitted; + ++LastEmitted; // Consume modifier character. + } + + if (*LastEmitted != '}') + report_fatal_error("Bad ${} expression in inline asm string: '" + + Twine(AsmStr) + "'"); + ++LastEmitted; // Consume '}' character. + } + // Okay, we finally have a value number. Ask the target to print this // operand! unsigned OpNo = InlineAsm::MIOp_FirstOperand; @@ -262,9 +289,11 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, ++OpNo; // Skip over the ID number. if (InlineAsm::isMemKind(OpFlags)) { - Error = AP->PrintAsmMemoryOperand(MI, OpNo, /*Modifier*/ nullptr, OS); + Error = AP->PrintAsmMemoryOperand( + MI, OpNo, Modifier[0] ? Modifier : nullptr, OS); } else { - Error = AP->PrintAsmOperand(MI, OpNo, /*Modifier*/ nullptr, OS); + Error = AP->PrintAsmOperand(MI, OpNo, + Modifier[0] ? Modifier : nullptr, OS); } } if (Error) { @@ -427,26 +456,23 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, // FIXME: Shouldn't arch-independent output template handling go into // PrintAsmOperand? - if (Modifier[0] == 'l') { // Labels are target independent. - if (MI->getOperand(OpNo).isBlockAddress()) { - const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); - MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); - Sym->print(OS, AP->MAI); - MMI->getContext().registerInlineAsmLabel(Sym); - } else if (MI->getOperand(OpNo).isMBB()) { - const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); - Sym->print(OS, AP->MAI); - } else { - Error = true; - } + // Labels are target independent. + if (MI->getOperand(OpNo).isBlockAddress()) { + const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); + MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); + Sym->print(OS, AP->MAI); + MMI->getContext().registerInlineAsmLabel(Sym); + } else if (MI->getOperand(OpNo).isMBB()) { + const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); + Sym->print(OS, AP->MAI); + } else if (Modifier[0] == 'l') { + Error = true; + } else if (InlineAsm::isMemKind(OpFlags)) { + Error = AP->PrintAsmMemoryOperand( + MI, OpNo, Modifier[0] ? Modifier : nullptr, OS); } else { - if (InlineAsm::isMemKind(OpFlags)) { - Error = AP->PrintAsmMemoryOperand( - MI, OpNo, Modifier[0] ? Modifier : nullptr, OS); - } else { - Error = AP->PrintAsmOperand(MI, OpNo, - Modifier[0] ? Modifier : nullptr, OS); - } + Error = AP->PrintAsmOperand(MI, OpNo, + Modifier[0] ? Modifier : nullptr, OS); } } if (Error) { diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index c6457f3626d1..62ad356e7f8f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1100,14 +1100,8 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, } for (auto HeapAllocSite : FI.HeapAllocSites) { - MCSymbol *BeginLabel = std::get<0>(HeapAllocSite); - MCSymbol *EndLabel = std::get<1>(HeapAllocSite); - - // The labels might not be defined if the instruction was replaced - // somewhere in the codegen pipeline. - if (!BeginLabel->isDefined() || !EndLabel->isDefined()) - continue; - + const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite); + const MCSymbol *EndLabel = std::get<1>(HeapAllocSite); const DIType *DITy = std::get<2>(HeapAllocSite); MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE); OS.AddComment("Call site offset"); @@ -1427,6 +1421,16 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc(); maybeRecordLocation(FnStartDL, MF); } + + // Find heap alloc sites and emit labels around them. + for (const auto &MBB : *MF) { + for (const auto &MI : MBB) { + if (MI.getHeapAllocMarker()) { + requestLabelBeforeInsn(&MI); + requestLabelAfterInsn(&MI); + } + } + } } static bool shouldEmitUdt(const DIType *T) { @@ -2850,8 +2854,18 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) { return; } + // Find heap alloc sites and add to list. + for (const auto &MBB : *MF) { + for (const auto &MI : MBB) { + if (MDNode *MD = MI.getHeapAllocMarker()) { + CurFn->HeapAllocSites.push_back(std::make_tuple(getLabelBeforeInsn(&MI), + getLabelAfterInsn(&MI), + dyn_cast<DIType>(MD))); + } + } + } + CurFn->Annotations = MF->getCodeViewAnnotations(); - CurFn->HeapAllocSites = MF->getCodeViewHeapAllocSites(); CurFn->End = Asm->getFunctionEnd(); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 7ffd77926cf7..b56b9047e1a9 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -148,7 +148,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { SmallVector<LexicalBlock *, 1> ChildBlocks; std::vector<std::pair<MCSymbol *, MDNode *>> Annotations; - std::vector<std::tuple<MCSymbol *, MCSymbol *, const DIType *>> + std::vector<std::tuple<const MCSymbol *, const MCSymbol *, const DIType *>> HeapAllocSites; const MCSymbol *Begin = nullptr; diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index f4134da48caa..84b86a71fa5f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -319,8 +319,10 @@ DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag) { Die.Owner = this; assert((UnitTag == dwarf::DW_TAG_compile_unit || + UnitTag == dwarf::DW_TAG_skeleton_unit || UnitTag == dwarf::DW_TAG_type_unit || - UnitTag == dwarf::DW_TAG_partial_unit) && "expected a unit TAG"); + UnitTag == dwarf::DW_TAG_partial_unit) && + "expected a unit TAG"); } void DIEValue::EmitValue(const AsmPrinter *AP) const { @@ -798,6 +800,8 @@ void DIEBlock::print(raw_ostream &O) const { //===----------------------------------------------------------------------===// unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_loclistx) + return getULEB128Size(Index); if (Form == dwarf::DW_FORM_data4) return 4; if (Form == dwarf::DW_FORM_sec_offset) @@ -808,6 +812,10 @@ unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { /// EmitValue - Emit label value. /// void DIELocList::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_loclistx) { + AP->EmitULEB128(Index); + return; + } DwarfDebug *DD = AP->getDwarfDebug(); MCSymbol *Label = DD->getDebugLocs().getList(Index).Label; AP->emitDwarfSymbolReference(Label, /*ForceOffset*/ DD->useSplitDwarf()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 7f9d6c618ad3..170fc8b6d49f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -262,7 +262,9 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, DbgLabels.addInstr(L, MI); } - if (MI.isDebugInstr()) + // Meta Instructions have no output and do not change any values and so + // can be safely ignored. + if (MI.isMetaInstruction()) continue; // Not a DBG_VALUE instruction. It may clobber registers which describe diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index 17e39b3d3268..36278f2e9e2d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -20,13 +20,33 @@ namespace llvm { class AsmPrinter; +/// This struct describes target specific location. +struct TargetIndexLocation { + int Index; + int Offset; + + TargetIndexLocation() = default; + TargetIndexLocation(unsigned Idx, int64_t Offset) + : Index(Idx), Offset(Offset) {} + + bool operator==(const TargetIndexLocation &Other) const { + return Index == Other.Index && Offset == Other.Offset; + } +}; + /// A single location or constant. class DbgValueLoc { /// Any complex address location expression for this DbgValueLoc. const DIExpression *Expression; /// Type of entry that this represents. - enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; + enum EntryType { + E_Location, + E_Integer, + E_ConstantFP, + E_ConstantInt, + E_TargetIndexLocation + }; enum EntryType EntryKind; /// Either a constant, @@ -36,8 +56,12 @@ class DbgValueLoc { const ConstantInt *CIP; } Constant; - /// Or a location in the machine frame. - MachineLocation Loc; + union { + /// Or a location in the machine frame. + MachineLocation Loc; + /// Or a location from target specific location. + TargetIndexLocation TIL; + }; public: DbgValueLoc(const DIExpression *Expr, int64_t i) @@ -56,8 +80,13 @@ public: : Expression(Expr), EntryKind(E_Location), Loc(Loc) { assert(cast<DIExpression>(Expr)->isValid()); } + DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc) + : Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {} bool isLocation() const { return EntryKind == E_Location; } + bool isTargetIndexLocation() const { + return EntryKind == E_TargetIndexLocation; + } bool isInt() const { return EntryKind == E_Integer; } bool isConstantFP() const { return EntryKind == E_ConstantFP; } bool isConstantInt() const { return EntryKind == E_ConstantInt; } @@ -65,6 +94,7 @@ public: const ConstantFP *getConstantFP() const { return Constant.CFP; } const ConstantInt *getConstantInt() const { return Constant.CIP; } MachineLocation getLoc() const { return Loc; } + TargetIndexLocation getTargetIndexLocation() const { return TIL; } bool isFragment() const { return getExpression()->isFragment(); } bool isEntryVal() const { return getExpression()->isEntryValue(); } const DIExpression *getExpression() const { return Expression; } @@ -162,6 +192,8 @@ inline bool operator==(const DbgValueLoc &A, switch (A.EntryKind) { case DbgValueLoc::E_Location: return A.Loc == B.Loc; + case DbgValueLoc::E_TargetIndexLocation: + return A.TIL == B.TIL; case DbgValueLoc::E_Integer: return A.Constant.Int == B.Constant.Int; case DbgValueLoc::E_ConstantFP: diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp index f483d532ff07..8c6109880afc 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp @@ -42,4 +42,6 @@ DebugLocStream::ListBuilder::~ListBuilder() { return; V.initializeDbgValue(&MI); V.setDebugLocListIndex(ListIndex); + if (TagOffset) + V.setDebugLocListTagOffset(*TagOffset); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h index 0db86b09d19a..10019a4720e6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h @@ -159,11 +159,17 @@ class DebugLocStream::ListBuilder { DbgVariable &V; const MachineInstr &MI; size_t ListIndex; + Optional<uint8_t> TagOffset; public: ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, DbgVariable &V, const MachineInstr &MI) - : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {} + : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)), + TagOffset(None) {} + + void setTagOffset(uint8_t TO) { + TagOffset = TO; + } /// Finalize the list. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 207a7284dafa..facbf22946e4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -133,6 +134,8 @@ void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, if (!hasEmittedCFISections) { if (Asm->needsOnlyDebugCFIMoves()) Asm->OutStreamer->EmitCFISections(false, true); + else if (Asm->TM.Options.ForceDwarfFrameSection) + Asm->OutStreamer->EmitCFISections(true, true); hasEmittedCFISections = true; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index a61c98ec1c18..38011102c7b3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -52,10 +52,23 @@ using namespace llvm; +static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) { + + // According to DWARF Debugging Information Format Version 5, + // 3.1.2 Skeleton Compilation Unit Entries: + // "When generating a split DWARF object file (see Section 7.3.2 + // on page 187), the compilation unit in the .debug_info section + // is a "skeleton" compilation unit with the tag DW_TAG_skeleton_unit" + if (DW->getDwarfVersion() >= 5 && Kind == UnitKind::Skeleton) + return dwarf::DW_TAG_skeleton_unit; + + return dwarf::DW_TAG_compile_unit; +} + DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW, - DwarfFile *DWU) - : DwarfUnit(dwarf::DW_TAG_compile_unit, Node, A, DW, DWU), UniqueID(UID) { + DwarfFile *DWU, UnitKind Kind) + : DwarfUnit(GetCompileUnitType(Kind, DW), Node, A, DW, DWU), UniqueID(UID) { insertDIE(Node, &getUnitDie()); MacroLabelBegin = Asm->createTempSymbol("cu_macro_begin"); } @@ -65,10 +78,6 @@ DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label) { // Don't use the address pool in non-fission or in the skeleton unit itself. - // FIXME: Once GDB supports this, it's probably worthwhile using the address - // pool from the skeleton - maybe even in non-fission (possibly fewer - // relocations by sharing them in the pool, but we have other ideas about how - // to reduce the number of relocations as well/instead). if ((!DD->useSplitDwarf() || !Skeleton) && DD->getDwarfVersion() < 5) return addLocalLabelAddress(Die, Attribute, Label); @@ -490,10 +499,10 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE, const MCSymbol *RangeSectionSym = TLOF.getDwarfRangesSection()->getBeginSymbol(); if (isDwoUnit()) - addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), + addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.Label, RangeSectionSym); else - addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), + addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.Label, RangeSectionSym); } } @@ -602,6 +611,10 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, unsigned Offset = DV.getDebugLocListIndex(); if (Offset != ~0U) { addLocationList(*VariableDie, dwarf::DW_AT_location, Offset); + auto TagOffset = DV.getDebugLocListTagOffset(); + if (TagOffset) + addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, + *TagOffset); return VariableDie; } @@ -619,6 +632,10 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, DwarfExpr.addUnsignedConstant(DVal->getInt()); DwarfExpr.addExpression(Expr); addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); + if (DwarfExpr.TagOffset) + addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, + dwarf::DW_FORM_data1, *DwarfExpr.TagOffset); + } else addConstantValue(*VariableDie, DVal->getInt(), DV.getType()); } else if (DVal->isConstantFP()) { @@ -951,8 +968,8 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE( addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target), MachineLocation(CallReg)); } else { - DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP); - assert(CalleeDIE && "Could not create DIE for call site entry origin"); + DIE *CalleeDIE = getDIE(CalleeSP); + assert(CalleeDIE && "Could not find DIE for call site entry origin"); addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin), *CalleeDIE); } @@ -1185,6 +1202,10 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, // Now attach the location information to the DIE. addBlock(Die, Attribute, DwarfExpr.finalize()); + + if (DwarfExpr.TagOffset) + addUInt(Die, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, + *DwarfExpr.TagOffset); } /// Start with the address based on the location provided, and generate the @@ -1215,13 +1236,20 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, // Now attach the location information to the DIE. addBlock(Die, Attribute, DwarfExpr.finalize()); + + if (DwarfExpr.TagOffset) + addUInt(Die, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, + *DwarfExpr.TagOffset); } /// Add a Dwarf loclistptr attribute data and value. void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index) { - dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4; + dwarf::Form Form = dwarf::DW_FORM_data4; + if (DD->getDwarfVersion() == 4) + Form =dwarf::DW_FORM_sec_offset; + if (DD->getDwarfVersion() >= 5) + Form =dwarf::DW_FORM_loclistx; Die.addValue(DIEValueAllocator, Attribute, Form, DIELocList(Index)); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 1b7ea2673ac0..8491d078ed89 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -40,6 +40,8 @@ class MCExpr; class MCSymbol; class MDNode; +enum class UnitKind { Skeleton, Full }; + class DwarfCompileUnit final : public DwarfUnit { /// A numeric ID unique among all CUs in the module unsigned UniqueID; @@ -104,7 +106,8 @@ class DwarfCompileUnit final : public DwarfUnit { public: DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, - DwarfDebug *DW, DwarfFile *DWU); + DwarfDebug *DW, DwarfFile *DWU, + UnitKind Kind = UnitKind::Full); bool hasRangeLists() const { return HasRangeLists; } unsigned getUniqueID() const { return UniqueID; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index c505e77e5acd..fa6800de7955 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -241,6 +241,11 @@ static DbgValueLoc getDebugLocValue(const MachineInstr *MI) { MachineLocation MLoc(RegOp.getReg(), Op1.isImm()); return DbgValueLoc(Expr, MLoc); } + if (MI->getOperand(0).isTargetIndex()) { + auto Op = MI->getOperand(0); + return DbgValueLoc(Expr, + TargetIndexLocation(Op.getIndex(), Op.getOffset())); + } if (MI->getOperand(0).isImm()) return DbgValueLoc(Expr, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) @@ -535,6 +540,14 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, } } +DIE &DwarfDebug::constructSubprogramDefinitionDIE(const DISubprogram *SP) { + DICompileUnit *Unit = SP->getUnit(); + assert(SP->isDefinition() && "Subprogram not a definition"); + assert(Unit && "Subprogram definition without parent unit"); + auto &CU = getOrCreateDwarfCompileUnit(Unit); + return *CU.getOrCreateSubprogramDIE(SP); +} + /// Try to interpret values loaded into registers that forward parameters /// for \p CallMI. Store parameters with interpreted value into \p Params. static void collectCallSiteParameters(const MachineInstr *CallMI, @@ -595,7 +608,6 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, Implicit.push_back(FwdReg); else Explicit.push_back(FwdReg); - break; } } } @@ -615,8 +627,12 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, ++NumCSParams; }; - // Search for a loading value in forwaring registers. + // Search for a loading value in forwarding registers. for (; I != MBB->rend(); ++I) { + // Skip bundle headers. + if (I->isBundle()) + continue; + // If the next instruction is a call we can not interpret parameter's // forwarding registers or we finished the interpretation of all parameters. if (I->isCall()) @@ -636,32 +652,33 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, for (auto Reg : concat<unsigned>(ExplicitFwdRegDefs, ImplicitFwdRegDefs)) ForwardedRegWorklist.erase(Reg); - // The describeLoadedValue() hook currently does not have any information - // about which register it should describe in case of multiple defines, so - // for now we only handle instructions where a forwarded register is (at - // least partially) defined by the instruction's single explicit define. - if (I->getNumExplicitDefs() != 1 || ExplicitFwdRegDefs.empty()) - continue; - unsigned Reg = ExplicitFwdRegDefs[0]; - - if (auto ParamValue = TII->describeLoadedValue(*I)) { - if (ParamValue->first.isImm()) { - int64_t Val = ParamValue->first.getImm(); - DbgValueLoc DbgLocVal(ParamValue->second, Val); - finishCallSiteParam(DbgLocVal, Reg); - } else if (ParamValue->first.isReg()) { - Register RegLoc = ParamValue->first.getReg(); - unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); - Register FP = TRI->getFrameRegister(*MF); - bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP); - if (TRI->isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) { - DbgValueLoc DbgLocVal(ParamValue->second, - MachineLocation(RegLoc, - /*IsIndirect=*/IsSPorFP)); - finishCallSiteParam(DbgLocVal, Reg); - } else if (ShouldTryEmitEntryVals) { - ForwardedRegWorklist.insert(RegLoc); - RegsForEntryValues[RegLoc] = Reg; + for (auto ParamFwdReg : ExplicitFwdRegDefs) { + if (auto ParamValue = TII->describeLoadedValue(*I, ParamFwdReg)) { + if (ParamValue->first.isImm()) { + int64_t Val = ParamValue->first.getImm(); + DbgValueLoc DbgLocVal(ParamValue->second, Val); + finishCallSiteParam(DbgLocVal, ParamFwdReg); + } else if (ParamValue->first.isReg()) { + Register RegLoc = ParamValue->first.getReg(); + // TODO: For now, there is no use of describing the value loaded into the + // register that is also the source registers (e.g. $r0 = add $r0, x). + if (ParamFwdReg == RegLoc) + continue; + + unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); + Register FP = TRI->getFrameRegister(*MF); + bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP); + if (TRI->isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) { + DbgValueLoc DbgLocVal(ParamValue->second, + MachineLocation(RegLoc, + /*IsIndirect=*/IsSPorFP)); + finishCallSiteParam(DbgLocVal, ParamFwdReg); + // TODO: Add support for entry value plus an expression. + } else if (ShouldTryEmitEntryVals && + ParamValue->second->getNumElements() == 0) { + ForwardedRegWorklist.insert(RegLoc); + RegsForEntryValues[RegLoc] = ParamFwdReg; + } } } } @@ -707,6 +724,12 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, // Emit call site entries for each call or tail call in the function. for (const MachineBasicBlock &MBB : MF) { for (const MachineInstr &MI : MBB.instrs()) { + // Bundles with call in them will pass the isCall() test below but do not + // have callee operand information so skip them here. Iterator will + // eventually reach the call MI. + if (MI.isBundle()) + continue; + // Skip instructions which aren't calls. Both calls and tail-calling jump // instructions (e.g TAILJMPd64) are classified correctly here. if (!MI.isCall()) @@ -735,25 +758,45 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, if (!CalleeDecl || !CalleeDecl->getSubprogram()) continue; CalleeSP = CalleeDecl->getSubprogram(); + + if (CalleeSP->isDefinition()) { + // Ensure that a subprogram DIE for the callee is available in the + // appropriate CU. + constructSubprogramDefinitionDIE(CalleeSP); + } else { + // Create the declaration DIE if it is missing. This is required to + // support compilation of old bitcode with an incomplete list of + // retained metadata. + CU.getOrCreateSubprogramDIE(CalleeSP); + } } // TODO: Omit call site entries for runtime calls (objc_msgSend, etc). bool IsTail = TII->isTailCall(MI); + // If MI is in a bundle, the label was created after the bundle since + // EmitFunctionBody iterates over top-level MIs. Get that top-level MI + // to search for that label below. + const MachineInstr *TopLevelCallMI = + MI.isInsideBundle() ? &*getBundleStart(MI.getIterator()) : &MI; + // For tail calls, for non-gdb tuning, no return PC information is needed. // For regular calls (and tail calls in GDB tuning), the return PC // is needed to disambiguate paths in the call graph which could lead to // some target function. const MCExpr *PCOffset = - (IsTail && !tuneForGDB()) ? nullptr - : getFunctionLocalOffsetAfterInsn(&MI); + (IsTail && !tuneForGDB()) + ? nullptr + : getFunctionLocalOffsetAfterInsn(TopLevelCallMI); - // Address of a call-like instruction for a normal call or a jump-like - // instruction for a tail call. This is needed for GDB + DWARF 4 tuning. + // Return address of a call-like instruction for a normal call or a + // jump-like instruction for a tail call. This is needed for + // GDB + DWARF 4 tuning. const MCSymbol *PCAddr = - ApplyGNUExtensions ? const_cast<MCSymbol*>(getLabelAfterInsn(&MI)) - : nullptr; + ApplyGNUExtensions + ? const_cast<MCSymbol *>(getLabelAfterInsn(TopLevelCallMI)) + : nullptr; assert((IsTail || PCOffset || PCAddr) && "Call without return PC information"); @@ -837,10 +880,13 @@ void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, // This CU is either a clang module DWO or a skeleton CU. NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, DIUnit->getDWOId()); - if (!DIUnit->getSplitDebugFilename().empty()) + if (!DIUnit->getSplitDebugFilename().empty()) { // This is a prefabricated skeleton CU. - NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, - DIUnit->getSplitDebugFilename()); + dwarf::Attribute attrDWOName = getDwarfVersion() >= 5 + ? dwarf::DW_AT_dwo_name + : dwarf::DW_AT_GNU_dwo_name; + NewCU.addString(Die, attrDWOName, DIUnit->getSplitDebugFilename()); + } } } // Create new DwarfCompileUnit for the given metadata node with tag @@ -878,11 +924,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); } - // Create DIEs for function declarations used for call site debug info. - for (auto Scope : DIUnit->getRetainedTypes()) - if (auto *SP = dyn_cast_or_null<DISubprogram>(Scope)) - NewCU.getOrCreateSubprogramDIE(SP); - CUMap.insert({DIUnit, &NewCU}); CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); return NewCU; @@ -974,6 +1015,7 @@ void DwarfDebug::beginModule() { // Create the symbol that points to the first entry following the debug // address table (.debug_addr) header. AddrPool.setLabel(Asm->createTempSymbol("addr_table_base")); + 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 @@ -1077,11 +1119,17 @@ void DwarfDebug::finalizeModuleInfo() { // If we're splitting the dwarf out now that we've got the entire // CU then add the dwo id to it. auto *SkCU = TheCU.getSkeleton(); - if (useSplitDwarf() && !TheCU.getUnitDie().children().empty()) { + + bool HasSplitUnit = SkCU && !TheCU.getUnitDie().children().empty(); + + if (HasSplitUnit) { + dwarf::Attribute attrDWOName = getDwarfVersion() >= 5 + ? dwarf::DW_AT_dwo_name + : dwarf::DW_AT_GNU_dwo_name; finishUnitAttributes(TheCU.getCUNode(), TheCU); - TheCU.addString(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + TheCU.addString(TheCU.getUnitDie(), attrDWOName, Asm->TM.Options.MCOptions.SplitDwarfFile); - SkCU->addString(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + SkCU->addString(SkCU->getUnitDie(), attrDWOName, Asm->TM.Options.MCOptions.SplitDwarfFile); // Emit a unique identifier for this CU. uint64_t ID = @@ -1127,29 +1175,34 @@ void DwarfDebug::finalizeModuleInfo() { // We don't keep track of which addresses are used in which CU so this // is a bit pessimistic under LTO. - if (!AddrPool.isEmpty() && - (getDwarfVersion() >= 5 || - (SkCU && !TheCU.getUnitDie().children().empty()))) + if ((!AddrPool.isEmpty() || TheCU.hasRangeLists()) && + (getDwarfVersion() >= 5 || HasSplitUnit)) U.addAddrTableBase(); if (getDwarfVersion() >= 5) { if (U.hasRangeLists()) U.addRnglistsBase(); - if (!DebugLocs.getLists().empty() && !useSplitDwarf()) { - DebugLocs.setSym(Asm->createTempSymbol("loclists_table_base")); - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base, - DebugLocs.getSym(), - TLOF.getDwarfLoclistsSection()->getBeginSymbol()); + if (!DebugLocs.getLists().empty()) { + if (!useSplitDwarf()) + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_loclists_base, + DebugLocs.getSym(), + TLOF.getDwarfLoclistsSection()->getBeginSymbol()); } } auto *CUNode = cast<DICompileUnit>(P.first); // If compile Unit has macros, emit "DW_AT_macro_info" attribute. - if (CUNode->getMacros()) - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, - U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + if (CUNode->getMacros()) { + if (useSplitDwarf()) + TheCU.addSectionDelta(TheCU.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoDWOSection()->getBeginSymbol()); + else + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + } } // Emit all frontend-produced Skeleton CUs, i.e., Clang modules. @@ -1185,9 +1238,10 @@ void DwarfDebug::endModule() { emitDebugStr(); if (useSplitDwarf()) + // Emit debug_loc.dwo/debug_loclists.dwo section. emitDebugLocDWO(); else - // Emit info into a debug loc section. + // Emit debug_loc/debug_loclists section. emitDebugLoc(); // Corresponding abbreviations into a abbrev section. @@ -1203,8 +1257,12 @@ void DwarfDebug::endModule() { // Emit info into a debug ranges section. emitDebugRanges(); + if (useSplitDwarf()) + // Emit info into a debug macinfo.dwo section. + emitDebugMacinfoDWO(); + else // Emit info into a debug macinfo section. - emitDebugMacinfo(); + emitDebugMacinfo(); if (useSplitDwarf()) { emitDebugStrDWO(); @@ -2208,6 +2266,11 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) return; return DwarfExpr.addExpression(std::move(Cursor)); + } else if (Value.isTargetIndexLocation()) { + TargetIndexLocation Loc = Value.getTargetIndexLocation(); + // TODO TargetIndexLocation is a target-independent. Currently only the WebAssembly-specific + // encoding is supported. + DwarfExpr.addWasmLocation(Loc.Index, Loc.Offset); } else if (Value.isConstantFP()) { APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt(); DwarfExpr.addUnsignedConstant(RawBytes); @@ -2242,6 +2305,8 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, DwarfDebug::emitDebugLocValue(AP, BT, Value, DwarfExpr); } DwarfExpr.finalize(); + if (DwarfExpr.TagOffset) + List.setTagOffset(*DwarfExpr.TagOffset); } void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, @@ -2296,7 +2361,7 @@ static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, Asm->OutStreamer->EmitLabel(Holder.getRnglistsTableBaseSym()); for (const RangeSpanList &List : Holder.getRangeLists()) - Asm->EmitLabelDifference(List.getSym(), Holder.getRnglistsTableBaseSym(), + Asm->EmitLabelDifference(List.Label, Holder.getRnglistsTableBaseSym(), 4); return TableEnd; @@ -2313,12 +2378,13 @@ static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm, const auto &DebugLocs = DD.getDebugLocs(); - // FIXME: Generate the offsets table and use DW_FORM_loclistx with the - // DW_AT_loclists_base attribute. Until then set the number of offsets to 0. Asm->OutStreamer->AddComment("Offset entry count"); - Asm->emitInt32(0); + Asm->emitInt32(DebugLocs.getLists().size()); Asm->OutStreamer->EmitLabel(DebugLocs.getSym()); + for (const auto &List : DebugLocs.getLists()) + Asm->EmitLabelDifference(List.Label, DebugLocs.getSym(), 4); + return TableEnd; } @@ -2418,32 +2484,27 @@ static void emitRangeList( } } +// Handles emission of both debug_loclist / debug_loclist.dwo static void emitLocList(DwarfDebug &DD, AsmPrinter *Asm, const DebugLocStream::List &List) { - emitRangeList( - DD, Asm, List.Label, DD.getDebugLocs().getEntries(List), *List.CU, - dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair, - dwarf::DW_LLE_startx_length, dwarf::DW_LLE_end_of_list, - llvm::dwarf::LocListEncodingString, - /* ShouldUseBaseAddress */ true, - [&](const DebugLocStream::Entry &E) { - DD.emitDebugLocEntryLocation(E, List.CU); - }); + emitRangeList(DD, Asm, List.Label, DD.getDebugLocs().getEntries(List), + *List.CU, dwarf::DW_LLE_base_addressx, + dwarf::DW_LLE_offset_pair, dwarf::DW_LLE_startx_length, + dwarf::DW_LLE_end_of_list, llvm::dwarf::LocListEncodingString, + /* ShouldUseBaseAddress */ true, + [&](const DebugLocStream::Entry &E) { + DD.emitDebugLocEntryLocation(E, List.CU); + }); } -// Emit locations into the .debug_loc/.debug_rnglists section. -void DwarfDebug::emitDebugLoc() { +void DwarfDebug::emitDebugLocImpl(MCSection *Sec) { if (DebugLocs.getLists().empty()) return; + Asm->OutStreamer->SwitchSection(Sec); + MCSymbol *TableEnd = nullptr; - if (getDwarfVersion() >= 5) { - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfLoclistsSection()); + if (getDwarfVersion() >= 5) TableEnd = emitLoclistsTableHeader(Asm, *this); - } else { - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfLocSection()); - } for (const auto &List : DebugLocs.getLists()) emitLocList(*this, Asm, List); @@ -2452,11 +2513,28 @@ void DwarfDebug::emitDebugLoc() { Asm->OutStreamer->EmitLabel(TableEnd); } +// Emit locations into the .debug_loc/.debug_loclists section. +void DwarfDebug::emitDebugLoc() { + emitDebugLocImpl( + getDwarfVersion() >= 5 + ? Asm->getObjFileLowering().getDwarfLoclistsSection() + : Asm->getObjFileLowering().getDwarfLocSection()); +} + +// Emit locations into the .debug_loc.dwo/.debug_loclists.dwo section. void DwarfDebug::emitDebugLocDWO() { + if (getDwarfVersion() >= 5) { + emitDebugLocImpl( + Asm->getObjFileLowering().getDwarfLoclistsDWOSection()); + + return; + } + for (const auto &List : DebugLocs.getLists()) { Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfLocDWOSection()); Asm->OutStreamer->EmitLabel(List.Label); + for (const auto &Entry : DebugLocs.getEntries(List)) { // GDB only supports startx_length in pre-standard split-DWARF. // (in v5 standard loclists, it currently* /only/ supports base_address + @@ -2468,8 +2546,9 @@ void DwarfDebug::emitDebugLocDWO() { Asm->emitInt8(dwarf::DW_LLE_startx_length); unsigned idx = AddrPool.getIndex(Entry.Begin); Asm->EmitULEB128(idx); + // Also the pre-standard encoding is slightly different, emitting this as + // an address-length entry here, but its a ULEB128 in DWARFv5 loclists. Asm->EmitLabelDifference(Entry.End, Entry.Begin, 4); - emitDebugLocEntryLocation(Entry, List.CU); } Asm->emitInt8(dwarf::DW_LLE_end_of_list); @@ -2639,19 +2718,33 @@ void DwarfDebug::emitDebugARanges() { /// Emit a single range list. We handle both DWARF v5 and earlier. static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, const RangeSpanList &List) { - emitRangeList(DD, Asm, List.getSym(), List.getRanges(), List.getCU(), + emitRangeList(DD, Asm, List.Label, List.Ranges, *List.CU, dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair, dwarf::DW_RLE_startx_length, dwarf::DW_RLE_end_of_list, llvm::dwarf::RangeListEncodingString, - List.getCU().getCUNode()->getRangesBaseAddress() || + List.CU->getCUNode()->getRangesBaseAddress() || DD.getDwarfVersion() >= 5, [](auto) {}); } -static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm, - const DwarfFile &Holder, MCSymbol *TableEnd) { +void DwarfDebug::emitDebugRangesImpl(const DwarfFile &Holder, MCSection *Section) { + if (Holder.getRangeLists().empty()) + return; + + assert(useRangesSection()); + assert(!CUMap.empty()); + assert(llvm::any_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return !Pair.second->getCUNode()->isDebugDirectivesOnly(); + })); + + Asm->OutStreamer->SwitchSection(Section); + + MCSymbol *TableEnd = nullptr; + if (getDwarfVersion() >= 5) + TableEnd = emitRnglistsTableHeader(Asm, Holder); + for (const RangeSpanList &List : Holder.getRangeLists()) - emitRangeList(DD, Asm, List); + emitRangeList(*this, Asm, List); if (TableEnd) Asm->OutStreamer->EmitLabel(TableEnd); @@ -2660,55 +2753,17 @@ static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm, /// Emit address ranges into the .debug_ranges section or into the DWARF v5 /// .debug_rnglists section. void DwarfDebug::emitDebugRanges() { - if (CUMap.empty()) - return; - const auto &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - if (Holder.getRangeLists().empty()) - return; - - assert(useRangesSection()); - assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { - return Pair.second->getCUNode()->isDebugDirectivesOnly(); - })); - - // Start the dwarf ranges section. - MCSymbol *TableEnd = nullptr; - if (getDwarfVersion() >= 5) { - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfRnglistsSection()); - TableEnd = emitRnglistsTableHeader(Asm, Holder); - } else - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfRangesSection()); - - emitDebugRangesImpl(*this, Asm, Holder, TableEnd); + emitDebugRangesImpl(Holder, + getDwarfVersion() >= 5 + ? Asm->getObjFileLowering().getDwarfRnglistsSection() + : Asm->getObjFileLowering().getDwarfRangesSection()); } void DwarfDebug::emitDebugRangesDWO() { - assert(useSplitDwarf()); - - if (CUMap.empty()) - return; - - const auto &Holder = InfoHolder; - - if (Holder.getRangeLists().empty()) - return; - - assert(getDwarfVersion() >= 5); - assert(useRangesSection()); - assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { - return Pair.second->getCUNode()->isDebugDirectivesOnly(); - })); - - // Start the dwarf ranges section. - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfRnglistsDWOSection()); - MCSymbol *TableEnd = emitRnglistsTableHeader(Asm, Holder); - - emitDebugRangesImpl(*this, Asm, Holder, TableEnd); + emitDebugRangesImpl(InfoHolder, + Asm->getObjFileLowering().getDwarfRnglistsDWOSection()); } void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { @@ -2745,35 +2800,30 @@ void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) { Asm->EmitULEB128(dwarf::DW_MACINFO_end_file); } -/// Emit macros into a debug macinfo section. -void DwarfDebug::emitDebugMacinfo() { - if (CUMap.empty()) - return; - - if (llvm::all_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { - return Pair.second->getCUNode()->isDebugDirectivesOnly(); - })) - return; - - // Start the dwarf macinfo section. - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfMacinfoSection()); - +void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) { for (const auto &P : CUMap) { auto &TheCU = *P.second; - if (TheCU.getCUNode()->isDebugDirectivesOnly()) - continue; auto *SkCU = TheCU.getSkeleton(); DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; auto *CUNode = cast<DICompileUnit>(P.first); DIMacroNodeArray Macros = CUNode->getMacros(); - if (!Macros.empty()) { - Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); - handleMacroNodes(Macros, U); - } + if (Macros.empty()) + continue; + Asm->OutStreamer->SwitchSection(Section); + Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); + handleMacroNodes(Macros, U); + Asm->OutStreamer->AddComment("End Of Macro List Mark"); + Asm->emitInt8(0); } - Asm->OutStreamer->AddComment("End Of Macro List Mark"); - Asm->emitInt8(0); +} + +/// Emit macros into a debug macinfo section. +void DwarfDebug::emitDebugMacinfo() { + emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoSection()); +} + +void DwarfDebug::emitDebugMacinfoDWO() { + emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoDWOSection()); } // DWARF5 Experimental Separate Dwarf emitters. @@ -2792,7 +2842,8 @@ void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { auto OwnedUnit = std::make_unique<DwarfCompileUnit>( - CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder); + CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder, + UnitKind::Skeleton); DwarfCompileUnit &NewCU = *OwnedUnit; NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index c8c511f67c2a..fd82b1f98055 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -118,6 +118,9 @@ public: class DbgVariable : public DbgEntity { /// Offset in DebugLocs. unsigned DebugLocListIndex = ~0u; + /// DW_OP_LLVM_tag_offset value from DebugLocs. + Optional<uint8_t> DebugLocListTagOffset; + /// Single value location description. std::unique_ptr<DbgValueLoc> ValueLoc = nullptr; @@ -174,6 +177,8 @@ public: void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; } unsigned getDebugLocListIndex() const { return DebugLocListIndex; } + void setDebugLocListTagOffset(uint8_t O) { DebugLocListTagOffset = O; } + Optional<uint8_t> getDebugLocListTagOffset() const { return DebugLocListTagOffset; } StringRef getName() const { return getVariable()->getName(); } const DbgValueLoc *getValueLoc() const { return ValueLoc.get(); } /// Get the FI entries, sorted by fragment offset. @@ -437,6 +442,9 @@ class DwarfDebug : public DebugHandlerBase { /// Construct a DIE for this abstract scope. void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope); + /// Construct a DIE for the subprogram definition \p SP and return it. + DIE &constructSubprogramDefinitionDIE(const DISubprogram *SP); + /// Construct DIEs for call site entries describing the calls in \p MF. void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU, DIE &ScopeDIE, const MachineFunction &MF); @@ -498,15 +506,21 @@ class DwarfDebug : public DebugHandlerBase { /// Emit variable locations into a debug loc dwo section. void emitDebugLocDWO(); + void emitDebugLocImpl(MCSection *Sec); + /// Emit address ranges into a debug aranges section. void emitDebugARanges(); /// Emit address ranges into a debug ranges section. void emitDebugRanges(); void emitDebugRangesDWO(); + void emitDebugRangesImpl(const DwarfFile &Holder, MCSection *Section); /// Emit macros into a debug macinfo section. void emitDebugMacinfo(); + /// Emit macros into a debug macinfo.dwo section. + void emitDebugMacinfoDWO(); + void emitDebugMacinfoImpl(MCSection *Section); void emitMacro(DIMacro &M); void emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U); void handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 1c5a244d7c5d..310647f15a5e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -155,20 +155,18 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, CurSubReg.set(Offset, Offset + Size); // If this sub-register has a DWARF number and we haven't covered - // its range, emit a DWARF piece for it. - if (CurSubReg.test(Coverage)) { + // its range, and its range covers the value, emit a DWARF piece for it. + if (Offset < MaxSize && CurSubReg.test(Coverage)) { // Emit a piece for any gap in the coverage. if (Offset > CurPos) - DwarfRegs.push_back({-1, Offset - CurPos, "no DWARF register encoding"}); + DwarfRegs.push_back( + {-1, Offset - CurPos, "no DWARF register encoding"}); DwarfRegs.push_back( {Reg, std::min<unsigned>(Size, MaxSize - Offset), "sub-register"}); - if (Offset >= MaxSize) - break; - - // Mark it as emitted. - Coverage.set(Offset, Offset + Size); - CurPos = Offset + Size; } + // Mark it as emitted. + Coverage.set(Offset, Offset + Size); + CurPos = Offset + Size; } // Failed to find any DWARF encoding. if (CurPos == 0) @@ -246,8 +244,8 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, // a call site parameter expression and if that expression is just a register // location, emit it with addBReg and offset 0, because we should emit a DWARF // expression representing a value, rather than a location. - if (!isMemoryLocation() && !HasComplexExpression && - (!isParameterValue() || isEntryValue())) { + if (!isMemoryLocation() && !HasComplexExpression && (!isParameterValue() || + isEntryValue())) { for (auto &Reg : DwarfRegs) { if (Reg.DwarfRegNo >= 0) addReg(Reg.DwarfRegNo, Reg.Comment); @@ -391,6 +389,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base // location. assert(OffsetInBits >= FragmentOffset && "fragment offset not added?"); + assert(SizeInBits >= OffsetInBits - FragmentOffset && "size underflow"); // If addMachineReg already emitted DW_OP_piece operations to represent // a super-register by splicing together sub-registers, subtract the size @@ -436,9 +435,6 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, break; case dwarf::DW_OP_deref: assert(!isRegisterLocation()); - // For more detailed explanation see llvm.org/PR43343. - assert(!isParameterValue() && "Parameter entry values should not be " - "dereferenced due to safety reasons."); if (!isMemoryLocation() && ::isMemoryLocation(ExprCursor)) // Turning this into a memory location description makes the deref // implicit. @@ -576,3 +572,11 @@ void DwarfExpression::emitLegacyZExt(unsigned FromBits) { emitUnsigned((1ULL << FromBits) - 1); emitOp(dwarf::DW_OP_and); } + +void DwarfExpression::addWasmLocation(unsigned Index, int64_t Offset) { + assert(LocationKind == Implicit || LocationKind == Unknown); + LocationKind = Implicit; + emitOp(dwarf::DW_OP_WASM_location); + emitUnsigned(Index); + emitSigned(Offset); +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 1ad46669f9b2..46c07b1d5b6b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -337,6 +337,10 @@ public: void emitLegacySExt(unsigned FromBits); void emitLegacyZExt(unsigned FromBits); + + /// Emit location information expressed via WebAssembly location + offset + /// The Index is an identifier for locals, globals or operand stack. + void addWasmLocation(unsigned Index, int64_t Offset); }; /// DwarfExpression implementation for .debug_loc entries. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp index e3c9095d1343..e5c4db58f477 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -126,6 +126,6 @@ void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) { std::pair<uint32_t, RangeSpanList *> DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) { CURangeLists.push_back( - RangeSpanList(Asm->createTempSymbol("debug_ranges"), CU, std::move(R))); + RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)}); return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back()); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h index 35fa51fb24c4..cf293d7534d0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h @@ -37,21 +37,12 @@ struct RangeSpan { const MCSymbol *End; }; -class RangeSpanList { -private: +struct RangeSpanList { // Index for locating within the debug_range section this particular span. - MCSymbol *RangeSym; + MCSymbol *Label; const DwarfCompileUnit *CU; // List of ranges. SmallVector<RangeSpan, 2> Ranges; - -public: - RangeSpanList(MCSymbol *Sym, const DwarfCompileUnit &CU, - SmallVector<RangeSpan, 2> Ranges) - : RangeSym(Sym), CU(&CU), Ranges(std::move(Ranges)) {} - MCSymbol *getSym() const { return RangeSym; } - const DwarfCompileUnit &getCU() const { return *CU; } - const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; } }; class DwarfFile { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 37c68c085792..1aba956c48de 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -188,8 +188,9 @@ int64_t DwarfUnit::getDefaultLowerBound() const { /// Check whether the DIE for this MDNode can be shared across CUs. bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const { - // When the MDNode can be part of the type system, the DIE can be shared - // across CUs. + // When the MDNode can be part of the type system (this includes subprogram + // declarations *and* subprogram definitions, even local definitions), the + // DIE must be shared across CUs. // Combining type units and cross-CU DIE sharing is lower value (since // cross-CU DIE sharing is used in LTO and removes type redundancy at that // level already) but may be implementable for some value in projects @@ -197,9 +198,7 @@ bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const { // together. if (isDwoUnit() && !DD->shareAcrossDWOCUs()) return false; - return (isa<DIType>(D) || - (isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) && - !DD->generateTypeUnits(); + return (isa<DIType>(D) || isa<DISubprogram>(D)) && !DD->generateTypeUnits(); } DIE *DwarfUnit::getDIE(const DINode *D) const { @@ -800,6 +799,15 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { if (!Name.empty()) addString(Buffer, dwarf::DW_AT_name, Name); + // If alignment is specified for a typedef , create and insert DW_AT_alignment + // attribute in DW_TAG_typedef DIE. + if (Tag == dwarf::DW_TAG_typedef && DD->getDwarfVersion() >= 5) { + uint32_t AlignInBytes = DTy->getAlignInBytes(); + if (AlignInBytes > 0) + addUInt(Buffer, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, + AlignInBytes); + } + // Add size if non-zero (derived types might be zero-sized.) if (Size && Tag != dwarf::DW_TAG_pointer_type && Tag != dwarf::DW_TAG_ptr_to_member_type @@ -1114,8 +1122,8 @@ DIE *DwarfUnit::getOrCreateModule(const DIModule *M) { M->getConfigurationMacros()); if (!M->getIncludePath().empty()) addString(MDie, dwarf::DW_AT_LLVM_include_path, M->getIncludePath()); - if (!M->getISysRoot().empty()) - addString(MDie, dwarf::DW_AT_LLVM_isysroot, M->getISysRoot()); + if (!M->getSysRoot().empty()) + addString(MDie, dwarf::DW_AT_LLVM_sysroot, M->getSysRoot()); return &MDie; } @@ -1224,6 +1232,9 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, Language == dwarf::DW_LANG_ObjC)) addFlag(SPDie, dwarf::DW_AT_prototyped); + if (SP->isObjCDirect()) + addFlag(SPDie, dwarf::DW_AT_APPLE_objc_direct); + unsigned CC = 0; DITypeRefArray Args; if (const DISubroutineType *SPTy = SP->getType()) { @@ -1307,6 +1318,9 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, addFlag(SPDie, dwarf::DW_AT_elemental); if (SP->isRecursive()) addFlag(SPDie, dwarf::DW_AT_recursive); + + if (DD->getDwarfVersion() >= 5 && SP->isDeleted()) + addFlag(SPDie, dwarf::DW_AT_deleted); } void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp index 290be81c6baa..914308d9147e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for writing Win64 exception info into asm files. +// This file contains support for writing the metadata for Windows Control Flow +// Guard, including address-taken functions, and valid longjmp targets. // //===----------------------------------------------------------------------===// @@ -17,6 +18,7 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/Instructions.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCStreamer.h" @@ -29,16 +31,69 @@ WinCFGuard::WinCFGuard(AsmPrinter *A) : AsmPrinterHandler(), Asm(A) {} WinCFGuard::~WinCFGuard() {} +void WinCFGuard::endFunction(const MachineFunction *MF) { + + // Skip functions without any longjmp targets. + if (MF->getLongjmpTargets().empty()) + return; + + // Copy the function's longjmp targets to a module-level list. + LongjmpTargets.insert(LongjmpTargets.end(), MF->getLongjmpTargets().begin(), + MF->getLongjmpTargets().end()); +} + +/// Returns true if this function's address is escaped in a way that might make +/// it an indirect call target. Function::hasAddressTaken gives different +/// results when a function is called directly with a function prototype +/// mismatch, which requires a cast. +static bool isPossibleIndirectCallTarget(const Function *F) { + SmallVector<const Value *, 4> Users{F}; + while (!Users.empty()) { + const Value *FnOrCast = Users.pop_back_val(); + for (const Use &U : FnOrCast->uses()) { + const User *FnUser = U.getUser(); + if (isa<BlockAddress>(FnUser)) + continue; + if (const auto *Call = dyn_cast<CallBase>(FnUser)) { + if (!Call->isCallee(&U)) + return true; + } else if (isa<Instruction>(FnUser)) { + // Consider any other instruction to be an escape. This has some weird + // consequences like no-op intrinsics being an escape or a store *to* a + // function address being an escape. + return true; + } else if (const auto *C = dyn_cast<Constant>(FnUser)) { + // If this is a constant pointer cast of the function, don't consider + // this escape. Analyze the uses of the cast as well. This ensures that + // direct calls with mismatched prototypes don't end up in the CFG + // table. Consider other constants, such as vtable initializers, to + // escape the function. + if (C->stripPointerCasts() == F) + Users.push_back(FnUser); + else + return true; + } + } + } + return false; +} + void WinCFGuard::endModule() { const Module *M = Asm->MMI->getModule(); std::vector<const Function *> Functions; for (const Function &F : *M) - if (F.hasAddressTaken()) + if (isPossibleIndirectCallTarget(&F)) Functions.push_back(&F); - if (Functions.empty()) + if (Functions.empty() && LongjmpTargets.empty()) return; auto &OS = *Asm->OutStreamer; OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection()); for (const Function *F : Functions) OS.EmitCOFFSymbolIndex(Asm->getSymbol(F)); + + // Emit the symbol index of each longjmp target. + OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGLJMPSection()); + for (const MCSymbol *S : LongjmpTargets) { + OS.EmitCOFFSymbolIndex(S); + } } diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h index def0a59ab007..494a153b05ba 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h +++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for writing windows exception info into asm files. +// This file contains support for writing the metadata for Windows Control Flow +// Guard, including address-taken functions, and valid longjmp targets. // //===----------------------------------------------------------------------===// @@ -15,12 +16,14 @@ #include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/Support/Compiler.h" +#include <vector> namespace llvm { class LLVM_LIBRARY_VISIBILITY WinCFGuard : public AsmPrinterHandler { /// Target of directive emission. AsmPrinter *Asm; + std::vector<const MCSymbol *> LongjmpTargets; public: WinCFGuard(AsmPrinter *A); @@ -28,7 +31,7 @@ public: void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} - /// Emit the Control Flow Guard function ID table + /// Emit the Control Flow Guard function ID table. void endModule() override; /// Gather pre-function debug information. @@ -39,7 +42,7 @@ public: /// Gather post-function debug information. /// Please note that some AsmPrinter implementations may not call /// beginFunction at all. - void endFunction(const MachineFunction *MF) override {} + void endFunction(const MachineFunction *MF) override; /// Process beginning of an instruction. void beginInstruction(const MachineInstr *MI) override {} |