X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=d50f9d6c7d0a77f0d88b07baad7b8ff9d1d4d3c0;hb=d8be72124961bf81bd74f8e277fd6dad12c00aa9;hp=a0052f605d70a2ef1805b36bf1ba763b92f3a6c1;hpb=32abfefd9b7cbbf759a5b5d61f251e9515e465bf;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index a0052f605d7..d50f9d6c7d0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -58,11 +58,6 @@ static cl::opt UnknownLocations( cl::desc("Make an absence of debug location information explicit."), cl::init(false)); -static cl::opt -GenerateODRHash("generate-odr-hash", cl::Hidden, - cl::desc("Add an ODR hash to external type DIEs."), - cl::init(false)); - static cl::opt GenerateCUHash("generate-cu-hash", cl::Hidden, cl::desc("Add the CU hash as the dwo_id."), cl::init(false)); @@ -73,11 +68,7 @@ GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden, cl::init(false)); namespace { -enum DefaultOnOff { - Default, - Enable, - Disable -}; +enum DefaultOnOff { Default, Enable, Disable }; } static cl::opt @@ -184,7 +175,8 @@ static unsigned getDwarfVersionFromModule(const Module *M) { DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), FirstCU(0), SourceIdMap(DIEValueAllocator), PrevLabel(NULL), GlobalRangeCount(0), - InfoHolder(A, "info_string", DIEValueAllocator), + InfoHolder(A, "info_string", DIEValueAllocator), HasCURanges(false), + UsedNonDefaultText(false), SkeletonHolder(A, "skel_string", DIEValueAllocator) { DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0; @@ -430,10 +422,6 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU, SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, FunctionBeginSym); SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, FunctionEndSym); - // Add this range to the list of ranges for the CU. - RangeSpan Span(FunctionBeginSym, FunctionEndSym); - SPCU->addRange(llvm_move(Span)); - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); @@ -700,12 +688,12 @@ DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU, // as well. unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, StringRef DirName, unsigned CUID) { - // If we use .loc in assembly, we can't separate .file entries according to + // If we print assembly, we can't separate .file entries according to // compile units. Thus all files will belong to the default compile unit. // FIXME: add a better feature test than hasRawTextSupport. Even better, // extend .file to support this. - if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) + if (Asm->OutStreamer.hasRawTextSupport()) CUID = 0; // If FE did not provide a file name, then assume stdin. @@ -778,10 +766,9 @@ DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym, NewCU->getUniqueID()); - // Use a single line table if we are using .loc and generating assembly. + // Use a single line table if we are generating assembly. bool UseTheFirstCU = - (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) || - (NewCU->getUniqueID() == 0); + Asm->OutStreamer.hasRawTextSupport() || (NewCU->getUniqueID() == 0); if (!useSplitDwarf()) { // DW_AT_stmt_list is a offset of line number information for this @@ -791,7 +778,7 @@ DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { // is not okay to use line_table_start here. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list, - UseTheFirstCU ? Asm->GetTempSymbol("section_line") + UseTheFirstCU ? DwarfLineSectionSym : LineTableStartSym); else if (UseTheFirstCU) NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); @@ -861,8 +848,7 @@ void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU, void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N) { DIImportedEntity Module(N); - if (!Module.Verify()) - return; + assert(Module.Verify()); if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext())) constructImportedEntityDIE(TheCU, Module, D); } @@ -870,8 +856,7 @@ void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N, DIE *Context) { DIImportedEntity Module(N); - if (!Module.Verify()) - return; + assert(Module.Verify()); return constructImportedEntityDIE(TheCU, Module, Context); } @@ -1019,41 +1004,6 @@ void DwarfDebug::collectDeadVariables() { } } -// Type Signature [7.27] and ODR Hash code. - -/// \brief Grabs the string in whichever attribute is passed in and returns -/// a reference to it. Returns "" if the attribute doesn't exist. -static StringRef getDIEStringAttr(DIE *Die, unsigned Attr) { - DIEValue *V = Die->findAttribute(Attr); - - if (DIEString *S = dyn_cast_or_null(V)) - return S->getString(); - - return StringRef(""); -} - -/// Return true if the current DIE is contained within an anonymous namespace. -static bool isContainedInAnonNamespace(DIE *Die) { - DIE *Parent = Die->getParent(); - - while (Parent) { - if (Parent->getTag() == dwarf::DW_TAG_namespace && - getDIEStringAttr(Parent, dwarf::DW_AT_name) == "") - return true; - Parent = Parent->getParent(); - } - - return false; -} - -/// Test if the current CU language is C++ and that we have -/// a named type that is not contained in an anonymous namespace. -static bool shouldAddODRHash(DwarfTypeUnit *CU, DIE *Die) { - return CU->getLanguage() == dwarf::DW_LANG_C_plus_plus && - getDIEStringAttr(Die, dwarf::DW_AT_name) != "" && - !isContainedInAnonNamespace(Die); -} - void DwarfDebug::finalizeModuleInfo() { // Collect info for variables that were optimized out. collectDeadVariables(); @@ -1090,17 +1040,24 @@ void DwarfDebug::finalizeModuleInfo() { dwarf::DW_FORM_data8, ID); } - // If we've requested ranges and have them emit a DW_AT_ranges attribute - // on the unit that will remain in the .o file, otherwise add a - // DW_AT_low_pc. + // If we have code split among multiple sections or we've requested + // it 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: Also add a high pc if we can. - // FIXME: We should use ranges if we have multiple compile units. + // FIXME: We should use ranges if we have multiple compile units or + // allow reordering of code ala .subsections_via_symbols in mach-o. DwarfCompileUnit *U = SkCU ? SkCU : static_cast(TheU); - if (DwarfCURanges && TheU->getRanges().size()) + if (useCURanges() && TheU->getRanges().size()) { addSectionLabel(Asm, U, U->getUnitDie(), dwarf::DW_AT_ranges, Asm->GetTempSymbol("cu_ranges", U->getUniqueID()), DwarfDebugRangeSectionSym); - else + + // 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->addUInt(U->getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); } @@ -1149,10 +1106,8 @@ void DwarfDebug::endSections() { if (Section) { // We can't call MCSection::getLabelEndName, as it's only safe to do so // if we know the section name up-front. For user-created sections, the - // resulting - // label may not be valid to use as a label. (section names can use a - // greater - // set of characters on some systems) + // resulting label may not be valid to use as a label. (section names can + // use a greater set of characters on some systems) Sym = Asm->GetTempSymbol("debug_end", ID); Asm->OutStreamer.SwitchSection(Section); Asm->OutStreamer.EmitLabel(Sym); @@ -1161,6 +1116,15 @@ void DwarfDebug::endSections() { // Insert a final terminator. SectionMap[Section].push_back(SymbolCU(NULL, Sym)); } + + // For now only turn on CU ranges if we've explicitly asked for it, + // we have -ffunction-sections enabled, we've emitted a function + // into a unique section, or we're using LTO. If we're using LTO then + // we can't know that any particular function in the module is correlated + // to a particular CU and so we need to be conservative. At this point all + // sections should be finalized except for dwarf sections. + HasCURanges = DwarfCURanges || UsedNonDefaultText || (CUMap.size() > 1) || + TargetMachine::getFunctionSections(); } // Emit all Dwarf sections that should come after the content. @@ -1560,30 +1524,6 @@ void DwarfDebug::identifyScopeMarkers() { } } -// Get MDNode for DebugLoc's scope. -static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) { - if (MDNode *InlinedAt = DL.getInlinedAt(Ctx)) - return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx); - return DL.getScope(Ctx); -} - -// Walk up the scope chain of given debug loc and find line number info -// for the function. -static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { - const MDNode *Scope = getScopeNode(DL, Ctx); - DISubprogram SP = getDISubprogram(Scope); - if (SP.isSubprogram()) { - // Check for number of operands since the compatibility is - // cheap here. - if (SP->getNumOperands() > 19) - return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); - else - return DebugLoc::get(SP.getLineNumber(), 0, SP); - } - - return DebugLoc(); -} - // Gather pre-function debug information. Assumes being called immediately // after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { @@ -1610,12 +1550,18 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); - if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) - // Use a single line table if we are using .loc and generating assembly. + if (Asm->OutStreamer.hasRawTextSupport()) + // Use a single line table if we are generating assembly. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); else Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); + // Check the current section against the standard text section. If different + // keep track so that we will know when we're emitting functions into multiple + // sections. + if (Asm->getObjFileLowering().getTextSection() != Asm->getCurrentSection()) + UsedNonDefaultText = true; + // Emit a label for the function so that we have a beginning address. FunctionBeginSym = Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. @@ -1772,7 +1718,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Record beginning of function. if (!PrologEndLoc.isUnknown()) { DebugLoc FnStartDL = - getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext()); + PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext()); recordSourceLine( FnStartDL.getLine(), FnStartDL.getCol(), FnStartDL.getScope(MF->getFunction()->getContext()), @@ -1833,6 +1779,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionEndSym); + // Set DwarfDwarfCompileUnitID in MCContext to default value. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); @@ -1870,10 +1817,13 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { } DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); - if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); + // Add the range of this function to the list of ranges for the CU. + RangeSpan Span(FunctionBeginSym, FunctionEndSym); + TheCU->addRange(llvm_move(Span)); + // Clear debug info for (ScopeVariablesMap::iterator I = ScopeVariables.begin(), E = ScopeVariables.end(); @@ -2857,9 +2807,8 @@ void DwarfDebug::emitDebugARanges() { unsigned TupleSize = PtrSize * 2; // 7.20 in the Dwarf specs requires the table to be aligned to a tuple. - unsigned Padding = 0; - while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0) - Padding++; + unsigned Padding = + OffsetToAlignment(sizeof(int32_t) + ContentSize, TupleSize); ContentSize += Padding; ContentSize += (List.size() + 1) * TupleSize; @@ -2876,8 +2825,7 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer.AddComment("Segment Size (in bytes)"); Asm->EmitInt8(0); - for (unsigned n = 0; n < Padding; n++) - Asm->EmitInt8(0xff); + Asm->OutStreamer.EmitFill(Padding, 0xff); for (unsigned n = 0; n < List.size(); n++) { const ArangeSpan &Span = List[n]; @@ -2913,8 +2861,9 @@ void DwarfDebug::emitDebugRanges() { unsigned char Size = Asm->getDataLayout().getPointerSize(); // Grab the specific ranges for the compile units in the module. - for (DenseMap::iterator I = CUMap.begin(), - E = CUMap.end(); + for (MapVector::iterator + I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { DwarfCompileUnit *TheCU = I->second; @@ -2950,7 +2899,7 @@ void DwarfDebug::emitDebugRanges() { } // Now emit a range for the CU itself. - if (DwarfCURanges) { + if (useCURanges()) { Asm->OutStreamer.EmitLabel( Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID())); const SmallVectorImpl &Ranges = TheCU->getRanges(); @@ -2972,6 +2921,26 @@ void DwarfDebug::emitDebugRanges() { // DWARF5 Experimental Separate Dwarf emitters. +void DwarfDebug::initSkeletonUnit(const DwarfUnit *U, DIE *Die, + DwarfUnit *NewU) { + NewU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, + U->getCUNode().getSplitDebugFilename()); + + // Relocate to the beginning of the addr_base section, else 0 for the + // beginning of the one for this compile unit. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym); + else + NewU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0); + + if (!CompilationDir.empty()) + NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + + addGnuPubAttributes(NewU, Die); + + SkeletonHolder.addUnit(NewU); +} + // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, // DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, // DW_AT_ranges_base, DW_AT_addr_base. @@ -2980,21 +2949,10 @@ DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) { DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); DwarfCompileUnit *NewCU = new DwarfCompileUnit( - CU->getUniqueID(), Die, CU->getNode(), Asm, this, &SkeletonHolder); + CU->getUniqueID(), Die, CU->getCUNode(), Asm, this, &SkeletonHolder); NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(), DwarfInfoSectionSym); - NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, - CU->getNode().getSplitDebugFilename()); - - // Relocate to the beginning of the addr_base section, else 0 for the - // beginning of the one for this compile unit. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base, - DwarfAddrSectionSym); - else - NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0); - // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. // FIXME: Should handle multiple compile units. @@ -3003,14 +2961,25 @@ DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) { else NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); - if (!CompilationDir.empty()) - NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + initSkeletonUnit(CU, Die, NewCU); - addGnuPubAttributes(NewCU, Die); + return NewCU; +} - SkeletonHolder.addUnit(NewCU); +// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name, +// DW_AT_addr_base. +DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) { - return NewCU; + DIE *Die = new DIE(dwarf::DW_TAG_type_unit); + DwarfTypeUnit *NewTU = new DwarfTypeUnit(TU->getUniqueID(), Die, TU->getCU(), + Asm, this, &SkeletonHolder); + NewTU->setTypeSignature(TU->getTypeSignature()); + NewTU->setType(NULL); + NewTU->initSection( + Asm->getObjFileLowering().getDwarfTypesSection(TU->getTypeSignature())); + + initSkeletonUnit(TU, Die, NewTU); + return NewTU; } // Emit the .debug_info.dwo section for separated dwarf. This contains the @@ -3041,40 +3010,48 @@ void DwarfDebug::emitDebugStrDWO() { OffSec, StrSym); } -void DwarfDebug::addDwarfTypeUnitType(uint16_t Language, DIE *RefDie, +void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, + StringRef Identifier, DIE *RefDie, DICompositeType CTy) { + // Flag the type unit reference as a declaration so that if it contains + // members (implicit special members, static data member definitions, member + // declarations for definitions in this CU, etc) consumers don't get confused + // and think this is a full definition. + CU.addFlag(RefDie, dwarf::DW_AT_declaration); + const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy]; - if (!TU) { - DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit); - DwarfTypeUnit *NewTU = - new DwarfTypeUnit(InfoHolder.getUnits().size(), UnitDie, Language, Asm, - this, &InfoHolder); - TU = NewTU; - InfoHolder.addUnit(NewTU); - - NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - Language); - - DIE *Die = NewTU->createTypeDIE(CTy); - - if (GenerateODRHash && shouldAddODRHash(NewTU, Die)) - NewTU->addUInt(UnitDie, dwarf::DW_AT_GNU_odr_signature, - dwarf::DW_FORM_data8, - DIEHash().computeDIEODRSignature(*Die)); - // FIXME: This won't handle circularly referential structures, as the DIE - // may have references to other DIEs still under construction and missing - // their signature. Hashing should walk through the signatures to their - // referenced type, or possibly walk the precomputed hashes of related types - // at the end. - uint64_t Signature = DIEHash().computeTypeSignature(*Die); - NewTU->setTypeSignature(Signature); - NewTU->setType(Die); - - NewTU->initSection( - useSplitDwarf() - ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) - : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); - } - - CUMap.begin()->second->addDIETypeSignature(RefDie, *TU); + if (TU) { + CU.addDIETypeSignature(RefDie, *TU); + return; + } + + DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit); + DwarfTypeUnit *NewTU = new DwarfTypeUnit(InfoHolder.getUnits().size(), + UnitDie, CU, Asm, this, &InfoHolder); + TU = NewTU; + InfoHolder.addUnit(NewTU); + + NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + CU.getLanguage()); + + MD5 Hash; + Hash.update(Identifier); + // ... take the least significant 8 bytes and return those. Our MD5 + // implementation always returns its results in little endian, swap bytes + // appropriately. + MD5::MD5Result Result; + Hash.final(Result); + uint64_t Signature = *reinterpret_cast(Result + 8); + NewTU->setTypeSignature(Signature); + if (useSplitDwarf()) + NewTU->setSkeleton(constructSkeletonTU(NewTU)); + + NewTU->setType(NewTU->createTypeDIE(CTy)); + + NewTU->initSection( + useSplitDwarf() + ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) + : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + + CU.addDIETypeSignature(RefDie, *NewTU); }