X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=663ebef250bfab5a7269d070f80b5991e4894f05;hp=7c7f1c6ff5e288cd37ad546d7c5ae09848243f77;hb=9e0dae166f9616e6b33b1bc7d8f493cb5b5e4f1b;hpb=231537a2fafcac185b6eb506c7a178e1795900eb diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 7c7f1c6ff5e..663ebef250b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" @@ -47,6 +48,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; #define DEBUG_TYPE "dwarfdebug" @@ -149,7 +151,7 @@ DIType DbgVariable::getType() const { if (tag == dwarf::DW_TAG_pointer_type) subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom()); - DIArray Elements = DICompositeType(subType).getTypeArray(); + DIArray Elements = DICompositeType(subType).getElements(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDerivedType DT(Elements.getElement(i)); if (getName() == DT.getName()) @@ -317,7 +319,7 @@ DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU, attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym); - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); @@ -344,9 +346,7 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { // We don't create a DIE if we have a single Range and the end label // is null. - SmallVectorImpl::const_iterator RI = Ranges.begin(); - MCSymbol *End = getLabelAfterInsn(RI->second); - return !End; + return !getLabelAfterInsn(Ranges.front().second); } static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D, @@ -455,46 +455,35 @@ static std::unique_ptr constructVariableDIE(DwarfCompileUnit &TheCU, DIE *DwarfDebug::createScopeChildrenDIE( DwarfCompileUnit &TheCU, LexicalScope *Scope, - SmallVectorImpl> &Children) { + SmallVectorImpl> &Children, + unsigned *ChildScopeCount) { DIE *ObjectPointer = nullptr; - // Collect arguments for current function. - if (LScopes.isCurrentFunctionScope(Scope)) { - for (DbgVariable *ArgDV : CurrentFnArguments) - if (ArgDV) - Children.push_back( - constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer)); - - // If this is a variadic function, add an unspecified parameter. - DISubprogram SP(Scope->getScopeNode()); - DIArray FnArgs = SP.getType().getTypeArray(); - if (FnArgs.getElement(FnArgs.getNumElements() - 1) - .isUnspecifiedParameter()) { - Children.push_back( - make_unique(dwarf::DW_TAG_unspecified_parameters)); - } - } - - // Collect lexical scope children first. for (DbgVariable *DV : ScopeVariables.lookup(Scope)) Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer)); + unsigned ChildCountWithoutScopes = Children.size(); + for (LexicalScope *LS : Scope->getChildren()) - if (std::unique_ptr Nested = constructScopeDIE(TheCU, LS)) - Children.push_back(std::move(Nested)); + constructScopeDIE(TheCU, LS, Children); + + if (ChildScopeCount) + *ChildScopeCount = Children.size() - ChildCountWithoutScopes; + return ObjectPointer; } -void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, +DIE *DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, LexicalScope *Scope, DIE &ScopeDIE) { // We create children when the scope DIE is not null. SmallVector, 8> Children; - if (DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children)) - TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); + DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); // Add children for (auto &I : Children) ScopeDIE.addChild(std::move(I)); + + return ObjectPointer; } void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, @@ -533,7 +522,8 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, SPCU.applySubprogramAttributesToDefinition(SP, *AbsDef); SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); - createAndAddScopeChildren(SPCU, Scope, *AbsDef); + if (DIE *ObjectPointer = createAndAddScopeChildren(SPCU, Scope, *AbsDef)) + SPCU.addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, @@ -549,16 +539,43 @@ DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub); - createAndAddScopeChildren(TheCU, Scope, ScopeDIE); + // Collect arguments for current function. + assert(LScopes.isCurrentFunctionScope(Scope)); + DIE *ObjectPointer = nullptr; + for (DbgVariable *ArgDV : CurrentFnArguments) + if (ArgDV) + ScopeDIE.addChild( + constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer)); + + // If this is a variadic function, add an unspecified parameter. + DITypeArray FnArgs = Sub.getType().getTypeArray(); + // If we have a single element of null, it is a function that returns void. + // If we have more than one elements and the last one is null, it is a + // variadic function. + if (FnArgs.getNumElements() > 1 && + !FnArgs.getElement(FnArgs.getNumElements() - 1)) + ScopeDIE.addChild(make_unique(dwarf::DW_TAG_unspecified_parameters)); + + // Collect lexical scope children first. + // ObjectPointer might be a local (non-argument) local variable if it's a + // block's synthetic this pointer. + if (DIE *BlockObjPtr = createAndAddScopeChildren(TheCU, Scope, ScopeDIE)) { + assert(!ObjectPointer && "multiple object pointers can't be described"); + ObjectPointer = BlockObjPtr; + } + + if (ObjectPointer) + TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); return ScopeDIE; } // Construct a DIE for this scope. -std::unique_ptr DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { +void DwarfDebug::constructScopeDIE( + DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl> &FinalChildren) { if (!Scope || !Scope->getScopeNode()) - return nullptr; + return; DIScope DS(Scope->getScopeNode()); @@ -576,17 +593,19 @@ std::unique_ptr DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, if (Scope->getParent() && DS.isSubprogram()) { ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); if (!ScopeDIE) - return nullptr; + return; // We create children when the scope DIE is not null. createScopeChildrenDIE(TheCU, Scope, Children); } else { // Early exit when we know the scope DIE is going to be null. if (isLexicalScopeDIENull(Scope)) - return nullptr; + return; + + unsigned ChildScopeCount; // We create children here when we know the scope DIE is not going to be // null and the children will be added to the scope DIE. - createScopeChildrenDIE(TheCU, Scope, Children); + createScopeChildrenDIE(TheCU, Scope, Children, &ChildScopeCount); // There is no need to emit empty lexical block DIE. std::pair DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, ScopesWithImportedEntities.end(), std::pair(DS, nullptr), less_first()); - if (Children.empty() && Range.first == Range.second) - return nullptr; - ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); - assert(ScopeDIE && "Scope DIE should not be null."); for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; ++i) - constructImportedEntityDIE(TheCU, i->second, *ScopeDIE); + Children.push_back( + constructImportedEntityDIE(TheCU, DIImportedEntity(i->second))); + // If there are only other scopes as children, put them directly in the + // parent instead, as this scope would serve no purpose. + if (Children.size() == ChildScopeCount) { + FinalChildren.insert(FinalChildren.end(), + std::make_move_iterator(Children.begin()), + std::make_move_iterator(Children.end())); + return; + } + ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); + assert(ScopeDIE && "Scope DIE should not be null."); } // Add children for (auto &I : Children) ScopeDIE->addChild(std::move(I)); - return ScopeDIE; + FinalChildren.push_back(std::move(ScopeDIE)); } void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { @@ -681,27 +707,21 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { return NewCU; } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const MDNode *N) { +void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, + const MDNode *N) { DIImportedEntity Module(N); assert(Module.Verify()); if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) - constructImportedEntityDIE(TheCU, Module, *D); -} - -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const MDNode *N, DIE &Context) { - DIImportedEntity Module(N); - assert(Module.Verify()); - return constructImportedEntityDIE(TheCU, Module, Context); + D->addChild(constructImportedEntityDIE(TheCU, Module)); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity &Module, - DIE &Context) { +std::unique_ptr +DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, + const DIImportedEntity &Module) { assert(Module.Verify() && "Use one of the MDNode * overloads to handle invalid metadata"); - DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module); + std::unique_ptr IMDie = make_unique((dwarf::Tag)Module.getTag()); + TheCU.insertDIE(Module, IMDie.get()); DIE *EntityDie; DIDescriptor Entity = resolve(Module.getEntity()); if (Entity.isNameSpace()) @@ -712,13 +732,16 @@ void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity)); else EntityDie = TheCU.getDIE(Entity); - TheCU.addSourceLine(IMDie, Module.getLineNumber(), + assert(EntityDie); + TheCU.addSourceLine(*IMDie, Module.getLineNumber(), Module.getContext().getFilename(), Module.getContext().getDirectory()); - TheCU.addDIEEntry(IMDie, dwarf::DW_AT_import, *EntityDie); + TheCU.addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); StringRef Name = Module.getName(); if (!Name.empty()) - TheCU.addString(IMDie, dwarf::DW_AT_name, Name); + TheCU.addString(*IMDie, dwarf::DW_AT_name, Name); + + return IMDie; } // Emit all Dwarf sections that should come prior to the content. Create @@ -761,8 +784,13 @@ void DwarfDebug::beginModule() { for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) SPMap.insert(std::make_pair(SPs.getElement(i), &CU)); DIArray EnumTypes = CUNode.getEnumTypes(); - for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) - CU.getOrCreateTypeDIE(EnumTypes.getElement(i)); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) { + DIType Ty(EnumTypes.getElement(i)); + // The enum types array by design contains pointers to + // MDNodes rather than DIRefs. Unique them here. + DIType UniqueTy(resolve(Ty.getRef())); + CU.getOrCreateTypeDIE(UniqueTy); + } DIArray RetainedTypes = CUNode.getRetainedTypes(); for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) { DIType Ty(RetainedTypes.getElement(i)); @@ -774,7 +802,7 @@ void DwarfDebug::beginModule() { // Emit imported_modules last so that the relevant context is already // available. for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) - constructImportedEntityDIE(CU, ImportedEntities.getElement(i)); + constructAndAddImportedEntityDIE(CU, ImportedEntities.getElement(i)); } // Tell MMI that we have debug info. @@ -787,9 +815,7 @@ void DwarfDebug::beginModule() { void DwarfDebug::finishVariableDefinitions() { for (const auto &Var : ConcreteVariables) { DIE *VariableDie = Var->getDIE(); - // FIXME: There shouldn't be any variables without DIEs. - if (!VariableDie) - continue; + assert(VariableDie); // FIXME: Consider the time-space tradeoff of just storing the unit pointer // in the ConcreteVariables list, rather than looking it up again here. // DIE::getUnit isn't simple - it walks parent pointers, etc. @@ -943,10 +969,7 @@ void DwarfDebug::finalizeModuleInfo() { 0); } else { RangeSpan &Range = TheU->getRanges().back(); - U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc, - Range.getStart()); - U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(), - Range.getStart()); + attachLowHighPC(U, U.getUnitDie(), Range.getStart(), Range.getEnd()); } } } @@ -1135,13 +1158,14 @@ bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { // arguments does the function have at source level. if (ArgNo > Size) CurrentFnArguments.resize(ArgNo * 2); + assert(!CurrentFnArguments[ArgNo - 1]); CurrentFnArguments[ArgNo - 1] = Var; return true; } // Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable( - SmallPtrSet &Processed) { + SmallPtrSetImpl &Processed) { for (const auto &VI : MMI->getVariableDbgInfo()) { if (!VI.Var) continue; @@ -1186,9 +1210,121 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } +/// Determine whether two variable pieces overlap. +static bool piecesOverlap(DIVariable P1, DIVariable P2) { + if (!P1.isVariablePiece() || !P2.isVariablePiece()) + return true; + unsigned l1 = P1.getPieceOffset(); + unsigned l2 = P2.getPieceOffset(); + unsigned r1 = l1 + P1.getPieceSize(); + unsigned r2 = l2 + P2.getPieceSize(); + // True where [l1,r1[ and [r1,r2[ overlap. + return (l1 < r2) && (l2 < r1); +} + +/// Build the location list for all DBG_VALUEs in the function that +/// describe the same variable. If the ranges of several independent +/// pieces of the same variable overlap partially, split them up and +/// combine the ranges. The resulting DebugLocEntries are will have +/// strict monotonically increasing begin addresses and will never +/// overlap. +// +// Input: +// +// Ranges History [var, loc, piece ofs size] +// 0 | [x, (reg0, piece 0, 32)] +// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry +// 2 | | ... +// 3 | [clobber reg0] +// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of x. +// +// Output: +// +// [0-1] [x, (reg0, piece 0, 32)] +// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)] +// [3-4] [x, (reg1, piece 32, 32)] +// [4- ] [x, (mem, piece 0, 64)] +void +DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, + const DbgValueHistoryMap::InstrRanges &Ranges) { + SmallVector OpenRanges; + + for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { + const MachineInstr *Begin = I->first; + const MachineInstr *End = I->second; + assert(Begin->isDebugValue() && "Invalid History entry"); + + // Check if a variable is inaccessible in this range. + if (Begin->getNumOperands() > 1 && + Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) { + OpenRanges.clear(); + continue; + } + + // If this piece overlaps with any open ranges, truncate them. + DIVariable DIVar = Begin->getDebugVariable(); + auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), + [&](DebugLocEntry::Value R) { + return piecesOverlap(DIVar, R.getVariable()); + }); + OpenRanges.erase(Last, OpenRanges.end()); + + const MCSymbol *StartLabel = getLabelBeforeInsn(Begin); + assert(StartLabel && "Forgot label before DBG_VALUE starting a range!"); + + const MCSymbol *EndLabel; + if (End != nullptr) + EndLabel = getLabelAfterInsn(End); + else if (std::next(I) == Ranges.end()) + EndLabel = FunctionEndSym; + else + EndLabel = getLabelBeforeInsn(std::next(I)->first); + assert(EndLabel && "Forgot label after instruction ending a range!"); + + DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); + + auto Value = getDebugLocValue(Begin); + DebugLocEntry Loc(StartLabel, EndLabel, Value); + bool couldMerge = false; + + // If this is a piece, it may belong to the current DebugLocEntry. + if (DIVar.isVariablePiece()) { + // Add this value to the list of open ranges. + OpenRanges.push_back(Value); + + // Attempt to add the piece to the last entry. + if (!DebugLoc.empty()) + if (DebugLoc.back().MergeValues(Loc)) + couldMerge = true; + } + + if (!couldMerge) { + // Need to add a new DebugLocEntry. Add all values from still + // valid non-overlapping pieces. + if (OpenRanges.size()) + Loc.addValues(OpenRanges); + + DebugLoc.push_back(std::move(Loc)); + } + + // 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() << "Values:\n"; + for (auto Value : CurEntry->getValues()) + Value.getVariable()->dump(); + dbgs() << "-----\n"); + } +} + + // Find variables for each lexical scope. void -DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { +DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); @@ -1206,10 +1342,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { continue; LexicalScope *Scope = nullptr; - if (DV.getTag() == dwarf::DW_TAG_arg_variable && - DISubprogram(DV.getContext()).describes(CurFn->getFunction())) - Scope = LScopes.getCurrentFunctionScope(); - else if (MDNode *IA = DV.getInlinedAt()) { + if (MDNode *IA = DV.getInlinedAt()) { DebugLoc DL = DebugLoc::getFromDILocation(IA); Scope = LScopes.findInlinedScope(DebugLoc::get( DL.getLine(), DL.getCol(), DV.getContext(), IA)); @@ -1219,7 +1352,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { if (!Scope) continue; - Processed.insert(DV); + Processed.insert(getEntireVariable(DV)); const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); @@ -1236,40 +1369,12 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); DebugLocList &LocList = DotDebugLocEntries.back(); + LocList.CU = TheCU; LocList.Label = Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1); - SmallVector &DebugLoc = LocList.List; - for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { - const MachineInstr *Begin = I->first; - const MachineInstr *End = I->second; - assert(Begin->isDebugValue() && "Invalid History entry"); - - // Check if a variable is unaccessible in this range. - if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() && - !Begin->getOperand(0).getReg()) - continue; - DEBUG(dbgs() << "DotDebugLoc Pair:\n" << "\t" << *Begin); - if (End != nullptr) - DEBUG(dbgs() << "\t" << *End); - else - DEBUG(dbgs() << "\tNULL\n"); - - const MCSymbol *StartLabel = getLabelBeforeInsn(Begin); - assert(StartLabel && "Forgot label before DBG_VALUE starting a range!"); - - const MCSymbol *EndLabel; - if (End != nullptr) - EndLabel = getLabelAfterInsn(End); - else if (std::next(I) == Ranges.end()) - EndLabel = FunctionEndSym; - else - EndLabel = getLabelBeforeInsn(std::next(I)->first); - assert(EndLabel && "Forgot label after instruction ending a range!"); - - DebugLocEntry Loc(StartLabel, EndLabel, getDebugLocValue(Begin), TheCU); - if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) - DebugLoc.push_back(std::move(Loc)); - } + + // Build the location list for this variable. + buildLocationList(LocList.List, Ranges); } // Collect info for variables that were optimized out. @@ -1436,7 +1541,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // belongs to so that we add to the correct per-cu line table in the // non-asm case. LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - assert(FnScope->getScopeNode() == DI->second); + // FnScope->getScopeNode() and DI->second should represent the same function, + // though they may not be the same MDNode due to inline functions merged in + // LTO where the debug info metadata still differs (either due to distinct + // written differences - two versions of a linkonce_odr function + // written/copied into two separate files, or some sub-optimal metadata that + // isn't structurally identical (see: file path/name info from clang, which + // includes the directory of the cpp file being built, even when the file name + // is absolute (such as an <> lookup header))) DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); if (Asm->OutStreamer.hasRawTextSupport()) @@ -1451,7 +1563,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { Asm->OutStreamer.EmitLabel(FunctionBeginSym); // Calculate history for local variables. - calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues); + calculateDbgValueHistory(MF, Asm->TM.getSubtargetImpl()->getRegisterInfo(), + DbgValues); // Request labels for the full history. for (const auto &I : DbgValues) { @@ -1461,10 +1574,25 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // The first mention of a function argument gets the FunctionBeginSym // label, so arguments are visible when breaking at function entry. - DIVariable DV(I.first); + DIVariable DV(Ranges.front().first->getDebugVariable()); if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && - getDISubprogram(DV.getContext()).describes(MF->getFunction())) - LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; + getDISubprogram(DV.getContext()).describes(MF->getFunction())) { + if (!DV.isVariablePiece()) + LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; + else { + // Mark all non-overlapping initial pieces. + for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { + DIVariable Piece = I->first->getDebugVariable(); + if (std::all_of(Ranges.begin(), I, + [&](DbgValueHistoryMap::InstrRange Pred){ + return !piecesOverlap(Piece, Pred.first->getDebugVariable()); + })) + LabelsBeforeInsn[I->first] = FunctionBeginSym; + else + break; + } + } + } for (const auto &Range : Ranges) { requestLabelBeforeInsn(Range.first); @@ -1539,7 +1667,6 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // 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. - PrevSection = nullptr; PrevCU = nullptr; CurFn = nullptr; return; @@ -1562,8 +1689,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); - if (!SP.isSubprogram()) - continue; + assert(SP.isSubprogram()); // Collect info for variables that were optimized out. DIArray Variables = SP.getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { @@ -1583,7 +1709,6 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Add the range of this function to the list of ranges for the CU. RangeSpan Span(FunctionBeginSym, FunctionEndSym); TheCU.addRange(std::move(Span)); - PrevSection = Asm->getCurrentSection(); PrevCU = &TheCU; // Clear debug info @@ -1611,8 +1736,8 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, assert(Scope.isScope()); Fn = Scope.getFilename(); Dir = Scope.getDirectory(); - if (Scope.isLexicalBlock()) - Discriminator = DILexicalBlock(S).getDiscriminator(); + if (Scope.isLexicalBlockFile()) + Discriminator = DILexicalBlockFile(S).getDiscriminator(); unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); Src = static_cast(*InfoHolder.getUnits()[CUID]) @@ -1633,9 +1758,12 @@ void DwarfDebug::emitSectionLabels() { // Dwarf sections base addresses. DwarfInfoSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); - if (useSplitDwarf()) + if (useSplitDwarf()) { DwarfInfoDWOSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo"); + DwarfTypesDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo"); + } DwarfAbbrevSectionSym = emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) @@ -1945,12 +2073,66 @@ void DwarfDebug::emitDebugStr() { Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } +/// Emits an optimal (=sorted) sequence of DW_OP_pieces. +void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, + const DITypeIdentifierMap &Map, + ArrayRef Values) { + assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) { + return P.isVariablePiece(); + }) && "all values are expected to be pieces"); + assert(std::is_sorted(Values.begin(), Values.end()) && + "pieces are expected to be sorted"); + + unsigned Offset = 0; + for (auto Piece : Values) { + DIVariable Var = Piece.getVariable(); + unsigned PieceOffset = Var.getPieceOffset(); + unsigned PieceSize = Var.getPieceSize(); + assert(Offset <= PieceOffset && "overlapping or duplicate pieces"); + if (Offset < PieceOffset) { + // The DWARF spec seriously mandates pieces with no locations for gaps. + Asm->EmitDwarfOpPiece(Streamer, (PieceOffset-Offset)*8); + Offset += PieceOffset-Offset; + } + + Offset += PieceSize; + + const unsigned SizeOfByte = 8; + assert(!Var.isIndirect() && "indirect address for piece"); +#ifndef NDEBUG + unsigned VarSize = Var.getSizeInBits(Map); + assert(PieceSize+PieceOffset <= VarSize/SizeOfByte + && "piece is larger than or outside of variable"); + assert(PieceSize*SizeOfByte != VarSize + && "piece covers entire variable"); +#endif + if (Piece.isLocation() && Piece.getLoc().isReg()) + Asm->EmitDwarfRegOpPiece(Streamer, + Piece.getLoc(), + PieceSize*SizeOfByte); + else { + emitDebugLocValue(Streamer, Piece); + Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte); + } + } +} + + void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry) { - assert(Entry.getValues().size() == 1 && - "multi-value entries are not supported yet."); const DebugLocEntry::Value Value = Entry.getValues()[0]; - DIVariable DV(Value.getVariable()); + if (Value.isVariablePiece()) + // Emit all pieces that belong to the same variable and range. + return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues()); + + assert(Entry.getValues().size() == 1 && "only pieces may have >1 value"); + emitDebugLocValue(Streamer, Value); +} + +void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, + const DebugLocEntry::Value &Value) { + DIVariable DV = Value.getVariable(); + // Regular entry. if (Value.isInt()) { DIBasicType BTy(resolve(DV.getType())); if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || @@ -1997,6 +2179,9 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, } else if (Element == DIBuilder::OpDeref) { if (!Loc.isReg()) Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + } else if (Element == DIBuilder::OpPiece) { + i += 3; + // handled in emitDebugLocEntry. } else llvm_unreachable("unknown Opcode found in complex address"); } @@ -2028,11 +2213,12 @@ void DwarfDebug::emitDebugLoc() { unsigned char Size = Asm->getDataLayout().getPointerSize(); for (const auto &DebugLoc : DotDebugLocEntries) { Asm->OutStreamer.EmitLabel(DebugLoc.Label); + const DwarfCompileUnit *CU = DebugLoc.CU; + assert(!CU->getRanges().empty()); for (const auto &Entry : DebugLoc.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. - const DwarfCompileUnit *CU = Entry.getCU(); if (CU->getRanges().size() == 1) { // Grab the begin symbol from the first range as our base. const MCSymbol *Base = CU->getRanges()[0].getStart(); @@ -2309,24 +2495,6 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { return NewCU; } -// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name, -// DW_AT_addr_base. -DwarfTypeUnit &DwarfDebug::constructSkeletonTU(DwarfTypeUnit &TU) { - DwarfCompileUnit &CU = static_cast( - *SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]); - - auto OwnedUnit = make_unique(TU.getUniqueID(), CU, Asm, this, - &SkeletonHolder); - DwarfTypeUnit &NewTU = *OwnedUnit; - NewTU.setTypeSignature(TU.getTypeSignature()); - NewTU.setType(nullptr); - NewTU.initSection( - Asm->getObjFileLowering().getDwarfTypesSection(TU.getTypeSignature())); - - initSkeletonUnit(TU, NewTU.getUnitDie(), std::move(OwnedUnit)); - return NewTU; -} - // Emit the .debug_info.dwo section for separated dwarf. This contains the // compile units that would normally be in debug_info. void DwarfDebug::emitDebugInfoDWO() { @@ -2399,9 +2567,9 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, bool TopLevelType = TypeUnitsUnderConstruction.empty(); AddrPool.resetUsedFlag(); - auto OwnedUnit = - make_unique(InfoHolder.getUnits().size(), CU, Asm, this, - &InfoHolder, getDwoLineTable(CU)); + auto OwnedUnit = make_unique( + InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm, + this, &InfoHolder, getDwoLineTable(CU)); DwarfTypeUnit &NewTU = *OwnedUnit; DIE &UnitDie = NewTU.getUnitDie(); TU = &NewTU; @@ -2414,15 +2582,14 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, uint64_t Signature = makeTypeSignature(Identifier); NewTU.setTypeSignature(Signature); - if (!useSplitDwarf()) + if (useSplitDwarf()) + NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection(), + DwarfTypesDWOSectionSym); + else { CU.applyStmtList(UnitDie); - - // FIXME: Skip using COMDAT groups for type units in the .dwo file once tools - // such as DWP ( http://gcc.gnu.org/wiki/DebugFissionDWP ) can cope with it. - NewTU.initSection( - useSplitDwarf() - ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) - : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + NewTU.initSection( + Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + } NewTU.setType(NewTU.createTypeDIE(CTy)); @@ -2450,17 +2617,14 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // If the type wasn't dependent on fission addresses, finish adding the type // and all its dependent types. - for (auto &TU : TypeUnitsToAdd) { - if (useSplitDwarf()) - TU.first->setSkeleton(constructSkeletonTU(*TU.first)); + for (auto &TU : TypeUnitsToAdd) InfoHolder.addUnit(std::move(TU.first)); - } } CU.addDIETypeSignature(RefDie, NewTU); } void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, - MCSymbol *Begin, MCSymbol *End) { + const MCSymbol *Begin, const MCSymbol *End) { assert(Begin && "Begin label should not be null!"); assert(End && "End label should not be null!"); assert(Begin->isDefined() && "Invalid starting label");