diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 2888 |
1 files changed, 2888 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp new file mode 100644 index 000000000000..71bb2b0858cc --- /dev/null +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -0,0 +1,2888 @@ +//===- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfDebug.h" +#include "ByteStreamer.h" +#include "DIEHash.h" +#include "DebugLocEntry.h" +#include "DebugLocStream.h" +#include "DwarfCompileUnit.h" +#include "DwarfExpression.h" +#include "DwarfFile.h" +#include "DwarfUnit.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/AccelTable.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DIE.h" +#include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MD5.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <string> +#include <utility> +#include <vector> + +using namespace llvm; + +#define DEBUG_TYPE "dwarfdebug" + +static cl::opt<bool> +DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, + cl::desc("Disable debug info printing")); + +static cl::opt<bool> UseDwarfRangesBaseAddressSpecifier( + "use-dwarf-ranges-base-address-specifier", cl::Hidden, + cl::desc("Use base address specifiers in debug_ranges"), cl::init(false)); + +static cl::opt<bool> GenerateARangeSection("generate-arange-section", + cl::Hidden, + cl::desc("Generate dwarf aranges"), + cl::init(false)); + +static cl::opt<bool> + GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, + cl::desc("Generate DWARF4 type units."), + cl::init(false)); + +static cl::opt<bool> SplitDwarfCrossCuReferences( + "split-dwarf-cross-cu-references", cl::Hidden, + cl::desc("Enable cross-cu references in DWO files"), cl::init(false)); + +enum DefaultOnOff { Default, Enable, Disable }; + +static cl::opt<DefaultOnOff> UnknownLocations( + "use-unknown-locations", cl::Hidden, + cl::desc("Make an absence of debug location information explicit."), + cl::values(clEnumVal(Default, "At top of block or after label"), + clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")), + cl::init(Default)); + +static cl::opt<AccelTableKind> AccelTables( + "accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."), + cl::values(clEnumValN(AccelTableKind::Default, "Default", + "Default for platform"), + clEnumValN(AccelTableKind::None, "Disable", "Disabled."), + clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), + clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")), + cl::init(AccelTableKind::Default)); + +static cl::opt<DefaultOnOff> +DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, + cl::desc("Use inlined strings rather than string section."), + cl::values(clEnumVal(Default, "Default for platform"), + clEnumVal(Enable, "Enabled"), + clEnumVal(Disable, "Disabled")), + cl::init(Default)); + +static cl::opt<bool> + NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden, + cl::desc("Disable emission .debug_ranges section."), + cl::init(false)); + +static cl::opt<DefaultOnOff> DwarfSectionsAsReferences( + "dwarf-sections-as-references", cl::Hidden, + cl::desc("Use sections+offset as references rather than labels."), + cl::values(clEnumVal(Default, "Default for platform"), + clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), + cl::init(Default)); + +enum LinkageNameOption { + DefaultLinkageNames, + AllLinkageNames, + AbstractLinkageNames +}; + +static cl::opt<LinkageNameOption> + DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, + cl::desc("Which DWARF linkage-name attributes to emit."), + cl::values(clEnumValN(DefaultLinkageNames, "Default", + "Default for platform"), + clEnumValN(AllLinkageNames, "All", "All"), + clEnumValN(AbstractLinkageNames, "Abstract", + "Abstract subprograms")), + cl::init(DefaultLinkageNames)); + +static const char *const DWARFGroupName = "dwarf"; +static const char *const DWARFGroupDescription = "DWARF Emission"; +static const char *const DbgTimerName = "writer"; +static const char *const DbgTimerDescription = "DWARF Debug Writer"; +static constexpr unsigned ULEB128PadSize = 4; + +void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) { + BS.EmitInt8( + Op, Comment ? Twine(Comment) + " " + dwarf::OperationEncodingString(Op) + : dwarf::OperationEncodingString(Op)); +} + +void DebugLocDwarfExpression::emitSigned(int64_t Value) { + BS.EmitSLEB128(Value, Twine(Value)); +} + +void DebugLocDwarfExpression::emitUnsigned(uint64_t Value) { + BS.EmitULEB128(Value, Twine(Value)); +} + +void DebugLocDwarfExpression::emitData1(uint8_t Value) { + BS.EmitInt8(Value, Twine(Value)); +} + +void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) { + assert(Idx < (1ULL << (ULEB128PadSize * 7)) && "Idx wont fit"); + BS.EmitULEB128(Idx, Twine(Idx), ULEB128PadSize); +} + +bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, + unsigned MachineReg) { + // This information is not available while emitting .debug_loc entries. + return false; +} + +bool DbgVariable::isBlockByrefVariable() const { + assert(getVariable() && "Invalid complex DbgVariable!"); + return getVariable()->getType()->isBlockByrefStruct(); +} + +const DIType *DbgVariable::getType() const { + DIType *Ty = getVariable()->getType(); + // FIXME: isBlockByrefVariable should be reformulated in terms of complex + // addresses instead. + if (Ty->isBlockByrefStruct()) { + /* Byref variables, in Blocks, are declared by the programmer as + "SomeType VarName;", but the compiler creates a + __Block_byref_x_VarName struct, and gives the variable VarName + either the struct, or a pointer to the struct, as its type. This + is necessary for various behind-the-scenes things the compiler + needs to do with by-reference variables in blocks. + + However, as far as the original *programmer* is concerned, the + variable should still have type 'SomeType', as originally declared. + + The following function dives into the __Block_byref_x_VarName + struct to find the original type of the variable. This will be + passed back to the code generating the type for the Debug + Information Entry for the variable 'VarName'. 'VarName' will then + have the original type 'SomeType' in its debug information. + + The original type 'SomeType' will be the type of the field named + 'VarName' inside the __Block_byref_x_VarName struct. + + NOTE: In order for this to not completely fail on the debugger + side, the Debug Information Entry for the variable VarName needs to + have a DW_AT_location that tells the debugger how to unwind through + the pointers and __Block_byref_x_VarName struct to find the actual + value of the variable. The function addBlockByrefType does this. */ + DIType *subType = Ty; + uint16_t tag = Ty->getTag(); + + if (tag == dwarf::DW_TAG_pointer_type) + subType = cast<DIDerivedType>(Ty)->getBaseType(); + + auto Elements = cast<DICompositeType>(subType)->getElements(); + for (unsigned i = 0, N = Elements.size(); i < N; ++i) { + auto *DT = cast<DIDerivedType>(Elements[i]); + if (getName() == DT->getName()) + return DT->getBaseType(); + } + } + return Ty; +} + +/// Get .debug_loc entry for the instruction range starting at MI. +static DbgValueLoc getDebugLocValue(const MachineInstr *MI) { + const DIExpression *Expr = MI->getDebugExpression(); + assert(MI->getNumOperands() == 4); + if (MI->getOperand(0).isReg()) { + auto RegOp = MI->getOperand(0); + auto Op1 = MI->getOperand(1); + // If the second operand is an immediate, this is a + // register-indirect address. + assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset"); + MachineLocation MLoc(RegOp.getReg(), Op1.isImm()); + return DbgValueLoc(Expr, MLoc); + } + if (MI->getOperand(0).isImm()) + return DbgValueLoc(Expr, MI->getOperand(0).getImm()); + if (MI->getOperand(0).isFPImm()) + return DbgValueLoc(Expr, MI->getOperand(0).getFPImm()); + if (MI->getOperand(0).isCImm()) + return DbgValueLoc(Expr, MI->getOperand(0).getCImm()); + + llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); +} + +void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) { + assert(FrameIndexExprs.empty() && "Already initialized?"); + assert(!ValueLoc.get() && "Already initialized?"); + + assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable"); + assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() && + "Wrong inlined-at"); + + ValueLoc = llvm::make_unique<DbgValueLoc>(getDebugLocValue(DbgValue)); + if (auto *E = DbgValue->getDebugExpression()) + if (E->getNumElements()) + FrameIndexExprs.push_back({0, E}); +} + +ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { + if (FrameIndexExprs.size() == 1) + return FrameIndexExprs; + + assert(llvm::all_of(FrameIndexExprs, + [](const FrameIndexExpr &A) { + return A.Expr->isFragment(); + }) && + "multiple FI expressions without DW_OP_LLVM_fragment"); + llvm::sort(FrameIndexExprs, + [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool { + return A.Expr->getFragmentInfo()->OffsetInBits < + B.Expr->getFragmentInfo()->OffsetInBits; + }); + + return FrameIndexExprs; +} + +void DbgVariable::addMMIEntry(const DbgVariable &V) { + assert(DebugLocListIndex == ~0U && !ValueLoc.get() && "not an MMI entry"); + assert(V.DebugLocListIndex == ~0U && !V.ValueLoc.get() && "not an MMI entry"); + assert(V.getVariable() == getVariable() && "conflicting variable"); + assert(V.getInlinedAt() == getInlinedAt() && "conflicting inlined-at location"); + + assert(!FrameIndexExprs.empty() && "Expected an MMI entry"); + assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry"); + + // FIXME: This logic should not be necessary anymore, as we now have proper + // deduplication. However, without it, we currently run into the assertion + // below, which means that we are likely dealing with broken input, i.e. two + // non-fragment entries for the same variable at different frame indices. + if (FrameIndexExprs.size()) { + auto *Expr = FrameIndexExprs.back().Expr; + if (!Expr || !Expr->isFragment()) + return; + } + + for (const auto &FIE : V.FrameIndexExprs) + // Ignore duplicate entries. + if (llvm::none_of(FrameIndexExprs, [&](const FrameIndexExpr &Other) { + return FIE.FI == Other.FI && FIE.Expr == Other.Expr; + })) + FrameIndexExprs.push_back(FIE); + + assert((FrameIndexExprs.size() == 1 || + llvm::all_of(FrameIndexExprs, + [](FrameIndexExpr &FIE) { + return FIE.Expr && FIE.Expr->isFragment(); + })) && + "conflicting locations for variable"); +} + +static AccelTableKind computeAccelTableKind(unsigned DwarfVersion, + bool GenerateTypeUnits, + DebuggerKind Tuning, + const Triple &TT) { + // Honor an explicit request. + if (AccelTables != AccelTableKind::Default) + return AccelTables; + + // Accelerator tables with type units are currently not supported. + if (GenerateTypeUnits) + return AccelTableKind::None; + + // Accelerator tables get emitted if targetting DWARF v5 or LLDB. DWARF v5 + // always implies debug_names. For lower standard versions we use apple + // accelerator tables on apple platforms and debug_names elsewhere. + if (DwarfVersion >= 5) + return AccelTableKind::Dwarf; + if (Tuning == DebuggerKind::LLDB) + return TT.isOSBinFormatMachO() ? AccelTableKind::Apple + : AccelTableKind::Dwarf; + return AccelTableKind::None; +} + +DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) + : DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()), + InfoHolder(A, "info_string", DIEValueAllocator), + SkeletonHolder(A, "skel_string", DIEValueAllocator), + IsDarwin(A->TM.getTargetTriple().isOSDarwin()) { + const Triple &TT = Asm->TM.getTargetTriple(); + + // Make sure we know our "debugger tuning". The target option takes + // precedence; fall back to triple-based defaults. + if (Asm->TM.Options.DebuggerTuning != DebuggerKind::Default) + DebuggerTuning = Asm->TM.Options.DebuggerTuning; + else if (IsDarwin) + DebuggerTuning = DebuggerKind::LLDB; + else if (TT.isPS4CPU()) + DebuggerTuning = DebuggerKind::SCE; + else + DebuggerTuning = DebuggerKind::GDB; + + if (DwarfInlinedStrings == Default) + UseInlineStrings = TT.isNVPTX(); + else + UseInlineStrings = DwarfInlinedStrings == Enable; + + UseLocSection = !TT.isNVPTX(); + + HasAppleExtensionAttributes = tuneForLLDB(); + + // Handle split DWARF. + HasSplitDwarf = !Asm->TM.Options.MCOptions.SplitDwarfFile.empty(); + + // SCE defaults to linkage names only for abstract subprograms. + if (DwarfLinkageNames == DefaultLinkageNames) + UseAllLinkageNames = !tuneForSCE(); + else + UseAllLinkageNames = DwarfLinkageNames == AllLinkageNames; + + unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion; + unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber + : MMI->getModule()->getDwarfVersion(); + // Use dwarf 4 by default if nothing is requested. For NVPTX, use dwarf 2. + DwarfVersion = + TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION); + + UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX(); + + // Use sections as references. Force for NVPTX. + if (DwarfSectionsAsReferences == Default) + UseSectionsAsReferences = TT.isNVPTX(); + else + UseSectionsAsReferences = DwarfSectionsAsReferences == Enable; + + // Don't generate type units for unsupported object file formats. + GenerateTypeUnits = + A->TM.getTargetTriple().isOSBinFormatELF() && GenerateDwarfTypeUnits; + + TheAccelTableKind = computeAccelTableKind( + DwarfVersion, GenerateTypeUnits, DebuggerTuning, A->TM.getTargetTriple()); + + // Work around a GDB bug. GDB doesn't support the standard opcode; + // SCE doesn't support GNU's; LLDB prefers the standard opcode, which + // is defined as of DWARF 3. + // See GDB bug 11616 - DW_OP_form_tls_address is unimplemented + // https://sourceware.org/bugzilla/show_bug.cgi?id=11616 + UseGNUTLSOpcode = tuneForGDB() || DwarfVersion < 3; + + // GDB does not fully support the DWARF 4 representation for bitfields. + UseDWARF2Bitfields = (DwarfVersion < 4) || tuneForGDB(); + + // The DWARF v5 string offsets table has - possibly shared - contributions + // from each compile and type unit each preceded by a header. The string + // offsets table used by the pre-DWARF v5 split-DWARF implementation uses + // a monolithic string offsets table without any header. + UseSegmentedStringOffsetsTable = DwarfVersion >= 5; + + Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); +} + +// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h. +DwarfDebug::~DwarfDebug() = default; + +static bool isObjCClass(StringRef Name) { + return Name.startswith("+") || Name.startswith("-"); +} + +static bool hasObjCCategory(StringRef Name) { + if (!isObjCClass(Name)) + return false; + + return Name.find(") ") != StringRef::npos; +} + +static void getObjCClassCategory(StringRef In, StringRef &Class, + StringRef &Category) { + if (!hasObjCCategory(In)) { + Class = In.slice(In.find('[') + 1, In.find(' ')); + Category = ""; + return; + } + + Class = In.slice(In.find('[') + 1, In.find('(')); + Category = In.slice(In.find('[') + 1, In.find(' ')); +} + +static StringRef getObjCMethodName(StringRef In) { + return In.slice(In.find(' ') + 1, In.find(']')); +} + +// Add the various names to the Dwarf accelerator table names. +void DwarfDebug::addSubprogramNames(const DICompileUnit &CU, + const DISubprogram *SP, DIE &Die) { + if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) + return; + + if (!SP->isDefinition()) + return; + + if (SP->getName() != "") + addAccelName(CU, SP->getName(), Die); + + // If the linkage name is different than the name, go ahead and output that as + // 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))) + addAccelName(CU, SP->getLinkageName(), Die); + + // If this is an Objective-C selector name add it to the ObjC accelerator + // too. + if (isObjCClass(SP->getName())) { + StringRef Class, Category; + getObjCClassCategory(SP->getName(), Class, Category); + addAccelObjC(CU, Class, Die); + if (Category != "") + addAccelObjC(CU, Category, Die); + // Also add the base method name to the name table. + addAccelName(CU, getObjCMethodName(SP->getName()), Die); + } +} + +/// Check whether we should create a DIE for the given Scope, return true +/// if we don't create a DIE (the corresponding DIE is null). +bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { + if (Scope->isAbstractScope()) + return false; + + // We don't create a DIE if there is no Range. + const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges(); + if (Ranges.empty()) + return true; + + if (Ranges.size() > 1) + return false; + + // We don't create a DIE if we have a single Range and the end label + // is null. + return !getLabelAfterInsn(Ranges.front().second); +} + +template <typename Func> static void forBothCUs(DwarfCompileUnit &CU, Func F) { + F(CU); + if (auto *SkelCU = CU.getSkeleton()) + if (CU.getCUNode()->getSplitDebugInlining()) + F(*SkelCU); +} + +bool DwarfDebug::shareAcrossDWOCUs() const { + return SplitDwarfCrossCuReferences; +} + +void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, + LexicalScope *Scope) { + assert(Scope && Scope->getScopeNode()); + assert(Scope->isAbstractScope()); + assert(!Scope->getInlinedAt()); + + auto *SP = cast<DISubprogram>(Scope->getScopeNode()); + + // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram + // was inlined from another compile unit. + if (useSplitDwarf() && !shareAcrossDWOCUs() && !SP->getUnit()->getSplitDebugInlining()) + // Avoid building the original CU if it won't be used + SrcCU.constructAbstractSubprogramScopeDIE(Scope); + else { + auto &CU = getOrCreateDwarfCompileUnit(SP->getUnit()); + if (auto *SkelCU = CU.getSkeleton()) { + (shareAcrossDWOCUs() ? CU : SrcCU) + .constructAbstractSubprogramScopeDIE(Scope); + if (CU.getCUNode()->getSplitDebugInlining()) + SkelCU->constructAbstractSubprogramScopeDIE(Scope); + } else + CU.constructAbstractSubprogramScopeDIE(Scope); + } +} + +void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, + DwarfCompileUnit &CU, DIE &ScopeDIE, + const MachineFunction &MF) { + // Add a call site-related attribute (DWARF5, Sec. 3.3.1.3). Do this only if + // the subprogram is required to have one. + if (!SP.areAllCallsDescribed() || !SP.isDefinition()) + return; + + // Use DW_AT_call_all_calls to express that call site entries are present + // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls + // because one of its requirements is not met: call site entries for + // optimized-out calls are elided. + CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls); + + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "TargetInstrInfo not found: cannot label tail calls"); + + // Emit call site entries for each call or tail call in the function. + for (const MachineBasicBlock &MBB : MF) { + for (const MachineInstr &MI : MBB.instrs()) { + // Skip instructions which aren't calls. Both calls and tail-calling jump + // instructions (e.g TAILJMPd64) are classified correctly here. + if (!MI.isCall()) + continue; + + // TODO: Add support for targets with delay slots (see: beginInstruction). + if (MI.hasDelaySlot()) + return; + + // If this is a direct call, find the callee's subprogram. + const MachineOperand &CalleeOp = MI.getOperand(0); + if (!CalleeOp.isGlobal()) + continue; + const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal()); + if (!CalleeDecl || !CalleeDecl->getSubprogram()) + continue; + + // TODO: Omit call site entries for runtime calls (objc_msgSend, etc). + // TODO: Add support for indirect calls. + + bool IsTail = TII->isTailCall(MI); + + // For tail calls, no return PC information is needed. For regular calls, + // the return PC is needed to disambiguate paths in the call graph which + // could lead to some target function. + const MCExpr *PCOffset = + IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI); + + assert((IsTail || PCOffset) && "Call without return PC information"); + LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> " + << CalleeDecl->getName() << (IsTail ? " [tail]" : "") + << "\n"); + CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(), + IsTail, PCOffset); + } + } +} + +void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { + if (!U.hasDwarfPubSections()) + return; + + U.addFlag(D, dwarf::DW_AT_GNU_pubnames); +} + +void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, + DwarfCompileUnit &NewCU) { + DIE &Die = NewCU.getUnitDie(); + StringRef FN = DIUnit->getFilename(); + + StringRef Producer = DIUnit->getProducer(); + StringRef Flags = DIUnit->getFlags(); + if (!Flags.empty() && !useAppleExtensionAttributes()) { + std::string ProducerWithFlags = Producer.str() + " " + Flags.str(); + NewCU.addString(Die, dwarf::DW_AT_producer, ProducerWithFlags); + } else + NewCU.addString(Die, dwarf::DW_AT_producer, Producer); + + NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + DIUnit->getSourceLanguage()); + NewCU.addString(Die, dwarf::DW_AT_name, FN); + + // Add DW_str_offsets_base to the unit DIE, except for split units. + if (useSegmentedStringOffsetsTable() && !useSplitDwarf()) + NewCU.addStringOffsetsStart(); + + if (!useSplitDwarf()) { + NewCU.initStmtList(); + + // If we're using split dwarf the compilation dir is going to be in the + // skeleton CU and so we don't need to duplicate it here. + if (!CompilationDir.empty()) + NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + + addGnuPubAttributes(NewCU, Die); + } + + if (useAppleExtensionAttributes()) { + if (DIUnit->isOptimized()) + NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized); + + StringRef Flags = DIUnit->getFlags(); + if (!Flags.empty()) + NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags); + + if (unsigned RVer = DIUnit->getRuntimeVersion()) + NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + dwarf::DW_FORM_data1, RVer); + } + + if (DIUnit->getDWOId()) { + // 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()) + // This is a prefabricated skeleton CU. + NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, + DIUnit->getSplitDebugFilename()); + } +} +// Create new DwarfCompileUnit for the given metadata node with tag +// DW_TAG_compile_unit. +DwarfCompileUnit & +DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { + if (auto *CU = CUMap.lookup(DIUnit)) + return *CU; + + CompilationDir = DIUnit->getDirectory(); + + auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( + InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); + 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 + // compilation directory. + if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) + Asm->OutStreamer->emitDwarfFile0Directive( + CompilationDir, DIUnit->getFilename(), + NewCU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource(), + NewCU.getUniqueID()); + + if (useSplitDwarf()) { + NewCU.setSkeleton(constructSkeletonCU(NewCU)); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); + } else { + finishUnitAttributes(DIUnit, NewCU); + 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; +} + +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) { + llvm::sort( + GVEs, [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { + // Sort order: first null exprs, then exprs without fragment + // info, then sort by fragment offset in bits. + // FIXME: Come up with a more comprehensive comparator so + // the sorting isn't non-deterministic, and so the following + // std::unique call works correctly. + if (!A.Expr || !B.Expr) + return !!B.Expr; + auto FragmentA = A.Expr->getFragmentInfo(); + auto FragmentB = B.Expr->getFragmentInfo(); + if (!FragmentA || !FragmentB) + return !!FragmentB; + return FragmentA->OffsetInBits < FragmentB->OffsetInBits; + }); + GVEs.erase(std::unique(GVEs.begin(), GVEs.end(), + [](DwarfCompileUnit::GlobalExpr A, + DwarfCompileUnit::GlobalExpr B) { + return A.Expr == B.Expr; + }), + GVEs.end()); + return GVEs; +} + +// Emit all Dwarf sections that should come prior to the content. Create +// global DIEs and emit initial debug info sections. This is invoked by +// the target AsmPrinter. +void DwarfDebug::beginModule() { + NamedRegionTimer T(DbgTimerName, DbgTimerDescription, DWARFGroupName, + DWARFGroupDescription, TimePassesIsEnabled); + if (DisableDebugInfoPrinting) { + MMI->setDebugInfoAvailability(false); + return; + } + + const Module *M = MMI->getModule(); + + unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(), + M->debug_compile_units_end()); + // Tell MMI whether we have debug info. + assert(MMI->hasDebugInfo() == (NumDebugCUs > 0) && + "DebugInfoAvailabilty initialized unexpectedly"); + SingleCU = NumDebugCUs == 1; + DenseMap<DIGlobalVariable *, SmallVector<DwarfCompileUnit::GlobalExpr, 1>> + GVMap; + for (const GlobalVariable &Global : M->globals()) { + SmallVector<DIGlobalVariableExpression *, 1> GVs; + Global.getDebugInfo(GVs); + for (auto *GVE : GVs) + GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()}); + } + + // Create the symbol that designates the start of the unit's contribution + // to the string offsets table. In a split DWARF scenario, only the skeleton + // unit has the DW_AT_str_offsets_base attribute (and hence needs the symbol). + if (useSegmentedStringOffsetsTable()) + (useSplitDwarf() ? SkeletonHolder : InfoHolder) + .setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base")); + + + // Create the symbols that designates the start of the DWARF v5 range list + // and locations list tables. They are located past the table headers. + if (getDwarfVersion() >= 5) { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.setRnglistsTableBaseSym( + Asm->createTempSymbol("rnglists_table_base")); + Holder.setLoclistsTableBaseSym( + Asm->createTempSymbol("loclists_table_base")); + + if (useSplitDwarf()) + InfoHolder.setRnglistsTableBaseSym( + Asm->createTempSymbol("rnglists_dwo_table_base")); + } + + // Create the symbol that points to the first entry following the debug + // address table (.debug_addr) header. + AddrPool.setLabel(Asm->createTempSymbol("addr_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() && + CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty()) + continue; + + DwarfCompileUnit &CU = getOrCreateDwarfCompileUnit(CUNode); + + // Global Variables. + for (auto *GVE : CUNode->getGlobalVariables()) { + // Don't bother adding DIGlobalVariableExpressions listed in the CU if we + // already know about the variable and it isn't adding a constant + // expression. + auto &GVMapEntry = GVMap[GVE->getVariable()]; + auto *Expr = GVE->getExpression(); + if (!GVMapEntry.size() || (Expr && Expr->isConstant())) + GVMapEntry.push_back({nullptr, Expr}); + } + DenseSet<DIGlobalVariable *> Processed; + for (auto *GVE : CUNode->getGlobalVariables()) { + DIGlobalVariable *GV = GVE->getVariable(); + if (Processed.insert(GV).second) + CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV])); + } + + for (auto *Ty : CUNode->getEnumTypes()) { + // The enum types array by design contains pointers to + // MDNodes rather than DIRefs. Unique them here. + CU.getOrCreateTypeDIE(cast<DIType>(Ty)); + } + for (auto *Ty : CUNode->getRetainedTypes()) { + // The retained types array by design contains pointers to + // MDNodes rather than DIRefs. Unique them here. + if (DIType *RT = dyn_cast<DIType>(Ty)) + // 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); + } +} + +void DwarfDebug::finishEntityDefinitions() { + for (const auto &Entity : ConcreteEntities) { + DIE *Die = Entity->getDIE(); + assert(Die); + // FIXME: Consider the time-space tradeoff of just storing the unit pointer + // in the ConcreteEntities list, rather than looking it up again here. + // DIE::getUnit isn't simple - it walks parent pointers, etc. + DwarfCompileUnit *Unit = CUDieMap.lookup(Die->getUnitDie()); + assert(Unit); + Unit->finishEntityDefinition(Entity.get()); + } +} + +void DwarfDebug::finishSubprogramDefinitions() { + for (const DISubprogram *SP : ProcessedSPNodes) { + assert(SP->getUnit()->getEmissionKind() != DICompileUnit::NoDebug); + forBothCUs( + getOrCreateDwarfCompileUnit(SP->getUnit()), + [&](DwarfCompileUnit &CU) { CU.finishSubprogramDefinition(SP); }); + } +} + +void DwarfDebug::finalizeModuleInfo() { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + finishSubprogramDefinitions(); + + finishEntityDefinitions(); + + // Include the DWO file name in the hash if there's more than one CU. + // This handles ThinLTO's situation where imported CUs may very easily be + // duplicate with the same CU partially imported into another ThinLTO unit. + StringRef DWOName; + if (CUMap.size() > 1) + DWOName = Asm->TM.Options.MCOptions.SplitDwarfFile; + + // Handle anything that needs to be done on a per-unit basis after + // all other generation. + for (const auto &P : CUMap) { + auto &TheCU = *P.second; + if (TheCU.getCUNode()->isDebugDirectivesOnly()) + continue; + // Emit DW_AT_containing_type attribute to connect types with their + // vtable holding type. + TheCU.constructContainingTypeDIEs(); + + // Add CU specific attributes if we need to add any. + // 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() && !empty(TheCU.getUnitDie().children())) { + finishUnitAttributes(TheCU.getCUNode(), TheCU); + TheCU.addString(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); + SkCU->addString(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); + // Emit a unique identifier for this CU. + uint64_t ID = + DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie()); + if (getDwarfVersion() >= 5) { + TheCU.setDWOId(ID); + SkCU->setDWOId(ID); + } else { + TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); + SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); + } + + if (getDwarfVersion() < 5 && !SkeletonHolder.getRangeLists().empty()) { + const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol(); + SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, + Sym, Sym); + } + } else if (SkCU) { + finishUnitAttributes(SkCU->getCUNode(), *SkCU); + } + + // If we have code split among multiple sections or non-contiguous + // ranges of code then emit a DW_AT_ranges attribute on the unit that will + // remain in the .o file, otherwise add a DW_AT_low_pc. + // FIXME: We should use ranges allow reordering of code ala + // .subsections_via_symbols in mach-o. This would mean turning on + // ranges for all subprogram DIEs for mach-o. + DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; + + if (unsigned NumRanges = TheCU.getRanges().size()) { + if (NumRanges > 1 && useRangesSection()) + // A DW_AT_low_pc attribute may also be specified in combination with + // DW_AT_ranges to specify the default base address for use in + // location lists (see Section 2.6.2) and range lists (see Section + // 2.17.3). + U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); + else + U.setBaseAddress(TheCU.getRanges().front().getStart()); + U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges()); + } + + // 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 && !empty(TheCU.getUnitDie().children())))) + U.addAddrTableBase(); + + if (getDwarfVersion() >= 5) { + if (U.hasRangeLists()) + U.addRnglistsBase(); + + if (!DebugLocs.getLists().empty() && !useSplitDwarf()) + U.addLoclistsBase(); + } + + 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()); + } + + // Emit all frontend-produced Skeleton CUs, i.e., Clang modules. + for (auto *CUNode : MMI->getModule()->debug_compile_units()) + if (CUNode->getDWOId()) + getOrCreateDwarfCompileUnit(CUNode); + + // Compute DIE offsets and sizes. + InfoHolder.computeSizeAndOffsets(); + if (useSplitDwarf()) + SkeletonHolder.computeSizeAndOffsets(); +} + +// Emit all Dwarf sections that should come after the content. +void DwarfDebug::endModule() { + assert(CurFn == nullptr); + assert(CurMI == nullptr); + + for (const auto &P : CUMap) { + auto &CU = *P.second; + CU.createBaseTypeDIEs(); + } + + // If we aren't actually generating debug info (check beginModule - + // conditionalized on !DisableDebugInfoPrinting and the presence of the + // llvm.dbg.cu metadata node) + if (!MMI->hasDebugInfo()) + return; + + // Finalize the debug info for the module. + finalizeModuleInfo(); + + emitDebugStr(); + + if (useSplitDwarf()) + emitDebugLocDWO(); + else + // Emit info into a debug loc section. + emitDebugLoc(); + + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); + + // Emit all the DIEs into a debug info section. + emitDebugInfo(); + + // Emit info into a debug aranges section. + if (GenerateARangeSection) + emitDebugARanges(); + + // Emit info into a debug ranges section. + emitDebugRanges(); + + // Emit info into a debug macinfo section. + emitDebugMacinfo(); + + if (useSplitDwarf()) { + emitDebugStrDWO(); + emitDebugInfoDWO(); + emitDebugAbbrevDWO(); + emitDebugLineDWO(); + emitDebugRangesDWO(); + } + + emitDebugAddr(); + + // Emit info into the dwarf accelerator table sections. + switch (getAccelTableKind()) { + case AccelTableKind::Apple: + emitAccelNames(); + emitAccelObjC(); + emitAccelNamespaces(); + emitAccelTypes(); + break; + case AccelTableKind::Dwarf: + emitAccelDebugNames(); + break; + case AccelTableKind::None: + break; + case AccelTableKind::Default: + llvm_unreachable("Default should have already been resolved."); + } + + // Emit the pubnames and pubtypes sections if requested. + emitDebugPubSections(); + + // clean up. + // 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)) + return; + + if (LexicalScope *Scope = + LScopes.findAbstractScope(cast_or_null<DILocalScope>(ScopeNode))) + CU.createAbstractEntity(Node, Scope); +} + +// Collect variable information from side table maintained by MF. +void DwarfDebug::collectVariableInfoFromMFTable( + DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) { + SmallDenseMap<InlinedEntity, DbgVariable *> MFVars; + for (const auto &VI : Asm->MF->getVariableDbgInfo()) { + if (!VI.Var) + continue; + assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) && + "Expected inlined-at fields to agree"); + + InlinedEntity Var(VI.Var, VI.Loc->getInlinedAt()); + Processed.insert(Var); + LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); + + // If variable scope is not found then skip this variable. + if (!Scope) + continue; + + ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode()); + auto RegVar = llvm::make_unique<DbgVariable>( + cast<DILocalVariable>(Var.first), Var.second); + RegVar->initializeMMI(VI.Expr, VI.Slot); + if (DbgVariable *DbgVar = MFVars.lookup(Var)) + DbgVar->addMMIEntry(*RegVar); + else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) { + MFVars.insert({Var, RegVar.get()}); + ConcreteEntities.push_back(std::move(RegVar)); + } + } +} + +/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its +/// enclosing lexical scope. The check ensures there are no other instructions +/// in the same lexical scope preceding the DBG_VALUE and that its range is +/// either open or otherwise rolls off the end of the scope. +static bool validThroughout(LexicalScopes &LScopes, + const MachineInstr *DbgValue, + const MachineInstr *RangeEnd) { + assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location"); + auto MBB = DbgValue->getParent(); + auto DL = DbgValue->getDebugLoc(); + auto *LScope = LScopes.findLexicalScope(DL); + // Scope doesn't exist; this is a dead DBG_VALUE. + if (!LScope) + return false; + auto &LSRange = LScope->getRanges(); + if (LSRange.size() == 0) + return false; + + // Determine if the DBG_VALUE is valid at the beginning of its lexical block. + const MachineInstr *LScopeBegin = LSRange.front().first; + // Early exit if the lexical scope begins outside of the current block. + if (LScopeBegin->getParent() != MBB) + return false; + MachineBasicBlock::const_reverse_iterator Pred(DbgValue); + for (++Pred; Pred != MBB->rend(); ++Pred) { + if (Pred->getFlag(MachineInstr::FrameSetup)) + break; + auto PredDL = Pred->getDebugLoc(); + if (!PredDL || Pred->isMetaInstruction()) + continue; + // Check whether the instruction preceding the DBG_VALUE is in the same + // (sub)scope as the DBG_VALUE. + if (DL->getScope() == PredDL->getScope()) + return false; + auto *PredScope = LScopes.findLexicalScope(PredDL); + if (!PredScope || LScope->dominates(PredScope)) + return false; + } + + // If the range of the DBG_VALUE is open-ended, report success. + if (!RangeEnd) + return true; + + // Fail if there are instructions belonging to our scope in another block. + const MachineInstr *LScopeEnd = LSRange.back().second; + if (LScopeEnd->getParent() != MBB) + return false; + + // Single, constant DBG_VALUEs in the prologue are promoted to be live + // throughout the function. This is a hack, presumably for DWARF v2 and not + // necessarily correct. It would be much better to use a dbg.declare instead + // if we know the constant is live throughout the scope. + if (DbgValue->getOperand(0).isImm() && MBB->pred_empty()) + return true; + + return false; +} + +/// Build the location list for all DBG_VALUEs in the function that +/// describe the same variable. The resulting DebugLocEntries will have +/// strict monotonically increasing begin addresses and will never +/// overlap. If the resulting list has only one entry that is valid +/// throughout variable's scope return true. +// +// See the definition of DbgValueHistoryMap::Entry for an explanation of the +// different kinds of history map entries. One thing to be aware of is that if +// a debug value is ended by another entry (rather than being valid until the +// end of the function), that entry's instruction may or may not be included in +// the range, depending on if the entry is a clobbering entry (it has an +// instruction that clobbers one or more preceding locations), or if it is an +// (overlapping) debug value entry. This distinction can be seen in the example +// below. The first debug value is ended by the clobbering entry 2, and the +// second and third debug values are ended by the overlapping debug value entry +// 4. +// +// Input: +// +// History map entries [type, end index, mi] +// +// 0 | [DbgValue, 2, DBG_VALUE $reg0, [...] (fragment 0, 32)] +// 1 | | [DbgValue, 4, DBG_VALUE $reg1, [...] (fragment 32, 32)] +// 2 | | [Clobber, $reg0 = [...], -, -] +// 3 | | [DbgValue, 4, DBG_VALUE 123, [...] (fragment 64, 32)] +// 4 [DbgValue, ~0, DBG_VALUE @g, [...] (fragment 0, 96)] +// +// Output [start, end) [Value...]: +// +// [0-1) [(reg0, fragment 0, 32)] +// [1-3) [(reg0, fragment 0, 32), (reg1, fragment 32, 32)] +// [3-4) [(reg1, fragment 32, 32), (123, fragment 64, 32)] +// [4-) [(@g, fragment 0, 96)] +bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, + const DbgValueHistoryMap::Entries &Entries) { + using OpenRange = + std::pair<DbgValueHistoryMap::EntryIndex, DbgValueLoc>; + SmallVector<OpenRange, 4> OpenRanges; + bool isSafeForSingleLocation = true; + const MachineInstr *StartDebugMI = nullptr; + const MachineInstr *EndMI = nullptr; + + for (auto EB = Entries.begin(), EI = EB, EE = Entries.end(); EI != EE; ++EI) { + const MachineInstr *Instr = EI->getInstr(); + + // Remove all values that are no longer live. + size_t Index = std::distance(EB, EI); + auto Last = + remove_if(OpenRanges, [&](OpenRange &R) { return R.first <= Index; }); + OpenRanges.erase(Last, OpenRanges.end()); + + // If we are dealing with a clobbering entry, this iteration will result in + // a location list entry starting after the clobbering instruction. + const MCSymbol *StartLabel = + EI->isClobber() ? getLabelAfterInsn(Instr) : getLabelBeforeInsn(Instr); + assert(StartLabel && + "Forgot label before/after instruction starting a range!"); + + const MCSymbol *EndLabel; + if (std::next(EI) == Entries.end()) { + EndLabel = Asm->getFunctionEnd(); + if (EI->isClobber()) + EndMI = EI->getInstr(); + } + else if (std::next(EI)->isClobber()) + EndLabel = getLabelAfterInsn(std::next(EI)->getInstr()); + else + EndLabel = getLabelBeforeInsn(std::next(EI)->getInstr()); + assert(EndLabel && "Forgot label after instruction ending a range!"); + + if (EI->isDbgValue()) + LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Instr << "\n"); + + // If this history map entry has a debug value, add that to the list of + // open ranges and check if its location is valid for a single value + // location. + if (EI->isDbgValue()) { + // Do not add undef debug values, as they are redundant information in + // the location list entries. An undef debug results in an empty location + // description. If there are any non-undef fragments then padding pieces + // with empty location descriptions will automatically be inserted, and if + // all fragments are undef then the whole location list entry is + // redundant. + if (!Instr->isUndefDebugValue()) { + auto Value = getDebugLocValue(Instr); + OpenRanges.emplace_back(EI->getEndIndex(), Value); + + // TODO: Add support for single value fragment locations. + if (Instr->getDebugExpression()->isFragment()) + isSafeForSingleLocation = false; + + if (!StartDebugMI) + StartDebugMI = Instr; + } else { + isSafeForSingleLocation = false; + } + } + + // Location list entries with empty location descriptions are redundant + // information in DWARF, so do not emit those. + if (OpenRanges.empty()) + continue; + + // Omit entries with empty ranges as they do not have any effect in DWARF. + if (StartLabel == EndLabel) { + LLVM_DEBUG(dbgs() << "Omitting location list entry with empty range.\n"); + continue; + } + + SmallVector<DbgValueLoc, 4> Values; + for (auto &R : OpenRanges) + Values.push_back(R.second); + DebugLoc.emplace_back(StartLabel, EndLabel, Values); + + // Attempt to coalesce the ranges of two otherwise identical + // DebugLocEntries. + auto CurEntry = DebugLoc.rbegin(); + LLVM_DEBUG({ + dbgs() << CurEntry->getValues().size() << " Values:\n"; + for (auto &Value : CurEntry->getValues()) + Value.dump(); + dbgs() << "-----\n"; + }); + + auto PrevEntry = std::next(CurEntry); + if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) + DebugLoc.pop_back(); + } + + return DebugLoc.size() == 1 && isSafeForSingleLocation && + validThroughout(LScopes, StartDebugMI, EndMI); +} + +DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, + LexicalScope &Scope, + const DINode *Node, + const DILocation *Location, + const MCSymbol *Sym) { + ensureAbstractEntityIsCreatedIfScoped(TheCU, Node, Scope.getScopeNode()); + if (isa<const DILocalVariable>(Node)) { + ConcreteEntities.push_back( + llvm::make_unique<DbgVariable>(cast<const DILocalVariable>(Node), + Location)); + InfoHolder.addScopeVariable(&Scope, + cast<DbgVariable>(ConcreteEntities.back().get())); + } else if (isa<const DILabel>(Node)) { + ConcreteEntities.push_back( + llvm::make_unique<DbgLabel>(cast<const DILabel>(Node), + Location, Sym)); + InfoHolder.addScopeLabel(&Scope, + cast<DbgLabel>(ConcreteEntities.back().get())); + } + return ConcreteEntities.back().get(); +} + +// Find variables for each lexical scope. +void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, + const DISubprogram *SP, + DenseSet<InlinedEntity> &Processed) { + // Grab the variable info that was squirreled away in the MMI side-table. + collectVariableInfoFromMFTable(TheCU, Processed); + + for (const auto &I : DbgValues) { + InlinedEntity IV = I.first; + if (Processed.count(IV)) + continue; + + // Instruction ranges, specifying where IV is accessible. + const auto &HistoryMapEntries = I.second; + if (HistoryMapEntries.empty()) + continue; + + LexicalScope *Scope = nullptr; + const DILocalVariable *LocalVar = cast<DILocalVariable>(IV.first); + if (const DILocation *IA = IV.second) + Scope = LScopes.findInlinedScope(LocalVar->getScope(), IA); + else + Scope = LScopes.findLexicalScope(LocalVar->getScope()); + // If variable scope is not found then skip this variable. + if (!Scope) + continue; + + Processed.insert(IV); + DbgVariable *RegVar = cast<DbgVariable>(createConcreteEntity(TheCU, + *Scope, LocalVar, IV.second)); + + const MachineInstr *MInsn = HistoryMapEntries.front().getInstr(); + assert(MInsn->isDebugValue() && "History must begin with debug value"); + + // Check if there is a single DBG_VALUE, valid throughout the var's scope. + // If the history map contains a single debug value, there may be an + // additional entry which clobbers the debug value. + size_t HistSize = HistoryMapEntries.size(); + bool SingleValueWithClobber = + HistSize == 2 && HistoryMapEntries[1].isClobber(); + if (HistSize == 1 || SingleValueWithClobber) { + const auto *End = + SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr; + if (validThroughout(LScopes, MInsn, End)) { + RegVar->initializeDbgValue(MInsn); + continue; + } + } + + // Do not emit location lists if .debug_loc secton is disabled. + if (!useLocSection()) + continue; + + // Handle multiple DBG_VALUE instructions describing one variable. + DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn); + + // Build the location list for this variable. + SmallVector<DebugLocEntry, 8> Entries; + bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries); + + // Check whether buildLocationList managed to merge all locations to one + // that is valid throughout the variable's scope. If so, produce single + // value location. + if (isValidSingleLocation) { + RegVar->initializeDbgValue(Entries[0].getValues()[0]); + continue; + } + + // If the variable has a DIBasicType, extract it. Basic types cannot have + // unique identifiers, so don't bother resolving the type with the + // identifier map. + const DIBasicType *BT = dyn_cast<DIBasicType>( + static_cast<const Metadata *>(LocalVar->getType())); + + // Finalize the entry by lowering it into a DWARF bytestream. + for (auto &Entry : Entries) + Entry.finalize(*Asm, List, BT, TheCU); + } + + // For each InlinedEntity collected from DBG_LABEL instructions, convert to + // DWARF-related DbgLabel. + for (const auto &I : DbgLabels) { + InlinedEntity IL = I.first; + const MachineInstr *MI = I.second; + if (MI == nullptr) + continue; + + LexicalScope *Scope = nullptr; + const DILabel *Label = cast<DILabel>(IL.first); + // Get inlined DILocation if it is inlined label. + if (const DILocation *IA = IL.second) + Scope = LScopes.findInlinedScope(Label->getScope(), IA); + else + Scope = LScopes.findLexicalScope(Label->getScope()); + // If label scope is not found then skip this label. + if (!Scope) + continue; + + Processed.insert(IL); + /// At this point, the temporary label is created. + /// Save the temporary label to DbgLabel entity to get the + /// actually address when generating Dwarf DIE. + MCSymbol *Sym = getLabelBeforeInsn(MI); + createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym); + } + + // Collect info for variables/labels that were optimized out. + 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()); + } + + if (Scope) + createConcreteEntity(TheCU, *Scope, DN, nullptr); + } +} + +// Process beginning of an instruction. +void DwarfDebug::beginInstruction(const MachineInstr *MI) { + DebugHandlerBase::beginInstruction(MI); + assert(CurMI); + + const auto *SP = MI->getMF()->getFunction().getSubprogram(); + if (!SP || SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) + return; + + // Check if source location changes, but ignore DBG_VALUE and CFI locations. + // If the instruction is part of the function frame setup code, do not emit + // any line record, as there is no correspondence with any user code. + if (MI->isMetaInstruction() || MI->getFlag(MachineInstr::FrameSetup)) + return; + const DebugLoc &DL = MI->getDebugLoc(); + // When we emit a line-0 record, we don't update PrevInstLoc; so look at + // the last line number actually emitted, to see if it was line 0. + unsigned LastAsmLine = + Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine(); + + // Request a label after the call in order to emit AT_return_pc information + // in call site entries. TODO: Add support for targets with delay slots. + if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot()) + requestLabelAfterInsn(MI); + + if (DL == PrevInstLoc) { + // If we have an ongoing unspecified location, nothing to do here. + if (!DL) + return; + // We have an explicit location, same as the previous location. + // But we might be coming back to it after a line 0 record. + if (LastAsmLine == 0 && DL.getLine() != 0) { + // Reinstate the source location but not marked as a statement. + const MDNode *Scope = DL.getScope(); + recordSourceLine(DL.getLine(), DL.getCol(), Scope, /*Flags=*/0); + } + return; + } + + if (!DL) { + // We have an unspecified location, which might want to be line 0. + // If we have already emitted a line-0 record, don't repeat it. + if (LastAsmLine == 0) + return; + // If user said Don't Do That, don't do that. + if (UnknownLocations == Disable) + return; + // See if we have a reason to emit a line-0 record now. + // Reasons to emit a line-0 record include: + // - User asked for it (UnknownLocations). + // - Instruction has a label, so it's referenced from somewhere else, + // possibly debug information; we want it to have a source location. + // - Instruction is at the top of a block; we don't want to inherit the + // location from the physically previous (maybe unrelated) block. + if (UnknownLocations == Enable || PrevLabel || + (PrevInstBB && PrevInstBB != MI->getParent())) { + // Preserve the file and column numbers, if we can, to save space in + // the encoded line table. + // Do not update PrevInstLoc, it remembers the last non-0 line. + const MDNode *Scope = nullptr; + unsigned Column = 0; + if (PrevInstLoc) { + Scope = PrevInstLoc.getScope(); + Column = PrevInstLoc.getCol(); + } + recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0); + } + return; + } + + // We have an explicit location, different from the previous location. + // Don't repeat a line-0 record, but otherwise emit the new location. + // (The new location might be an explicit line 0, which we do emit.) + if (DL.getLine() == 0 && LastAsmLine == 0) + return; + unsigned Flags = 0; + if (DL == PrologEndLoc) { + Flags |= DWARF2_FLAG_PROLOGUE_END | DWARF2_FLAG_IS_STMT; + PrologEndLoc = DebugLoc(); + } + // If the line changed, we call that a new statement; unless we went to + // line 0 and came back, in which case it is not a new statement. + unsigned OldLine = PrevInstLoc ? PrevInstLoc.getLine() : LastAsmLine; + if (DL.getLine() && DL.getLine() != OldLine) + Flags |= DWARF2_FLAG_IS_STMT; + + const MDNode *Scope = DL.getScope(); + recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags); + + // If we're not at line 0, remember this location. + if (DL.getLine()) + PrevInstLoc = DL; +} + +static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { + // First known non-DBG_VALUE and non-frame setup location marks + // the beginning of the function body. + for (const auto &MBB : *MF) + for (const auto &MI : MBB) + if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) && + MI.getDebugLoc()) + return MI.getDebugLoc(); + return DebugLoc(); +} + +/// Register a source line with debug info. Returns the unique label that was +/// emitted and which provides correspondence to the source line list. +static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col, + const MDNode *S, unsigned Flags, unsigned CUID, + uint16_t DwarfVersion, + ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs) { + StringRef Fn; + unsigned FileNo = 1; + unsigned Discriminator = 0; + if (auto *Scope = cast_or_null<DIScope>(S)) { + Fn = Scope->getFilename(); + if (Line != 0 && DwarfVersion >= 4) + if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope)) + Discriminator = LBF->getDiscriminator(); + + FileNo = static_cast<DwarfCompileUnit &>(*DCUs[CUID]) + .getOrCreateSourceID(Scope->getFile()); + } + Asm.OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0, + Discriminator, Fn); +} + +DebugLoc DwarfDebug::emitInitialLocDirective(const MachineFunction &MF, + unsigned CUID) { + // Get beginning of function. + if (DebugLoc PrologEndLoc = findPrologueEndLoc(&MF)) { + // Ensure the compile unit is created if the function is called before + // beginFunction(). + (void)getOrCreateDwarfCompileUnit( + MF.getFunction().getSubprogram()->getUnit()); + // We'd like to list the prologue as "not statements" but GDB behaves + // poorly if we do that. Revisit this with caution/GDB (7.5+) testing. + const DISubprogram *SP = PrologEndLoc->getInlinedAtScope()->getSubprogram(); + ::recordSourceLine(*Asm, SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT, + CUID, getDwarfVersion(), getUnits()); + return PrologEndLoc; + } + return DebugLoc(); +} + +// Gather pre-function debug information. Assumes being called immediately +// after the function entry point has been emitted. +void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) { + CurFn = MF; + + auto *SP = MF->getFunction().getSubprogram(); + assert(LScopes.empty() || SP == LScopes.getCurrentFunctionScope()->getScopeNode()); + if (SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) + return; + + DwarfCompileUnit &CU = getOrCreateDwarfCompileUnit(SP->getUnit()); + + // Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function + // belongs to so that we add to the correct per-cu line table in the + // non-asm case. + if (Asm->OutStreamer->hasRawTextSupport()) + // Use a single line table if we are generating assembly. + Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); + else + Asm->OutStreamer->getContext().setDwarfCompileUnitID(CU.getUniqueID()); + + // Record beginning of function. + PrologEndLoc = emitInitialLocDirective( + *MF, Asm->OutStreamer->getContext().getDwarfCompileUnitID()); +} + +void DwarfDebug::skippedNonDebugFunction() { + // If we don't have a subprogram for this function then there will be a hole + // in the range information. Keep note of this by setting the previously used + // section to nullptr. + PrevCU = nullptr; + CurFn = nullptr; +} + +// Gather and emit post-function debug information. +void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { + const DISubprogram *SP = MF->getFunction().getSubprogram(); + + assert(CurFn == MF && + "endFunction should be called with the same function as beginFunction"); + + // Set DwarfDwarfCompileUnitID in MCContext to default value. + Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); + + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + assert(!FnScope || SP == FnScope->getScopeNode()); + DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit()); + if (TheCU.getCUNode()->isDebugDirectivesOnly()) { + PrevLabel = nullptr; + CurFn = nullptr; + return; + } + + DenseSet<InlinedEntity> Processed; + collectEntityInfo(TheCU, SP, Processed); + + // Add the range of this function to the list of ranges for the CU. + TheCU.addRange(RangeSpan(Asm->getFunctionBegin(), Asm->getFunctionEnd())); + + // Under -gmlt, skip building the subprogram if there are no inlined + // subroutines inside it. But with -fdebug-info-for-profiling, the subprogram + // is still needed as we need its source location. + if (!TheCU.getCUNode()->getDebugInfoForProfiling() && + TheCU.getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly && + LScopes.getAbstractScopesList().empty() && !IsDarwin) { + assert(InfoHolder.getScopeVariables().empty()); + PrevLabel = nullptr; + CurFn = nullptr; + return; + } + +#ifndef NDEBUG + size_t NumAbstractScopes = LScopes.getAbstractScopesList().size(); +#endif + // Construct abstract scopes. + for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { + 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"); + } + constructAbstractSubprogramScopeDIE(TheCU, AScope); + } + + ProcessedSPNodes.insert(SP); + DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope); + if (auto *SkelCU = TheCU.getSkeleton()) + if (!LScopes.getAbstractScopesList().empty() && + TheCU.getCUNode()->getSplitDebugInlining()) + SkelCU->constructSubprogramScopeDIE(SP, FnScope); + + // Construct call site entries. + constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF); + + // Clear debug info + // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the + // DbgVariables except those that are also in AbstractVariables (since they + // can be used cross-function) + InfoHolder.getScopeVariables().clear(); + InfoHolder.getScopeLabels().clear(); + PrevLabel = nullptr; + CurFn = nullptr; +} + +// Register a source line with debug info. Returns the unique label that was +// emitted and which provides correspondence to the source line list. +void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, + unsigned Flags) { + ::recordSourceLine(*Asm, Line, Col, S, Flags, + Asm->OutStreamer->getContext().getDwarfCompileUnitID(), + getDwarfVersion(), getUnits()); +} + +//===----------------------------------------------------------------------===// +// Emit Methods +//===----------------------------------------------------------------------===// + +// Emit the debug info section. +void DwarfDebug::emitDebugInfo() { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.emitUnits(/* UseOffsets */ false); +} + +// Emit the abbreviation section. +void DwarfDebug::emitAbbreviations() { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + + Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); +} + +void DwarfDebug::emitStringOffsetsTableHeader() { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.getStringPool().emitStringOffsetsTableHeader( + *Asm, Asm->getObjFileLowering().getDwarfStrOffSection(), + Holder.getStringOffsetsStartSym()); +} + +template <typename AccelTableT> +void DwarfDebug::emitAccel(AccelTableT &Accel, MCSection *Section, + StringRef TableName) { + Asm->OutStreamer->SwitchSection(Section); + + // Emit the full data. + emitAppleAccelTable(Asm, Accel, TableName, Section->getBeginSymbol()); +} + +void DwarfDebug::emitAccelDebugNames() { + // Don't emit anything if we have no compilation units to index. + if (getUnits().empty()) + return; + + emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits()); +} + +// Emit visible names into a hashed accelerator table section. +void DwarfDebug::emitAccelNames() { + emitAccel(AccelNames, Asm->getObjFileLowering().getDwarfAccelNamesSection(), + "Names"); +} + +// Emit objective C classes and categories into a hashed accelerator table +// section. +void DwarfDebug::emitAccelObjC() { + emitAccel(AccelObjC, Asm->getObjFileLowering().getDwarfAccelObjCSection(), + "ObjC"); +} + +// Emit namespace dies into a hashed accelerator table. +void DwarfDebug::emitAccelNamespaces() { + emitAccel(AccelNamespace, + Asm->getObjFileLowering().getDwarfAccelNamespaceSection(), + "namespac"); +} + +// Emit type dies into a hashed accelerator table. +void DwarfDebug::emitAccelTypes() { + emitAccel(AccelTypes, Asm->getObjFileLowering().getDwarfAccelTypesSection(), + "types"); +} + +// Public name handling. +// The format for the various pubnames: +// +// dwarf pubnames - offset/name pairs where the offset is the offset into the CU +// for the DIE that is named. +// +// gnu pubnames - offset/index value/name tuples where the offset is the offset +// into the CU and the index value is computed according to the type of value +// for the DIE that is named. +// +// For type units the offset is the offset of the skeleton DIE. For split dwarf +// it's the offset within the debug_info/debug_types dwo section, however, the +// reference in the pubname header doesn't change. + +/// computeIndexValue - Compute the gdb index value for the DIE and CU. +static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, + const DIE *Die) { + // Entities that ended up only in a Type Unit reference the CU instead (since + // the pub entry has offsets within the CU there's no real offset that can be + // provided anyway). As it happens all such entities (namespaces and types, + // types only in C++ at that) are rendered as TYPE+EXTERNAL. If this turns out + // not to be true it would be necessary to persist this information from the + // point at which the entry is added to the index data structure - since by + // the time the index is built from that, the original type/namespace DIE in a + // type unit has already been destroyed so it can't be queried for properties + // like tag, etc. + if (Die->getTag() == dwarf::DW_TAG_compile_unit) + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, + dwarf::GIEL_EXTERNAL); + dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC; + + // We could have a specification DIE that has our most of our knowledge, + // look for that now. + if (DIEValue SpecVal = Die->findAttribute(dwarf::DW_AT_specification)) { + DIE &SpecDIE = SpecVal.getDIEEntry().getEntry(); + if (SpecDIE.findAttribute(dwarf::DW_AT_external)) + Linkage = dwarf::GIEL_EXTERNAL; + } else if (Die->findAttribute(dwarf::DW_AT_external)) + Linkage = dwarf::GIEL_EXTERNAL; + + switch (Die->getTag()) { + case dwarf::DW_TAG_class_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_enumeration_type: + return dwarf::PubIndexEntryDescriptor( + dwarf::GIEK_TYPE, CU->getLanguage() != dwarf::DW_LANG_C_plus_plus + ? dwarf::GIEL_STATIC + : dwarf::GIEL_EXTERNAL); + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_base_type: + case dwarf::DW_TAG_subrange_type: + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC); + case dwarf::DW_TAG_namespace: + return dwarf::GIEK_TYPE; + case dwarf::DW_TAG_subprogram: + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, Linkage); + case dwarf::DW_TAG_variable: + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, Linkage); + case dwarf::DW_TAG_enumerator: + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, + dwarf::GIEL_STATIC); + default: + return dwarf::GIEK_NONE; + } +} + +/// emitDebugPubSections - Emit visible names and types into debug pubnames and +/// pubtypes sections. +void DwarfDebug::emitDebugPubSections() { + for (const auto &NU : CUMap) { + DwarfCompileUnit *TheU = NU.second; + if (!TheU->hasDwarfPubSections()) + continue; + + bool GnuStyle = TheU->getCUNode()->getNameTableKind() == + DICompileUnit::DebugNameTableKind::GNU; + + Asm->OutStreamer->SwitchSection( + GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() + : Asm->getObjFileLowering().getDwarfPubNamesSection()); + emitDebugPubSection(GnuStyle, "Names", TheU, TheU->getGlobalNames()); + + Asm->OutStreamer->SwitchSection( + GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() + : Asm->getObjFileLowering().getDwarfPubTypesSection()); + emitDebugPubSection(GnuStyle, "Types", TheU, TheU->getGlobalTypes()); + } +} + +void DwarfDebug::emitSectionReference(const DwarfCompileUnit &CU) { + if (useSectionsAsReferences()) + Asm->EmitDwarfOffset(CU.getSection()->getBeginSymbol(), + CU.getDebugSectionOffset()); + else + Asm->emitDwarfSymbolReference(CU.getLabelBegin()); +} + +void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, + DwarfCompileUnit *TheU, + const StringMap<const DIE *> &Globals) { + if (auto *Skeleton = TheU->getSkeleton()) + TheU = Skeleton; + + // Emit the header. + Asm->OutStreamer->AddComment("Length of Public " + Name + " Info"); + MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + Name + "_begin"); + MCSymbol *EndLabel = Asm->createTempSymbol("pub" + Name + "_end"); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); + + Asm->OutStreamer->EmitLabel(BeginLabel); + + Asm->OutStreamer->AddComment("DWARF Version"); + Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); + + Asm->OutStreamer->AddComment("Offset of Compilation Unit Info"); + emitSectionReference(*TheU); + + Asm->OutStreamer->AddComment("Compilation Unit Length"); + Asm->emitInt32(TheU->getLength()); + + // Emit the pubnames for this compilation unit. + for (const auto &GI : Globals) { + const char *Name = GI.getKeyData(); + const DIE *Entity = GI.second; + + Asm->OutStreamer->AddComment("DIE offset"); + Asm->emitInt32(Entity->getOffset()); + + if (GnuStyle) { + dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); + Asm->OutStreamer->AddComment( + Twine("Attributes: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); + Asm->emitInt8(Desc.toBits()); + } + + Asm->OutStreamer->AddComment("External Name"); + Asm->OutStreamer->EmitBytes(StringRef(Name, GI.getKeyLength() + 1)); + } + + Asm->OutStreamer->AddComment("End Mark"); + Asm->emitInt32(0); + Asm->OutStreamer->EmitLabel(EndLabel); +} + +/// Emit null-terminated strings into a debug str section. +void DwarfDebug::emitDebugStr() { + MCSection *StringOffsetsSection = nullptr; + if (useSegmentedStringOffsetsTable()) { + emitStringOffsetsTableHeader(); + StringOffsetsSection = Asm->getObjFileLowering().getDwarfStrOffSection(); + } + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection(), + StringOffsetsSection, /* UseRelativeOffsets = */ true); +} + +void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, + const DebugLocStream::Entry &Entry, + const DwarfCompileUnit *CU) { + auto &&Comments = DebugLocs.getComments(Entry); + auto Comment = Comments.begin(); + auto End = Comments.end(); + + // The expressions are inserted into a byte stream rather early (see + // DwarfExpression::addExpression) so for those ops (e.g. DW_OP_convert) that + // need to reference a base_type DIE the offset of that DIE is not yet known. + // To deal with this we instead insert a placeholder early and then extract + // it here and replace it with the real reference. + unsigned PtrSize = Asm->MAI->getCodePointerSize(); + DWARFDataExtractor Data(StringRef(DebugLocs.getBytes(Entry).data(), + DebugLocs.getBytes(Entry).size()), + Asm->getDataLayout().isLittleEndian(), PtrSize); + DWARFExpression Expr(Data, getDwarfVersion(), PtrSize); + + using Encoding = DWARFExpression::Operation::Encoding; + uint32_t Offset = 0; + for (auto &Op : Expr) { + assert(Op.getCode() != dwarf::DW_OP_const_type && + "3 operand ops 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; + if (Op.getDescription().Op[I] == Encoding::BaseTypeRef) { + if (CU) { + uint64_t Offset = CU->ExprRefedBaseTypes[Op.getRawOperand(I)].Die->getOffset(); + assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit"); + Asm->EmitULEB128(Offset, nullptr, ULEB128PadSize); + } else { + // Emit a reference to the 'generic type'. + Asm->EmitULEB128(0, nullptr, ULEB128PadSize); + } + // Make sure comments stay aligned. + for (unsigned J = 0; J < ULEB128PadSize; ++J) + if (Comment != End) + Comment++; + } else { + for (uint32_t J = Offset; J < Op.getOperandEndOffset(I); ++J) + Streamer.EmitInt8(Data.getData()[J], Comment != End ? *(Comment++) : ""); + } + Offset = Op.getOperandEndOffset(I); + } + assert(Offset == Op.getEndOffset()); + } +} + +void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, + const DbgValueLoc &Value, + DwarfExpression &DwarfExpr) { + auto *DIExpr = Value.getExpression(); + DIExpressionCursor ExprCursor(DIExpr); + DwarfExpr.addFragmentOffset(DIExpr); + // Regular entry. + if (Value.isInt()) { + if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed || + BT->getEncoding() == dwarf::DW_ATE_signed_char)) + DwarfExpr.addSignedConstant(Value.getInt()); + else + DwarfExpr.addUnsignedConstant(Value.getInt()); + } else if (Value.isLocation()) { + MachineLocation Location = Value.getLoc(); + if (Location.isIndirect()) + DwarfExpr.setMemoryLocationKind(); + DIExpressionCursor Cursor(DIExpr); + + if (DIExpr->isEntryValue()) { + DwarfExpr.setEntryValueFlag(); + DwarfExpr.addEntryValueExpression(Cursor); + } + + const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); + if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) + return; + return DwarfExpr.addExpression(std::move(Cursor)); + } else if (Value.isConstantFP()) { + APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt(); + DwarfExpr.addUnsignedConstant(RawBytes); + } + DwarfExpr.addExpression(std::move(ExprCursor)); +} + +void DebugLocEntry::finalize(const AsmPrinter &AP, + DebugLocStream::ListBuilder &List, + const DIBasicType *BT, + DwarfCompileUnit &TheCU) { + assert(!Values.empty() && + "location list entries without values are redundant"); + assert(Begin != End && "unexpected location list entry with empty range"); + DebugLocStream::EntryBuilder Entry(List, Begin, End); + BufferByteStreamer Streamer = Entry.getStreamer(); + DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer, TheCU); + const DbgValueLoc &Value = Values[0]; + if (Value.isFragment()) { + // Emit all fragments that belong to the same variable and range. + assert(llvm::all_of(Values, [](DbgValueLoc P) { + return P.isFragment(); + }) && "all values are expected to be fragments"); + assert(std::is_sorted(Values.begin(), Values.end()) && + "fragments are expected to be sorted"); + + for (auto Fragment : Values) + DwarfDebug::emitDebugLocValue(AP, BT, Fragment, DwarfExpr); + + } else { + assert(Values.size() == 1 && "only fragments may have >1 value"); + DwarfDebug::emitDebugLocValue(AP, BT, Value, DwarfExpr); + } + DwarfExpr.finalize(); +} + +void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, + const DwarfCompileUnit *CU) { + // Emit the size. + Asm->OutStreamer->AddComment("Loc expr size"); + if (getDwarfVersion() >= 5) + Asm->EmitULEB128(DebugLocs.getBytes(Entry).size()); + else if (DebugLocs.getBytes(Entry).size() <= std::numeric_limits<uint16_t>::max()) + Asm->emitInt16(DebugLocs.getBytes(Entry).size()); + else { + // The entry is too big to fit into 16 bit, drop it as there is nothing we + // can do. + Asm->emitInt16(0); + return; + } + // Emit the entry. + APByteStreamer Streamer(*Asm); + emitDebugLocEntry(Streamer, Entry, CU); +} + +// Emit the common part of the DWARF 5 range/locations list tables header. +static void emitListsTableHeaderStart(AsmPrinter *Asm, const DwarfFile &Holder, + MCSymbol *TableStart, + MCSymbol *TableEnd) { + // Build the table header, which starts with the length field. + Asm->OutStreamer->AddComment("Length"); + Asm->EmitLabelDifference(TableEnd, TableStart, 4); + Asm->OutStreamer->EmitLabel(TableStart); + // Version number (DWARF v5 and later). + Asm->OutStreamer->AddComment("Version"); + Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); + // Address size. + Asm->OutStreamer->AddComment("Address size"); + Asm->emitInt8(Asm->MAI->getCodePointerSize()); + // Segment selector size. + Asm->OutStreamer->AddComment("Segment selector size"); + Asm->emitInt8(0); +} + +// Emit the header of a DWARF 5 range list table list table. Returns the symbol +// that designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, + const DwarfFile &Holder) { + MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); + emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd); + + Asm->OutStreamer->AddComment("Offset entry count"); + Asm->emitInt32(Holder.getRangeLists().size()); + Asm->OutStreamer->EmitLabel(Holder.getRnglistsTableBaseSym()); + + for (const RangeSpanList &List : Holder.getRangeLists()) + Asm->EmitLabelDifference(List.getSym(), Holder.getRnglistsTableBaseSym(), + 4); + + return TableEnd; +} + +// Emit the header of a DWARF 5 locations list table. Returns the symbol that +// designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm, + const DwarfFile &Holder) { + MCSymbol *TableStart = Asm->createTempSymbol("debug_loclist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_loclist_table_end"); + emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd); + + // 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->OutStreamer->EmitLabel(Holder.getLoclistsTableBaseSym()); + + return TableEnd; +} + +// Emit locations into the .debug_loc/.debug_rnglists section. +void DwarfDebug::emitDebugLoc() { + if (DebugLocs.getLists().empty()) + return; + + bool IsLocLists = getDwarfVersion() >= 5; + MCSymbol *TableEnd = nullptr; + if (IsLocLists) { + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLoclistsSection()); + TableEnd = emitLoclistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder + : InfoHolder); + } else { + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); + } + + unsigned char Size = Asm->MAI->getCodePointerSize(); + for (const auto &List : DebugLocs.getLists()) { + Asm->OutStreamer->EmitLabel(List.Label); + + const DwarfCompileUnit *CU = List.CU; + const MCSymbol *Base = CU->getBaseAddress(); + for (const auto &Entry : DebugLocs.getEntries(List)) { + if (Base) { + // Set up the range. This range is relative to the entry point of the + // compile unit. This is a hard coded 0 for low_pc when we're emitting + // ranges, or the DW_AT_low_pc on the compile unit otherwise. + if (IsLocLists) { + Asm->OutStreamer->AddComment("DW_LLE_offset_pair"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_offset_pair, 1); + Asm->OutStreamer->AddComment(" starting offset"); + Asm->EmitLabelDifferenceAsULEB128(Entry.BeginSym, Base); + Asm->OutStreamer->AddComment(" ending offset"); + Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Base); + } else { + Asm->EmitLabelDifference(Entry.BeginSym, Base, Size); + Asm->EmitLabelDifference(Entry.EndSym, Base, Size); + } + + emitDebugLocEntryLocation(Entry, CU); + continue; + } + + // We have no base address. + if (IsLocLists) { + // TODO: Use DW_LLE_base_addressx + DW_LLE_offset_pair, or + // DW_LLE_startx_length in case if there is only a single range. + // That should reduce the size of the debug data emited. + // For now just use the DW_LLE_startx_length for all cases. + Asm->OutStreamer->AddComment("DW_LLE_startx_length"); + Asm->emitInt8(dwarf::DW_LLE_startx_length); + Asm->OutStreamer->AddComment(" start idx"); + Asm->EmitULEB128(AddrPool.getIndex(Entry.BeginSym)); + Asm->OutStreamer->AddComment(" length"); + Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Entry.BeginSym); + } else { + Asm->OutStreamer->EmitSymbolValue(Entry.BeginSym, Size); + Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size); + } + + emitDebugLocEntryLocation(Entry, CU); + } + + if (IsLocLists) { + // .debug_loclists section ends with DW_LLE_end_of_list. + Asm->OutStreamer->AddComment("DW_LLE_end_of_list"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_end_of_list, 1); + } else { + // Terminate the .debug_loc list with two 0 values. + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + } + } + + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); +} + +void DwarfDebug::emitDebugLocDWO() { + 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 + + // offset_pair, so the implementations can't really share much since they + // need to use different representations) + // * as of October 2018, at least + // Ideally/in v5, this could use SectionLabels to reuse existing addresses + // in the address pool to minimize object size/relocations. + Asm->emitInt8(dwarf::DW_LLE_startx_length); + unsigned idx = AddrPool.getIndex(Entry.BeginSym); + Asm->EmitULEB128(idx); + Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4); + + emitDebugLocEntryLocation(Entry, List.CU); + } + Asm->emitInt8(dwarf::DW_LLE_end_of_list); + } +} + +struct ArangeSpan { + const MCSymbol *Start, *End; +}; + +// Emit a debug aranges section, containing a CU lookup for any +// address we can tie back to a CU. +void DwarfDebug::emitDebugARanges() { + // Provides a unique id per text section. + MapVector<MCSection *, SmallVector<SymbolCU, 8>> SectionMap; + + // Filter labels by section. + for (const SymbolCU &SCU : ArangeLabels) { + if (SCU.Sym->isInSection()) { + // Make a note of this symbol and it's section. + MCSection *Section = &SCU.Sym->getSection(); + if (!Section->getKind().isMetadata()) + SectionMap[Section].push_back(SCU); + } else { + // Some symbols (e.g. common/bss on mach-o) can have no section but still + // appear in the output. This sucks as we rely on sections to build + // arange spans. We can do it without, but it's icky. + SectionMap[nullptr].push_back(SCU); + } + } + + DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> Spans; + + for (auto &I : SectionMap) { + MCSection *Section = I.first; + SmallVector<SymbolCU, 8> &List = I.second; + if (List.size() < 1) + continue; + + // If we have no section (e.g. common), just write out + // individual spans for each symbol. + if (!Section) { + for (const SymbolCU &Cur : List) { + ArangeSpan Span; + Span.Start = Cur.Sym; + Span.End = nullptr; + assert(Cur.CU); + Spans[Cur.CU].push_back(Span); + } + continue; + } + + // Sort the symbols by offset within the section. + llvm::stable_sort(List, [&](const SymbolCU &A, const SymbolCU &B) { + unsigned IA = A.Sym ? Asm->OutStreamer->GetSymbolOrder(A.Sym) : 0; + unsigned IB = B.Sym ? Asm->OutStreamer->GetSymbolOrder(B.Sym) : 0; + + // Symbols with no order assigned should be placed at the end. + // (e.g. section end labels) + if (IA == 0) + return false; + if (IB == 0) + return true; + return IA < IB; + }); + + // Insert a final terminator. + List.push_back(SymbolCU(nullptr, Asm->OutStreamer->endSection(Section))); + + // Build spans between each label. + const MCSymbol *StartSym = List[0].Sym; + for (size_t n = 1, e = List.size(); n < e; n++) { + const SymbolCU &Prev = List[n - 1]; + const SymbolCU &Cur = List[n]; + + // Try and build the longest span we can within the same CU. + if (Cur.CU != Prev.CU) { + ArangeSpan Span; + Span.Start = StartSym; + Span.End = Cur.Sym; + assert(Prev.CU); + Spans[Prev.CU].push_back(Span); + StartSym = Cur.Sym; + } + } + } + + // Start the dwarf aranges section. + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfARangesSection()); + + unsigned PtrSize = Asm->MAI->getCodePointerSize(); + + // Build a list of CUs used. + std::vector<DwarfCompileUnit *> CUs; + for (const auto &it : Spans) { + DwarfCompileUnit *CU = it.first; + CUs.push_back(CU); + } + + // Sort the CU list (again, to ensure consistent output order). + llvm::sort(CUs, [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { + return A->getUniqueID() < B->getUniqueID(); + }); + + // Emit an arange table for each CU we used. + for (DwarfCompileUnit *CU : CUs) { + std::vector<ArangeSpan> &List = Spans[CU]; + + // Describe the skeleton CU's offset and length, not the dwo file's. + if (auto *Skel = CU->getSkeleton()) + CU = Skel; + + // Emit size of content not including length itself. + unsigned ContentSize = + sizeof(int16_t) + // DWARF ARange version number + sizeof(int32_t) + // Offset of CU in the .debug_info section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int8_t); // Segment Size (in bytes) + + unsigned TupleSize = PtrSize * 2; + + // 7.20 in the Dwarf specs requires the table to be aligned to a tuple. + unsigned Padding = + OffsetToAlignment(sizeof(int32_t) + ContentSize, TupleSize); + + ContentSize += Padding; + ContentSize += (List.size() + 1) * TupleSize; + + // For each compile unit, write the list of spans it covers. + Asm->OutStreamer->AddComment("Length of ARange Set"); + Asm->emitInt32(ContentSize); + Asm->OutStreamer->AddComment("DWARF Arange version number"); + Asm->emitInt16(dwarf::DW_ARANGES_VERSION); + Asm->OutStreamer->AddComment("Offset Into Debug Info Section"); + emitSectionReference(*CU); + Asm->OutStreamer->AddComment("Address Size (in bytes)"); + Asm->emitInt8(PtrSize); + Asm->OutStreamer->AddComment("Segment Size (in bytes)"); + Asm->emitInt8(0); + + Asm->OutStreamer->emitFill(Padding, 0xff); + + for (const ArangeSpan &Span : List) { + Asm->EmitLabelReference(Span.Start, PtrSize); + + // Calculate the size as being from the span start to it's end. + if (Span.End) { + Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize); + } else { + // For symbols without an end marker (e.g. common), we + // write a single arange entry containing just that one symbol. + uint64_t Size = SymSize[Span.Start]; + if (Size == 0) + Size = 1; + + Asm->OutStreamer->EmitIntValue(Size, PtrSize); + } + } + + Asm->OutStreamer->AddComment("ARange terminator"); + Asm->OutStreamer->EmitIntValue(0, PtrSize); + Asm->OutStreamer->EmitIntValue(0, PtrSize); + } +} + +/// Emit a single range list. We handle both DWARF v5 and earlier. +static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, + const RangeSpanList &List) { + + auto DwarfVersion = DD.getDwarfVersion(); + // Emit our symbol so we can find the beginning of the range. + Asm->OutStreamer->EmitLabel(List.getSym()); + // Gather all the ranges that apply to the same section so they can share + // a base address entry. + MapVector<const MCSection *, std::vector<const RangeSpan *>> SectionRanges; + // Size for our labels. + auto Size = Asm->MAI->getCodePointerSize(); + + for (const RangeSpan &Range : List.getRanges()) + SectionRanges[&Range.getStart()->getSection()].push_back(&Range); + + const DwarfCompileUnit &CU = List.getCU(); + const MCSymbol *CUBase = CU.getBaseAddress(); + bool BaseIsSet = false; + for (const auto &P : SectionRanges) { + // Don't bother with a base address entry if there's only one range in + // this section in this range list - for example ranges for a CU will + // usually consist of single regions from each of many sections + // (-ffunction-sections, or just C++ inline functions) except under LTO + // or optnone where there may be holes in a single CU's section + // contributions. + auto *Base = CUBase; + if (!Base && (P.second.size() > 1 || DwarfVersion < 5) && + (CU.getCUNode()->getRangesBaseAddress() || DwarfVersion >= 5)) { + BaseIsSet = true; + // FIXME/use care: This may not be a useful base address if it's not + // the lowest address/range in this object. + Base = P.second.front()->getStart(); + if (DwarfVersion >= 5) { + Base = DD.getSectionLabel(&Base->getSection()); + Asm->OutStreamer->AddComment("DW_RLE_base_addressx"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_addressx, 1); + Asm->OutStreamer->AddComment(" base address index"); + Asm->EmitULEB128(DD.getAddressPool().getIndex(Base)); + } else { + Asm->OutStreamer->EmitIntValue(-1, Size); + Asm->OutStreamer->AddComment(" base address"); + Asm->OutStreamer->EmitSymbolValue(Base, Size); + } + } else if (BaseIsSet && DwarfVersion < 5) { + BaseIsSet = false; + assert(!Base); + Asm->OutStreamer->EmitIntValue(-1, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + } + + for (const auto *RS : P.second) { + const MCSymbol *Begin = RS->getStart(); + const MCSymbol *End = RS->getEnd(); + assert(Begin && "Range without a begin symbol?"); + assert(End && "Range without an end symbol?"); + if (Base) { + if (DwarfVersion >= 5) { + // Emit DW_RLE_offset_pair when we have a base. + Asm->OutStreamer->AddComment("DW_RLE_offset_pair"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_offset_pair, 1); + Asm->OutStreamer->AddComment(" starting offset"); + Asm->EmitLabelDifferenceAsULEB128(Begin, Base); + Asm->OutStreamer->AddComment(" ending offset"); + Asm->EmitLabelDifferenceAsULEB128(End, Base); + } else { + Asm->EmitLabelDifference(Begin, Base, Size); + Asm->EmitLabelDifference(End, Base, Size); + } + } else if (DwarfVersion >= 5) { + Asm->OutStreamer->AddComment("DW_RLE_startx_length"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_startx_length, 1); + Asm->OutStreamer->AddComment(" start index"); + Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin)); + Asm->OutStreamer->AddComment(" length"); + Asm->EmitLabelDifferenceAsULEB128(End, Begin); + } else { + Asm->OutStreamer->EmitSymbolValue(Begin, Size); + Asm->OutStreamer->EmitSymbolValue(End, Size); + } + } + } + if (DwarfVersion >= 5) { + Asm->OutStreamer->AddComment("DW_RLE_end_of_list"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_end_of_list, 1); + } else { + // Terminate the list with two 0 values. + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + } +} + +static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm, + const DwarfFile &Holder, MCSymbol *TableEnd) { + for (const RangeSpanList &List : Holder.getRangeLists()) + emitRangeList(DD, Asm, List); + + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); +} + +/// 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); +} + +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); +} + +void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { + for (auto *MN : Nodes) { + if (auto *M = dyn_cast<DIMacro>(MN)) + emitMacro(*M); + else if (auto *F = dyn_cast<DIMacroFile>(MN)) + emitMacroFile(*F, U); + else + llvm_unreachable("Unexpected DI type!"); + } +} + +void DwarfDebug::emitMacro(DIMacro &M) { + Asm->EmitULEB128(M.getMacinfoType()); + Asm->EmitULEB128(M.getLine()); + StringRef Name = M.getName(); + StringRef Value = M.getValue(); + Asm->OutStreamer->EmitBytes(Name); + if (!Value.empty()) { + // There should be one space between macro name and macro value. + Asm->emitInt8(' '); + Asm->OutStreamer->EmitBytes(Value); + } + Asm->emitInt8('\0'); +} + +void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) { + assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); + Asm->EmitULEB128(dwarf::DW_MACINFO_start_file); + Asm->EmitULEB128(F.getLine()); + Asm->EmitULEB128(U.getOrCreateSourceID(F.getFile())); + handleMacroNodes(F.getElements(), U); + Asm->EmitULEB128(dwarf::DW_MACINFO_end_file); +} + +/// 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()); + + 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); + } + } + Asm->OutStreamer->AddComment("End Of Macro List Mark"); + Asm->emitInt8(0); +} + +// DWARF5 Experimental Separate Dwarf emitters. + +void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, + std::unique_ptr<DwarfCompileUnit> NewU) { + + if (!CompilationDir.empty()) + NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + + addGnuPubAttributes(*NewU, Die); + + SkeletonHolder.addUnit(std::move(NewU)); +} + +DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { + + auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( + CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); + + NewCU.initStmtList(); + + if (useSegmentedStringOffsetsTable()) + NewCU.addStringOffsetsStart(); + + initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit)); + + return NewCU; +} + +// Emit the .debug_info.dwo section for separated dwarf. This contains the +// compile units that would normally be in debug_info. +void DwarfDebug::emitDebugInfoDWO() { + assert(useSplitDwarf() && "No split dwarf debug info?"); + // Don't emit relocations into the dwo file. + InfoHolder.emitUnits(/* UseOffsets */ true); +} + +// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the +// abbreviations for the .debug_info.dwo section. +void DwarfDebug::emitDebugAbbrevDWO() { + assert(useSplitDwarf() && "No split dwarf?"); + InfoHolder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection()); +} + +void DwarfDebug::emitDebugLineDWO() { + assert(useSplitDwarf() && "No split dwarf?"); + SplitTypeUnitFileTable.Emit( + *Asm->OutStreamer, MCDwarfLineTableParams(), + Asm->getObjFileLowering().getDwarfLineDWOSection()); +} + +void DwarfDebug::emitStringOffsetsTableHeaderDWO() { + assert(useSplitDwarf() && "No split dwarf?"); + InfoHolder.getStringPool().emitStringOffsetsTableHeader( + *Asm, Asm->getObjFileLowering().getDwarfStrOffDWOSection(), + InfoHolder.getStringOffsetsStartSym()); +} + +// Emit the .debug_str.dwo section for separated dwarf. This contains the +// string section and is identical in format to traditional .debug_str +// sections. +void DwarfDebug::emitDebugStrDWO() { + if (useSegmentedStringOffsetsTable()) + emitStringOffsetsTableHeaderDWO(); + assert(useSplitDwarf() && "No split dwarf?"); + MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection(); + InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), + OffSec, /* UseRelativeOffsets = */ false); +} + +// Emit address pool. +void DwarfDebug::emitDebugAddr() { + AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection()); +} + +MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { + if (!useSplitDwarf()) + return nullptr; + const DICompileUnit *DIUnit = CU.getCUNode(); + SplitTypeUnitFileTable.maybeSetRootFile( + DIUnit->getDirectory(), DIUnit->getFilename(), + CU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource()); + return &SplitTypeUnitFileTable; +} + +uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) { + MD5 Hash; + Hash.update(Identifier); + // ... take the least significant 8 bytes and return those. Our MD5 + // implementation always returns its results in little endian, so we actually + // need the "high" word. + MD5::MD5Result Result; + Hash.final(Result); + return Result.high(); +} + +void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, + StringRef Identifier, DIE &RefDie, + const DICompositeType *CTy) { + // Fast path if we're building some type units and one has already used the + // address pool we know we're going to throw away all this work anyway, so + // don't bother building dependent types. + if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed()) + return; + + auto Ins = TypeSignatures.insert(std::make_pair(CTy, 0)); + if (!Ins.second) { + CU.addDIETypeSignature(RefDie, Ins.first->second); + return; + } + + bool TopLevelType = TypeUnitsUnderConstruction.empty(); + AddrPool.resetUsedFlag(); + + auto OwnedUnit = llvm::make_unique<DwarfTypeUnit>(CU, Asm, this, &InfoHolder, + getDwoLineTable(CU)); + DwarfTypeUnit &NewTU = *OwnedUnit; + DIE &UnitDie = NewTU.getUnitDie(); + TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy); + + NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + CU.getLanguage()); + + uint64_t Signature = makeTypeSignature(Identifier); + NewTU.setTypeSignature(Signature); + Ins.first->second = Signature; + + if (useSplitDwarf()) { + MCSection *Section = + getDwarfVersion() <= 4 + ? Asm->getObjFileLowering().getDwarfTypesDWOSection() + : Asm->getObjFileLowering().getDwarfInfoDWOSection(); + NewTU.setSection(Section); + } else { + MCSection *Section = + getDwarfVersion() <= 4 + ? Asm->getObjFileLowering().getDwarfTypesSection(Signature) + : Asm->getObjFileLowering().getDwarfInfoSection(Signature); + NewTU.setSection(Section); + // Non-split type units reuse the compile unit's line table. + CU.applyStmtList(UnitDie); + } + + // Add DW_AT_str_offsets_base to the type unit DIE, but not for split type + // units. + if (useSegmentedStringOffsetsTable() && !useSplitDwarf()) + NewTU.addStringOffsetsStart(); + + NewTU.setType(NewTU.createTypeDIE(CTy)); + + if (TopLevelType) { + auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction); + TypeUnitsUnderConstruction.clear(); + + // Types referencing entries in the address table cannot be placed in type + // units. + if (AddrPool.hasBeenUsed()) { + + // Remove all the types built while building this type. + // This is pessimistic as some of these types might not be dependent on + // the type that used an address. + for (const auto &TU : TypeUnitsToAdd) + TypeSignatures.erase(TU.second); + + // Construct this type in the CU directly. + // This is inefficient because all the dependent types will be rebuilt + // from scratch, including building them in type units, discovering that + // they depend on addresses, throwing them out and rebuilding them. + CU.constructTypeDIE(RefDie, cast<DICompositeType>(CTy)); + return; + } + + // If the type wasn't dependent on fission addresses, finish adding the type + // and all its dependent types. + for (auto &TU : TypeUnitsToAdd) { + InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get()); + InfoHolder.emitUnit(TU.first.get(), useSplitDwarf()); + } + } + CU.addDIETypeSignature(RefDie, Signature); +} + +DwarfDebug::NonTypeUnitContext::NonTypeUnitContext(DwarfDebug *DD) + : DD(DD), + TypeUnitsUnderConstruction(std::move(DD->TypeUnitsUnderConstruction)) { + DD->TypeUnitsUnderConstruction.clear(); + assert(TypeUnitsUnderConstruction.empty() || !DD->AddrPool.hasBeenUsed()); +} + +DwarfDebug::NonTypeUnitContext::~NonTypeUnitContext() { + DD->TypeUnitsUnderConstruction = std::move(TypeUnitsUnderConstruction); + DD->AddrPool.resetUsedFlag(); +} + +DwarfDebug::NonTypeUnitContext DwarfDebug::enterNonTypeUnitContext() { + return NonTypeUnitContext(this); +} + +// Add the Name along with its companion DIE to the appropriate accelerator +// table (for AccelTableKind::Dwarf it's always AccelDebugNames, for +// AccelTableKind::Apple, we use the table we got as an argument). If +// accelerator tables are disabled, this function does nothing. +template <typename DataT> +void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, + AccelTable<DataT> &AppleAccel, StringRef Name, + const DIE &Die) { + if (getAccelTableKind() == AccelTableKind::None) + return; + + if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Default) + return; + + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm, Name); + + switch (getAccelTableKind()) { + case AccelTableKind::Apple: + AppleAccel.addName(Ref, Die); + break; + case AccelTableKind::Dwarf: + AccelDebugNames.addName(Ref, Die); + break; + case AccelTableKind::Default: + llvm_unreachable("Default should have already been resolved."); + case AccelTableKind::None: + llvm_unreachable("None handled above"); + } +} + +void DwarfDebug::addAccelName(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + addAccelNameImpl(CU, AccelNames, Name, Die); +} + +void DwarfDebug::addAccelObjC(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + // ObjC names go only into the Apple accelerator tables. + if (getAccelTableKind() == AccelTableKind::Apple) + addAccelNameImpl(CU, AccelObjC, Name, Die); +} + +void DwarfDebug::addAccelNamespace(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + addAccelNameImpl(CU, AccelNamespace, Name, Die); +} + +void DwarfDebug::addAccelType(const DICompileUnit &CU, StringRef Name, + const DIE &Die, char Flags) { + addAccelNameImpl(CU, AccelTypes, Name, Die); +} + +uint16_t DwarfDebug::getDwarfVersion() const { + return Asm->OutStreamer->getContext().getDwarfVersion(); +} + +void DwarfDebug::addSectionLabel(const MCSymbol *Sym) { + SectionLabels.insert(std::make_pair(&Sym->getSection(), Sym)); +} + +const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) { + return SectionLabels.find(S)->second; +} |