X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=a4fb07eacb3bbf3ab43857b6fbc59d71fabe4066;hb=b60a342483e1ec9f1da9419f252f23aae8571843;hp=4e349f280c312b9e7138ff373855ef75fbab83cf;hpb=15552c46a0f3307e5e363dcce33638aa489fe928;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 4e349f280c3..a4fb07eacb3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -14,6 +14,7 @@ #include "DwarfDebug.h" #include "ByteStreamer.h" #include "DIEHash.h" +#include "DebugLocEntry.h" #include "DwarfCompileUnit.h" #include "DwarfExpression.h" #include "DwarfUnit.h" @@ -32,6 +33,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -103,6 +105,14 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden, clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); +static cl::opt +DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, + cl::desc("Emit DWARF linkage-name attributes."), + cl::values(clEnumVal(Default, "Default for platform"), + clEnumVal(Enable, "Enabled"), + clEnumVal(Disable, "Disabled"), clEnumValEnd), + cl::init(Default)); + static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; @@ -129,20 +139,22 @@ bool DebugLocDwarfExpression::isFrameRegister(unsigned MachineReg) { /// resolve - Look in the DwarfDebug map for the MDNode that /// corresponds to the reference. -template T DbgVariable::resolve(DIRef Ref) const { +template T *DbgVariable::resolve(TypedDINodeRef Ref) const { return DD->resolve(Ref); } bool DbgVariable::isBlockByrefVariable() const { assert(Var && "Invalid complex DbgVariable!"); - return Var.isBlockByrefVariable(DD->getTypeIdentifierMap()); + return Var->getType() + .resolve(DD->getTypeIdentifierMap()) + ->isBlockByrefStruct(); } -DIType DbgVariable::getType() const { - DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap()); +const DIType *DbgVariable::getType() const { + DIType *Ty = Var->getType().resolve(DD->getTypeIdentifierMap()); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. - if (Var.isBlockByrefVariable(DD->getTypeIdentifierMap())) { + 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 @@ -167,17 +179,17 @@ DIType DbgVariable::getType() const { 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(); + DIType *subType = Ty; + uint16_t tag = Ty->getTag(); if (tag == dwarf::DW_TAG_pointer_type) - subType = resolve(DITypeRef(cast(Ty)->getBaseType())); + subType = resolve(cast(Ty)->getBaseType()); - DIArray Elements(cast(subType)->getElements()); + auto Elements = cast(subType)->getElements(); for (unsigned i = 0, N = Elements.size(); i < N; ++i) { - DIDerivedType DT = cast(Elements[i]); - if (getName() == DT.getName()) - return (resolve(DT.getTypeDerivedFrom())); + auto *DT = cast(Elements[i]); + if (getName() == DT->getName()) + return resolve(DT->getBaseType()); } } return Ty; @@ -189,49 +201,71 @@ static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), PrevLabel(nullptr), - InfoHolder(A, "info_string", DIEValueAllocator), - UsedNonDefaultText(false), + : Asm(A), MMI(Asm->MMI), DebugLocs(A->OutStreamer->isVerboseAsm()), + PrevLabel(nullptr), InfoHolder(A, "info_string", DIEValueAllocator), SkeletonHolder(A, "skel_string", DIEValueAllocator), IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), - IsPS4(Triple(A->getTargetTriple()).isPS4()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), - AccelTypes(TypeAtoms) { + AccelTypes(TypeAtoms), DebuggerTuning(DebuggerKind::Default) { CurFn = nullptr; CurMI = nullptr; + Triple TT(Asm->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; - // Turn on accelerator tables for Darwin by default, pubnames by - // default for non-Darwin/PS4, and handle split dwarf. + // Turn on accelerator tables for LLDB by default. if (DwarfAccelTables == Default) - HasDwarfAccelTables = IsDarwin; + HasDwarfAccelTables = tuneForLLDB(); else HasDwarfAccelTables = DwarfAccelTables == Enable; + // Handle split DWARF. Off by default for now. if (SplitDwarf == Default) HasSplitDwarf = false; else HasSplitDwarf = SplitDwarf == Enable; + // Pubnames/pubtypes on by default for GDB. if (DwarfPubSections == Default) - HasDwarfPubSections = !IsDarwin && !IsPS4; + HasDwarfPubSections = tuneForGDB(); else HasDwarfPubSections = DwarfPubSections == Enable; + // SCE does not use linkage names. + if (DwarfLinkageNames == Default) + UseLinkageNames = !tuneForSCE(); + else + UseLinkageNames = DwarfLinkageNames == Enable; + unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion; DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber : MMI->getModule()->getDwarfVersion(); + // Use dwarf 4 by default if nothing is requested. + DwarfVersion = DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION; - // Darwin and PS4 use the standard TLS opcode (defined in DWARF 3). - // Everybody else uses GNU's. - UseGNUTLSOpcode = !(IsDarwin || IsPS4) || DwarfVersion < 3; + // 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; - Asm->OutStreamer.getContext().setDwarfVersion(DwarfVersion); + Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); @@ -274,41 +308,29 @@ static StringRef getObjCMethodName(StringRef In) { // TODO: Determine whether or not we should add names for programs // that do not have a DW_AT_name or DW_AT_linkage_name field - this // is only slightly different than the lookup of non-standard ObjC names. -void DwarfDebug::addSubprogramNames(DISubprogram SP, DIE &Die) { - if (!SP.isDefinition()) +void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) { + if (!SP->isDefinition()) return; - addAccelName(SP.getName(), Die); + addAccelName(SP->getName(), Die); // If the linkage name is different than the name, go ahead and output // that as well into the name table. - if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName()) - addAccelName(SP.getLinkageName(), Die); + if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName()) + addAccelName(SP->getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator // too. - if (isObjCClass(SP.getName())) { + if (isObjCClass(SP->getName())) { StringRef Class, Category; - getObjCClassCategory(SP.getName(), Class, Category); + getObjCClassCategory(SP->getName(), Class, Category); addAccelObjC(Class, Die); if (Category != "") addAccelObjC(Category, Die); // Also add the base method name to the name table. - addAccelName(getObjCMethodName(SP.getName()), Die); + addAccelName(getObjCMethodName(SP->getName()), Die); } } -/// isSubprogramContext - Return true if Context is either a subprogram -/// or another context nested inside a subprogram. -bool DwarfDebug::isSubprogramContext(const MDNode *Context) { - if (!Context) - return false; - if (isa(Context)) - return true; - if (DIType T = dyn_cast(Context)) - return isSubprogramContext(resolve(T.getContext())); - return false; -} - /// 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) { @@ -360,9 +382,10 @@ void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { // Create new DwarfCompileUnit for the given metadata node with tag // DW_TAG_compile_unit. -DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { - StringRef FN = DIUnit.getFilename(); - CompilationDir = DIUnit.getDirectory(); +DwarfCompileUnit & +DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) { + StringRef FN = DIUnit->getFilename(); + CompilationDir = DIUnit->getDirectory(); auto OwnedUnit = make_unique( InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); @@ -376,13 +399,13 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { // 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.getContext().setMCLineTableCompilationDir( + if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) + Asm->OutStreamer->getContext().setMCLineTableCompilationDir( NewCU.getUniqueID(), CompilationDir); - NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); + NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit->getProducer()); NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - DIUnit.getLanguage()); + DIUnit->getSourceLanguage()); NewCU.addString(Die, dwarf::DW_AT_name, FN); if (!useSplitDwarf()) { @@ -396,14 +419,14 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { addGnuPubAttributes(NewCU, Die); } - if (DIUnit.isOptimized()) + if (DIUnit->isOptimized()) NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized); - StringRef Flags = DIUnit.getFlags(); + StringRef Flags = DIUnit->getFlags(); if (!Flags.empty()) NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags); - if (unsigned RVer = DIUnit.getRunTimeVersion()) + if (unsigned RVer = DIUnit->getRuntimeVersion()) NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, dwarf::DW_FORM_data1, RVer); @@ -412,16 +435,25 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { else NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection()); + 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()); + } + CUMap.insert(std::make_pair(DIUnit, &NewCU)); CUDieMap.insert(std::make_pair(&Die, &NewCU)); return NewCU; } void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, - const MDNode *N) { - DIImportedEntity Module = cast(N); - if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) - D->addChild(TheCU.constructImportedEntityDIE(Module)); + const DIImportedEntity *N) { + if (DIE *D = TheCU.getOrCreateContextDIE(N->getScope())) + D->addChild(TheCU.constructImportedEntityDIE(N)); } // Emit all Dwarf sections that should come prior to the content. Create @@ -433,8 +465,6 @@ void DwarfDebug::beginModule() { const Module *M = MMI->getModule(); - FunctionDIs = makeSubprogramMap(*M); - NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; @@ -443,30 +473,26 @@ void DwarfDebug::beginModule() { SingleCU = CU_Nodes->getNumOperands() == 1; for (MDNode *N : CU_Nodes->operands()) { - DICompileUnit CUNode = cast(N); + auto *CUNode = cast(N); DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); for (auto *IE : CUNode->getImportedEntities()) - ScopesWithImportedEntities.push_back(std::make_pair(IE->getScope(), IE)); - // Stable sort to preserve the order of appearance of imported entities. - // This is to avoid out-of-order processing of interdependent declarations - // within the same scope, e.g. { namespace A = base; namespace B = A; } - std::stable_sort(ScopesWithImportedEntities.begin(), - ScopesWithImportedEntities.end(), less_first()); + CU.addImportedEntity(IE); for (auto *GV : CUNode->getGlobalVariables()) CU.getOrCreateGlobalVariableDIE(GV); for (auto *SP : CUNode->getSubprograms()) SPMap.insert(std::make_pair(SP, &CU)); - for (DIType Ty : CUNode->getEnumTypes()) { + for (auto *Ty : CUNode->getEnumTypes()) { // The enum types array by design contains pointers to // MDNodes rather than DIRefs. Unique them here. - DIType UniqueTy = cast(resolve(Ty.getRef())); - CU.getOrCreateTypeDIE(UniqueTy); + CU.getOrCreateTypeDIE(cast(resolve(Ty->getRef()))); } - for (DIType Ty : CUNode->getRetainedTypes()) { + for (auto *Ty : CUNode->getRetainedTypes()) { // The retained types array by design contains pointers to // MDNodes rather than DIRefs. Unique them here. - DIType UniqueTy = cast(resolve(Ty.getRef())); - CU.getOrCreateTypeDIE(UniqueTy); + DIType *RT = cast(resolve(Ty->getRef())); + if (!RT->isExternalTypeRef()) + // 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. @@ -487,7 +513,8 @@ void DwarfDebug::finishVariableDefinitions() { // DIE::getUnit isn't simple - it walks parent pointers, etc. DwarfCompileUnit *Unit = lookupUnit(VariableDie->getUnit()); assert(Unit); - DbgVariable *AbsVar = getExistingAbstractVariable(Var->getVariable()); + DbgVariable *AbsVar = getExistingAbstractVariable( + InlinedVariable(Var->getVariable(), Var->getInlinedAt())); if (AbsVar && AbsVar->getDIE()) { Unit->addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin, *AbsVar->getDIE()); @@ -499,7 +526,7 @@ void DwarfDebug::finishVariableDefinitions() { void DwarfDebug::finishSubprogramDefinitions() { for (const auto &P : SPMap) forBothCUs(*P.second, [&](DwarfCompileUnit &CU) { - CU.finishSubprogramDefinition(cast(P.first)); + CU.finishSubprogramDefinition(cast(P.first)); }); } @@ -510,7 +537,7 @@ void DwarfDebug::collectDeadVariables() { if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (MDNode *N : CU_Nodes->operands()) { - DICompileUnit TheCU = cast(N); + auto *TheCU = cast(N); // Construct subprogram DIE and add variables DIEs. DwarfCompileUnit *SPCU = static_cast(CUMap.lookup(TheCU)); @@ -534,6 +561,8 @@ void DwarfDebug::finalizeModuleInfo() { // Collect info for variables that were optimized out. collectDeadVariables(); + unsigned MacroOffset = 0; + std::unique_ptr AS(new SizeReporterAsmStreamer(Asm)); // Handle anything that needs to be done on a per-unit basis after // all other generation. for (const auto &P : CUMap) { @@ -583,9 +612,18 @@ void DwarfDebug::finalizeModuleInfo() { // 2.17.3). U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); else - TheCU.setBaseAddress(TheCU.getRanges().front().getStart()); + U.setBaseAddress(TheCU.getRanges().front().getStart()); U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges()); } + + auto *CUNode = cast(P.first); + if (CUNode->getMacros()) { + // Compile Unit has macros, emit "DW_AT_macro_info" attribute. + U.addUInt(U.getUnitDie(), dwarf::DW_AT_macro_info, + dwarf::DW_FORM_sec_offset, MacroOffset); + // Update macro section offset + MacroOffset += handleMacroNodes(AS.get(), CUNode->getMacros(), U); + } } // Compute DIE offsets and sizes. @@ -629,6 +667,9 @@ void DwarfDebug::endModule() { // Emit info into a debug ranges section. emitDebugRanges(); + // Emit info into a debug macinfo section. + emitDebugMacinfo(); + if (useSplitDwarf()) { emitDebugStrDWO(); emitDebugInfoDWO(); @@ -658,74 +699,70 @@ void DwarfDebug::endModule() { } // Find abstract variable, if any, associated with Var. -DbgVariable *DwarfDebug::getExistingAbstractVariable(const DIVariable &DV, - DIVariable &Cleansed) { - LLVMContext &Ctx = DV->getContext(); +DbgVariable * +DwarfDebug::getExistingAbstractVariable(InlinedVariable IV, + const DILocalVariable *&Cleansed) { // More then one inlined variable corresponds to one abstract variable. - // FIXME: This duplication of variables when inlining should probably be - // removed. It's done to allow each DIVariable to describe its location - // because the DebugLoc on the dbg.value/declare isn't accurate. We should - // make it accurate then remove this duplication/cleansing stuff. - Cleansed = cleanseInlinedVariable(DV, Ctx); + Cleansed = IV.first; auto I = AbstractVariables.find(Cleansed); if (I != AbstractVariables.end()) return I->second.get(); return nullptr; } -DbgVariable *DwarfDebug::getExistingAbstractVariable(const DIVariable &DV) { - DIVariable Cleansed; - return getExistingAbstractVariable(DV, Cleansed); +DbgVariable *DwarfDebug::getExistingAbstractVariable(InlinedVariable IV) { + const DILocalVariable *Cleansed; + return getExistingAbstractVariable(IV, Cleansed); } -void DwarfDebug::createAbstractVariable(const DIVariable &Var, +void DwarfDebug::createAbstractVariable(const DILocalVariable *Var, LexicalScope *Scope) { - auto AbsDbgVariable = make_unique(Var, DIExpression(), this); + auto AbsDbgVariable = make_unique(Var, /* IA */ nullptr, this); InfoHolder.addScopeVariable(Scope, AbsDbgVariable.get()); AbstractVariables[Var] = std::move(AbsDbgVariable); } -void DwarfDebug::ensureAbstractVariableIsCreated(const DIVariable &DV, +void DwarfDebug::ensureAbstractVariableIsCreated(InlinedVariable IV, const MDNode *ScopeNode) { - DIVariable Cleansed = DV; - if (getExistingAbstractVariable(DV, Cleansed)) + const DILocalVariable *Cleansed = nullptr; + if (getExistingAbstractVariable(IV, Cleansed)) return; createAbstractVariable(Cleansed, LScopes.getOrCreateAbstractScope( - cast(ScopeNode))); + cast(ScopeNode))); } -void -DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(const DIVariable &DV, - const MDNode *ScopeNode) { - DIVariable Cleansed = DV; - if (getExistingAbstractVariable(DV, Cleansed)) +void DwarfDebug::ensureAbstractVariableIsCreatedIfScoped( + InlinedVariable IV, const MDNode *ScopeNode) { + const DILocalVariable *Cleansed = nullptr; + if (getExistingAbstractVariable(IV, Cleansed)) return; if (LexicalScope *Scope = - LScopes.findAbstractScope(cast_or_null(ScopeNode))) + LScopes.findAbstractScope(cast_or_null(ScopeNode))) createAbstractVariable(Cleansed, Scope); } // Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable( - SmallPtrSetImpl &Processed) { + DenseSet &Processed) { for (const auto &VI : MMI->getVariableDbgInfo()) { if (!VI.Var) continue; - Processed.insert(VI.Var); + assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) && + "Expected inlined-at fields to agree"); + + InlinedVariable 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; - DIVariable DV = cast(VI.Var); - assert(DV->isValidLocationForIntrinsic(VI.Loc) && - "Expected inlined-at fields to agree"); - DIExpression Expr = cast_or_null(VI.Expr); - ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - auto RegVar = make_unique(DV, Expr, this, VI.Slot); + ensureAbstractVariableIsCreatedIfScoped(Var, Scope->getScopeNode()); + auto RegVar = make_unique(Var.first, Var.second, this); + RegVar->initializeMMI(VI.Expr, VI.Slot); if (InfoHolder.addScopeVariable(Scope, RegVar.get())) ConcreteVariables.push_back(std::move(RegVar)); } @@ -733,8 +770,7 @@ void DwarfDebug::collectVariableInfoFromMMITable( // Get .debug_loc entry for the instruction range starting at MI. static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { - const MDNode *Expr = MI->getDebugExpression(); - const MDNode *Var = MI->getDebugVariable(); + const DIExpression *Expr = MI->getDebugExpression(); assert(MI->getNumOperands() == 4); if (MI->getOperand(0).isReg()) { @@ -745,20 +781,20 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); - return DebugLocEntry::Value(Var, Expr, MLoc); + return DebugLocEntry::Value(Expr, MLoc); } if (MI->getOperand(0).isImm()) - return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getImm()); + return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) - return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getFPImm()); + return DebugLocEntry::Value(Expr, MI->getOperand(0).getFPImm()); if (MI->getOperand(0).isCImm()) - return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getCImm()); + return DebugLocEntry::Value(Expr, MI->getOperand(0).getCImm()); llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); } /// Determine whether two variable pieces overlap. -static bool piecesOverlap(DIExpression P1, DIExpression P2) { +static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2) { if (!P1->isBitPiece() || !P2->isBitPiece()) return true; unsigned l1 = P1->getBitPieceOffset(); @@ -810,7 +846,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, } // If this piece overlaps with any open ranges, truncate them. - DIExpression DIExpr = Begin->getDebugExpression(); + const DIExpression *DIExpr = Begin->getDebugExpression(); auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), [&](DebugLocEntry::Value R) { return piecesOverlap(DIExpr, R.getExpression()); @@ -858,85 +894,89 @@ DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, // Attempt to coalesce the ranges of two otherwise identical // DebugLocEntries. auto CurEntry = DebugLoc.rbegin(); - auto PrevEntry = std::next(CurEntry); - if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) - DebugLoc.pop_back(); - DEBUG({ dbgs() << CurEntry->getValues().size() << " Values:\n"; - for (auto Value : CurEntry->getValues()) { - Value.getVariable()->dump(); + for (auto &Value : CurEntry->getValues()) Value.getExpression()->dump(); - } dbgs() << "-----\n"; }); + + auto PrevEntry = std::next(CurEntry); + if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) + DebugLoc.pop_back(); } } +DbgVariable *DwarfDebug::createConcreteVariable(LexicalScope &Scope, + InlinedVariable IV) { + ensureAbstractVariableIsCreatedIfScoped(IV, Scope.getScopeNode()); + ConcreteVariables.push_back( + make_unique(IV.first, IV.second, this)); + InfoHolder.addScopeVariable(&Scope, ConcreteVariables.back().get()); + return ConcreteVariables.back().get(); +} // Find variables for each lexical scope. -void -DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP, - SmallPtrSetImpl &Processed) { +void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, + const DISubprogram *SP, + DenseSet &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMMITable(Processed); for (const auto &I : DbgValues) { - DIVariable DV = cast(I.first); - if (Processed.count(DV)) + InlinedVariable IV = I.first; + if (Processed.count(IV)) continue; - // Instruction ranges, specifying where DV is accessible. + // Instruction ranges, specifying where IV is accessible. const auto &Ranges = I.second; if (Ranges.empty()) continue; LexicalScope *Scope = nullptr; - if (MDLocation *IA = DV.get()->getInlinedAt()) - Scope = LScopes.findInlinedScope(DV.get()->getScope(), IA); + if (const DILocation *IA = IV.second) + Scope = LScopes.findInlinedScope(IV.first->getScope(), IA); else - Scope = LScopes.findLexicalScope(DV.get()->getScope()); + Scope = LScopes.findLexicalScope(IV.first->getScope()); // If variable scope is not found then skip this variable. if (!Scope) continue; - Processed.insert(DV); + Processed.insert(IV); + DbgVariable *RegVar = createConcreteVariable(*Scope, IV); + const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); - ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - ConcreteVariables.push_back(make_unique(MInsn, this)); - DbgVariable *RegVar = ConcreteVariables.back().get(); - InfoHolder.addScopeVariable(Scope, RegVar); // Check if the first DBG_VALUE is valid for the rest of the function. - if (Ranges.size() == 1 && Ranges.front().second == nullptr) + if (Ranges.size() == 1 && Ranges.front().second == nullptr) { + RegVar->initializeDbgValue(MInsn); continue; + } // Handle multiple DBG_VALUE instructions describing one variable. - RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); - - DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); - DebugLocList &LocList = DotDebugLocEntries.back(); - LocList.CU = &TheCU; - LocList.Label = Asm->createTempSymbol("debug_loc"); + DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn); // Build the location list for this variable. - buildLocationList(LocList.List, Ranges); + SmallVector Entries; + buildLocationList(Entries, Ranges); + + // If the variable has an 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( + static_cast(IV.first->getType())); + // Finalize the entry by lowering it into a DWARF bytestream. - for (auto &Entry : LocList.List) - Entry.finalize(*Asm, TypeIdentifierMap); + for (auto &Entry : Entries) + Entry.finalize(*Asm, List, BT); } // Collect info for variables that were optimized out. - for (DIVariable DV : SP->getVariables()) { - if (!Processed.insert(DV).second) - continue; - if (LexicalScope *Scope = LScopes.findLexicalScope(DV.get()->getScope())) { - ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - DIExpression NoExpr; - ConcreteVariables.push_back(make_unique(DV, NoExpr, this)); - InfoHolder.addScopeVariable(Scope, ConcreteVariables.back().get()); - } + for (const DILocalVariable *DV : SP->getVariables()) { + if (Processed.insert(InlinedVariable(DV, nullptr)).second) + if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) + createConcreteVariable(*Scope, InlinedVariable(DV, nullptr)); } } @@ -969,7 +1009,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { Flags |= DWARF2_FLAG_IS_STMT; } if (DL.getLine() != - Asm->OutStreamer.getContext().getCurrentDwarfLoc().getLine()) + Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine()) Flags |= DWARF2_FLAG_IS_STMT; const MDNode *Scope = DL.getScope(); @@ -994,8 +1034,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { return; if (!PrevLabel) { - PrevLabel = MMI->getContext().CreateTempSymbol(); - Asm->OutStreamer.EmitLabel(PrevLabel); + PrevLabel = MMI->getContext().createTempSymbol(); + Asm->OutStreamer->EmitLabel(PrevLabel); } I->second = PrevLabel; } @@ -1022,8 +1062,8 @@ void DwarfDebug::endInstruction() { // We need a label after this instruction. if (!PrevLabel) { - PrevLabel = MMI->getContext().CreateTempSymbol(); - Asm->OutStreamer.EmitLabel(PrevLabel); + PrevLabel = MMI->getContext().createTempSymbol(); + Asm->OutStreamer->EmitLabel(PrevLabel); } I->second = PrevLabel; } @@ -1060,12 +1100,8 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { for (const auto &MBB : *MF) for (const auto &MI : MBB) if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) && - MI.getDebugLoc()) { - // Did the target forget to set the FrameSetup flag for CFI insns? - assert(!MI.isCFIInstruction() && - "First non-frame-setup instruction is a CFI instruction."); + MI.getDebugLoc()) return MI.getDebugLoc(); - } return DebugLoc(); } @@ -1078,8 +1114,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (!MMI->hasDebugInfo()) return; - auto DI = FunctionDIs.find(MF->getFunction()); - if (DI == FunctionDIs.end()) + auto DI = MF->getFunction()->getSubprogram(); + if (!DI) return; // Grab the lexical scopes for the function, if we don't have any of those @@ -1107,11 +1143,11 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // is absolute (such as an <> lookup header))) DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); - if (Asm->OutStreamer.hasRawTextSupport()) + if (Asm->OutStreamer->hasRawTextSupport()) // Use a single line table if we are generating assembly. - Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); + Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); else - Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); + Asm->OutStreamer->getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); // Calculate history for local variables. calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), @@ -1125,14 +1161,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // The first mention of a function argument gets the CurrentFnBegin // label, so arguments are visible when breaking at function entry. - DIVariable DIVar = Ranges.front().first->getDebugVariable(); - if (DIVar.getTag() == dwarf::DW_TAG_arg_variable && - getDISubprogram(DIVar.getContext()).describes(MF->getFunction())) { + const DILocalVariable *DIVar = Ranges.front().first->getDebugVariable(); + if (DIVar->isParameter() && + getDISubprogram(DIVar->getScope())->describes(MF->getFunction())) { LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin(); if (Ranges.front().first->getDebugExpression()->isBitPiece()) { // Mark all non-overlapping initial pieces. for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { - DIExpression Piece = I->first->getDebugExpression(); + const DIExpression *Piece = I->first->getDebugExpression(); if (std::all_of(Ranges.begin(), I, [&](DbgValueHistoryMap::InstrRange Pred) { return !piecesOverlap(Piece, Pred.first->getDebugExpression()); @@ -1156,7 +1192,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Record beginning of function. PrologEndLoc = findPrologueEndLoc(MF); - if (MDLocation *L = PrologEndLoc) { + if (DILocation *L = PrologEndLoc) { // 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. auto *SP = L->getInlinedAtScope()->getSubprogram(); @@ -1170,7 +1206,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { "endFunction should be called with the same function as beginFunction"); if (!MMI->hasDebugInfo() || LScopes.empty() || - !FunctionDIs.count(MF->getFunction())) { + !MF->getFunction()->getSubprogram()) { // If we don't have a lexical scope 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. @@ -1180,13 +1216,13 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { } // Set DwarfDwarfCompileUnitID in MCContext to default value. - Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); + Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DISubprogram SP = cast(FnScope->getScopeNode()); + auto *SP = cast(FnScope->getScopeNode()); DwarfCompileUnit &TheCU = *SPMap.lookup(SP); - SmallPtrSet ProcessedVars; + DenseSet ProcessedVars; collectVariableInfo(TheCU, SP, ProcessedVars); // Add the range of this function to the list of ranges for the CU. @@ -1194,7 +1230,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Under -gmlt, skip building the subprogram if there are no inlined // subroutines inside it. - if (TheCU.getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly && + if (TheCU.getCUNode()->getEmissionKind() == DIBuilder::LineTablesOnly && LScopes.getAbstractScopesList().empty() && !IsDarwin) { assert(InfoHolder.getScopeVariables().empty()); assert(DbgValues.empty()); @@ -1213,12 +1249,13 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { #endif // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { - DISubprogram SP = cast(AScope->getScopeNode()); + auto *SP = cast(AScope->getScopeNode()); // Collect info for variables that were optimized out. - for (DIVariable DV : SP->getVariables()) { - if (!ProcessedVars.insert(DV).second) + for (const DILocalVariable *DV : SP->getVariables()) { + if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) continue; - ensureAbstractVariableIsCreated(DV, DV.getContext()); + ensureAbstractVariableIsCreated(InlinedVariable(DV, nullptr), + DV->getScope()); assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes && "ensureAbstractVariableIsCreated inserted abstract scopes"); } @@ -1250,18 +1287,18 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, StringRef Dir; unsigned Src = 1; unsigned Discriminator = 0; - if (DIScope Scope = cast_or_null(S)) { - Fn = Scope.getFilename(); - Dir = Scope.getDirectory(); - if (DILexicalBlockFile LBF = dyn_cast(Scope)) - Discriminator = LBF.getDiscriminator(); + if (auto *Scope = cast_or_null(S)) { + Fn = Scope->getFilename(); + Dir = Scope->getDirectory(); + if (auto *LBF = dyn_cast(Scope)) + Discriminator = LBF->getDiscriminator(); - unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); + unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID(); Src = static_cast(*InfoHolder.getUnits()[CUID]) .getOrCreateSourceID(Fn, Dir); } - Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, - Discriminator, Fn); + Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0, + Discriminator, Fn); } //===----------------------------------------------------------------------===// @@ -1281,10 +1318,10 @@ void DwarfDebug::emitAbbreviations() { Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); } -void DwarfDebug::emitAccel(DwarfAccelTable &Accel, const MCSection *Section, +void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section, StringRef TableName) { Accel.FinalizeTable(Asm, TableName); - Asm->OutStreamer.SwitchSection(Section); + Asm->OutStreamer->SwitchSection(Section); // Emit the full data. Accel.emit(Asm, Section->getBeginSymbol(), this); @@ -1337,9 +1374,8 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, // We could have a specification DIE that has our most of our knowledge, // look for that now. - DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification); - if (SpecVal) { - DIE &SpecDIE = cast(SpecVal)->getEntry(); + 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)) @@ -1375,16 +1411,16 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, /// emitDebugPubNames - Emit visible names into a debug pubnames section. /// void DwarfDebug::emitDebugPubNames(bool GnuStyle) { - const MCSection *PSec = - GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() - : Asm->getObjFileLowering().getDwarfPubNamesSection(); + MCSection *PSec = GnuStyle + ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() + : Asm->getObjFileLowering().getDwarfPubNamesSection(); emitDebugPubSection(GnuStyle, PSec, "Names", &DwarfCompileUnit::getGlobalNames); } void DwarfDebug::emitDebugPubSection( - bool GnuStyle, const MCSection *PSec, StringRef Name, + bool GnuStyle, MCSection *PSec, StringRef Name, const StringMap &(DwarfCompileUnit::*Accessor)() const) { for (const auto &NU : CUMap) { DwarfCompileUnit *TheU = NU.second; @@ -1398,23 +1434,23 @@ void DwarfDebug::emitDebugPubSection( TheU = Skeleton; // Start the dwarf pubnames section. - Asm->OutStreamer.SwitchSection(PSec); + Asm->OutStreamer->SwitchSection(PSec); // Emit the header. - Asm->OutStreamer.AddComment("Length of Public " + Name + " Info"); + 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->EmitLabel(BeginLabel); - Asm->OutStreamer.AddComment("DWARF Version"); + Asm->OutStreamer->AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); - Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); - Asm->emitSectionOffset(TheU->getLabelBegin()); + Asm->OutStreamer->AddComment("Offset of Compilation Unit Info"); + Asm->emitDwarfSymbolReference(TheU->getLabelBegin()); - Asm->OutStreamer.AddComment("Compilation Unit Length"); + Asm->OutStreamer->AddComment("Compilation Unit Length"); Asm->EmitInt32(TheU->getLength()); // Emit the pubnames for this compilation unit. @@ -1422,31 +1458,31 @@ void DwarfDebug::emitDebugPubSection( const char *Name = GI.getKeyData(); const DIE *Entity = GI.second; - Asm->OutStreamer.AddComment("DIE offset"); + Asm->OutStreamer->AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); if (GnuStyle) { dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); - Asm->OutStreamer.AddComment( + Asm->OutStreamer->AddComment( Twine("Kind: ") + 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("External Name"); + Asm->OutStreamer->EmitBytes(StringRef(Name, GI.getKeyLength() + 1)); } - Asm->OutStreamer.AddComment("End Mark"); + Asm->OutStreamer->AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(EndLabel); + Asm->OutStreamer->EmitLabel(EndLabel); } } void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { - const MCSection *PSec = - GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() - : Asm->getObjFileLowering().getDwarfPubTypesSection(); + MCSection *PSec = GnuStyle + ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() + : Asm->getObjFileLowering().getDwarfPubTypesSection(); emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfCompileUnit::getGlobalTypes); @@ -1458,36 +1494,32 @@ void DwarfDebug::emitDebugStr() { Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } - void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, - const DebugLocEntry &Entry) { - auto Comment = Entry.getComments().begin(); - auto End = Entry.getComments().end(); - for (uint8_t Byte : Entry.getDWARFBytes()) + const DebugLocStream::Entry &Entry) { + auto &&Comments = DebugLocs.getComments(Entry); + auto Comment = Comments.begin(); + auto End = Comments.end(); + for (uint8_t Byte : DebugLocs.getBytes(Entry)) Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : ""); } -static void emitDebugLocValue(const AsmPrinter &AP, - const DITypeIdentifierMap &TypeIdentifierMap, +static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, ByteStreamer &Streamer, const DebugLocEntry::Value &Value, unsigned PieceOffsetInBits) { - DIVariable DV = Value.getVariable(); DebugLocDwarfExpression DwarfExpr(*AP.MF->getSubtarget().getRegisterInfo(), AP.getDwarfDebug()->getDwarfVersion(), Streamer); // Regular entry. if (Value.isInt()) { - MDType *T = DV.getType().resolve(TypeIdentifierMap); - auto *B = dyn_cast(T); - if (B && (B->getEncoding() == dwarf::DW_ATE_signed || - B->getEncoding() == dwarf::DW_ATE_signed_char)) + 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 Loc = Value.getLoc(); - DIExpression Expr = Value.getExpression(); + const DIExpression *Expr = Value.getExpression(); if (!Expr || !Expr->getNumElements()) // Regular entry. AP.EmitDwarfRegOp(Streamer, Loc); @@ -1507,11 +1539,12 @@ static void emitDebugLocValue(const AsmPrinter &AP, // FIXME: ^ } - void DebugLocEntry::finalize(const AsmPrinter &AP, - const DITypeIdentifierMap &TypeIdentifierMap) { - BufferByteStreamer Streamer(DWARFBytes, Comments); - const DebugLocEntry::Value Value = Values[0]; + DebugLocStream::ListBuilder &List, + const DIBasicType *BT) { + DebugLocStream::EntryBuilder Entry(List, Begin, End); + BufferByteStreamer Streamer = Entry.getStreamer(); + const DebugLocEntry::Value &Value = Values[0]; if (Value.isBitPiece()) { // Emit all pieces that belong to the same variable and range. assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) { @@ -1522,7 +1555,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, unsigned Offset = 0; for (auto Piece : Values) { - DIExpression Expr = Piece.getExpression(); + const DIExpression *Expr = Piece.getExpression(); unsigned PieceOffset = Expr->getBitPieceOffset(); unsigned PieceSize = Expr->getBitPieceSize(); assert(Offset <= PieceOffset && "overlapping or duplicate pieces"); @@ -1536,70 +1569,66 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, } Offset += PieceSize; - emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Piece, PieceOffset); + emitDebugLocValue(AP, BT, Streamer, Piece, PieceOffset); } } else { assert(Values.size() == 1 && "only pieces may have >1 value"); - emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Value, 0); + emitDebugLocValue(AP, BT, Streamer, Value, 0); } } +void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) { + // Emit the size. + Asm->OutStreamer->AddComment("Loc expr size"); + Asm->EmitInt16(DebugLocs.getBytes(Entry).size()); -void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) { - Asm->OutStreamer.AddComment("Loc expr size"); - MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); - MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); - Asm->EmitLabelDifference(end, begin, 2); - Asm->OutStreamer.EmitLabel(begin); // Emit the entry. APByteStreamer Streamer(*Asm); emitDebugLocEntry(Streamer, Entry); - // Close the range. - Asm->OutStreamer.EmitLabel(end); } // Emit locations into the debug loc section. void DwarfDebug::emitDebugLoc() { // Start the dwarf loc section. - Asm->OutStreamer.SwitchSection( + Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfLocSection()); unsigned char Size = Asm->getDataLayout().getPointerSize(); - for (const auto &DebugLoc : DotDebugLocEntries) { - Asm->OutStreamer.EmitLabel(DebugLoc.Label); - const DwarfCompileUnit *CU = DebugLoc.CU; - for (const auto &Entry : DebugLoc.List) { + for (const auto &List : DebugLocs.getLists()) { + Asm->OutStreamer->EmitLabel(List.Label); + const DwarfCompileUnit *CU = List.CU; + for (const auto &Entry : DebugLocs.getEntries(List)) { // 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 (auto *Base = CU->getBaseAddress()) { - Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size); - Asm->EmitLabelDifference(Entry.getEndSym(), Base, Size); + Asm->EmitLabelDifference(Entry.BeginSym, Base, Size); + Asm->EmitLabelDifference(Entry.EndSym, Base, Size); } else { - Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size); - Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size); + Asm->OutStreamer->EmitSymbolValue(Entry.BeginSym, Size); + Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size); } emitDebugLocEntryLocation(Entry); } - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); } } void DwarfDebug::emitDebugLocDWO() { - Asm->OutStreamer.SwitchSection( + Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfLocDWOSection()); - for (const auto &DebugLoc : DotDebugLocEntries) { - Asm->OutStreamer.EmitLabel(DebugLoc.Label); - for (const auto &Entry : DebugLoc.List) { + for (const auto &List : DebugLocs.getLists()) { + Asm->OutStreamer->EmitLabel(List.Label); + for (const auto &Entry : DebugLocs.getEntries(List)) { // Just always use start_length for now - at least that's one address // rather than two. We could get fancier and try to, say, reuse an // address we know we've emitted elsewhere (the start of the function? // The start of the CU or CU subrange that encloses this range?) Asm->EmitInt8(dwarf::DW_LLE_start_length_entry); - unsigned idx = AddrPool.getIndex(Entry.getBeginSym()); + unsigned idx = AddrPool.getIndex(Entry.BeginSym); Asm->EmitULEB128(idx); - Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4); + Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4); emitDebugLocEntryLocation(Entry); } @@ -1615,13 +1644,13 @@ struct ArangeSpan { // address we can tie back to a CU. void DwarfDebug::emitDebugARanges() { // Provides a unique id per text section. - MapVector> SectionMap; + MapVector> SectionMap; // Filter labels by section. for (const SymbolCU &SCU : ArangeLabels) { if (SCU.Sym->isInSection()) { // Make a note of this symbol and it's section. - const MCSection *Section = &SCU.Sym->getSection(); + MCSection *Section = &SCU.Sym->getSection(); if (!Section->getKind().isMetadata()) SectionMap[Section].push_back(SCU); } else { @@ -1634,11 +1663,11 @@ void DwarfDebug::emitDebugARanges() { // Add terminating symbols for each section. for (const auto &I : SectionMap) { - const MCSection *Section = I.first; + MCSection *Section = I.first; MCSymbol *Sym = nullptr; if (Section) - Sym = Asm->OutStreamer.endSection(Section); + Sym = Asm->OutStreamer->endSection(Section); // Insert a final terminator. SectionMap[Section].push_back(SymbolCU(nullptr, Sym)); @@ -1668,8 +1697,8 @@ void DwarfDebug::emitDebugARanges() { // Sort the symbols by offset within the section. std::sort(List.begin(), List.end(), [&](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; + 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) @@ -1698,7 +1727,7 @@ void DwarfDebug::emitDebugARanges() { } // Start the dwarf aranges section. - Asm->OutStreamer.SwitchSection( + Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfARangesSection()); unsigned PtrSize = Asm->getDataLayout().getPointerSize(); @@ -1740,18 +1769,18 @@ void DwarfDebug::emitDebugARanges() { ContentSize += (List.size() + 1) * TupleSize; // For each compile unit, write the list of spans it covers. - Asm->OutStreamer.AddComment("Length of ARange Set"); + Asm->OutStreamer->AddComment("Length of ARange Set"); Asm->EmitInt32(ContentSize); - Asm->OutStreamer.AddComment("DWARF Arange version number"); + Asm->OutStreamer->AddComment("DWARF Arange version number"); Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); - Asm->OutStreamer.AddComment("Offset Into Debug Info Section"); - Asm->emitSectionOffset(CU->getLabelBegin()); - Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->OutStreamer->AddComment("Offset Into Debug Info Section"); + Asm->emitDwarfSymbolReference(CU->getLabelBegin()); + Asm->OutStreamer->AddComment("Address Size (in bytes)"); Asm->EmitInt8(PtrSize); - Asm->OutStreamer.AddComment("Segment Size (in bytes)"); + Asm->OutStreamer->AddComment("Segment Size (in bytes)"); Asm->EmitInt8(0); - Asm->OutStreamer.EmitFill(Padding, 0xff); + Asm->OutStreamer->EmitFill(Padding, 0xff); for (const ArangeSpan &Span : List) { Asm->EmitLabelReference(Span.Start, PtrSize); @@ -1766,20 +1795,20 @@ void DwarfDebug::emitDebugARanges() { if (Size == 0) Size = 1; - Asm->OutStreamer.EmitIntValue(Size, PtrSize); + Asm->OutStreamer->EmitIntValue(Size, PtrSize); } } - Asm->OutStreamer.AddComment("ARange terminator"); - Asm->OutStreamer.EmitIntValue(0, PtrSize); - Asm->OutStreamer.EmitIntValue(0, PtrSize); + Asm->OutStreamer->AddComment("ARange terminator"); + Asm->OutStreamer->EmitIntValue(0, PtrSize); + Asm->OutStreamer->EmitIntValue(0, PtrSize); } } // Emit visible names into a debug ranges section. void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. - Asm->OutStreamer.SwitchSection( + Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); // Size for our labels. @@ -1795,7 +1824,7 @@ void DwarfDebug::emitDebugRanges() { // Iterate over the misc ranges for the compile units in the module. for (const RangeSpanList &List : TheCU->getRangeLists()) { // Emit our symbol so we can find the beginning of the range. - Asm->OutStreamer.EmitLabel(List.getSym()); + Asm->OutStreamer->EmitLabel(List.getSym()); for (const RangeSpan &Range : List.getRanges()) { const MCSymbol *Begin = Range.getStart(); @@ -1806,24 +1835,88 @@ void DwarfDebug::emitDebugRanges() { Asm->EmitLabelDifference(Begin, Base, Size); Asm->EmitLabelDifference(End, Base, Size); } else { - Asm->OutStreamer.EmitSymbolValue(Begin, Size); - Asm->OutStreamer.EmitSymbolValue(End, Size); + Asm->OutStreamer->EmitSymbolValue(Begin, Size); + Asm->OutStreamer->EmitSymbolValue(End, Size); } } // And terminate the list with two 0 values. - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); } } } +unsigned DwarfDebug::handleMacroNodes(AsmStreamerBase *AS, + DIMacroNodeArray Nodes, + DwarfCompileUnit &U) { + unsigned Size = 0; + for (auto *MN : Nodes) { + if (auto *M = dyn_cast(MN)) + Size += emitMacro(AS, *M); + else if (auto *F = dyn_cast(MN)) + Size += emitMacroFile(AS, *F, U); + else + llvm_unreachable("Unexpected DI type!"); + } + return Size; +} + +unsigned DwarfDebug::emitMacro(AsmStreamerBase *AS, DIMacro &M) { + int Size = 0; + Size += AS->emitULEB128(M.getMacinfoType()); + Size += AS->emitULEB128(M.getLine()); + StringRef Name = M.getName(); + StringRef Value = M.getValue(); + Size += AS->emitBytes(Name); + if (!Value.empty()) { + // There should be one space between macro name and macro value. + Size += AS->emitInt8(' '); + Size += AS->emitBytes(Value); + } + Size += AS->emitInt8('\0'); + return Size; +} + +unsigned DwarfDebug::emitMacroFile(AsmStreamerBase *AS, DIMacroFile &F, + DwarfCompileUnit &U) { + int Size = 0; + assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); + Size += AS->emitULEB128(dwarf::DW_MACINFO_start_file); + Size += AS->emitULEB128(F.getLine()); + DIFile *File = F.getFile(); + unsigned FID = + U.getOrCreateSourceID(File->getFilename(), File->getDirectory()); + Size += AS->emitULEB128(FID); + Size += handleMacroNodes(AS, F.getElements(), U); + Size += AS->emitULEB128(dwarf::DW_MACINFO_end_file); + return Size; +} + +// Emit visible names into a debug macinfo section. +void DwarfDebug::emitDebugMacinfo() { + if (MCSection *Macinfo = Asm->getObjFileLowering().getDwarfMacinfoSection()) { + // Start the dwarf macinfo section. + Asm->OutStreamer->SwitchSection(Macinfo); + } + std::unique_ptr AS(new EmittingAsmStreamer(Asm)); + for (const auto &P : CUMap) { + auto &TheCU = *P.second; + auto *SkCU = TheCU.getSkeleton(); + DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; + auto *CUNode = cast(P.first); + handleMacroNodes(AS.get(), CUNode->getMacros(), 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 NewU) { NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name, - U.getCUNode().getSplitDebugFilename()); + U.getCUNode()->getSplitDebugFilename()); if (!CompilationDir.empty()) NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); @@ -1867,9 +1960,9 @@ void DwarfDebug::emitDebugAbbrevDWO() { void DwarfDebug::emitDebugLineDWO() { assert(useSplitDwarf() && "No split dwarf?"); - Asm->OutStreamer.SwitchSection( + Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfLineDWOSection()); - SplitTypeUnitFileTable.Emit(Asm->OutStreamer); + SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams()); } // Emit the .debug_str.dwo section for separated dwarf. This contains the @@ -1877,8 +1970,7 @@ void DwarfDebug::emitDebugLineDWO() { // sections. void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); - const MCSection *OffSec = - Asm->getObjFileLowering().getDwarfStrOffDWOSection(); + MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection(); InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), OffSec); } @@ -1887,11 +1979,11 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { if (!useSplitDwarf()) return nullptr; if (SingleCU) - SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode().getDirectory()); + SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode()->getDirectory()); return &SplitTypeUnitFileTable; } -static uint64_t makeTypeSignature(StringRef Identifier) { +uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) { MD5 Hash; Hash.update(Identifier); // ... take the least significant 8 bytes and return those. Our MD5 @@ -1904,7 +1996,7 @@ static uint64_t makeTypeSignature(StringRef Identifier) { void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, DIE &RefDie, - DICompositeType CTy) { + 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. @@ -1963,7 +2055,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // 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, CTy); + CU.constructTypeDIE(RefDie, cast(CTy)); return; } @@ -1982,27 +2074,23 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { if (!useDwarfAccelTables()) return; - AccelNames.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), - &Die); + AccelNames.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); } void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { if (!useDwarfAccelTables()) return; - AccelObjC.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), - &Die); + AccelObjC.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); } void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { if (!useDwarfAccelTables()) return; - AccelNamespace.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), - &Die); + AccelNamespace.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); } void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { if (!useDwarfAccelTables()) return; - AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), - &Die); + AccelTypes.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); }