diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp')
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 189 | 
1 files changed, 152 insertions, 37 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index c8cd8eb8ffd3c..32271a0ef24aa 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -28,7 +28,6 @@  #include "llvm/CodeGen/MachineInstr.h"  #include "llvm/CodeGen/MachineOperand.h"  #include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetLoweringObjectFile.h"  #include "llvm/CodeGen/TargetRegisterInfo.h"  #include "llvm/CodeGen/TargetSubtargetInfo.h"  #include "llvm/IR/DataLayout.h" @@ -40,6 +39,7 @@  #include "llvm/MC/MCSymbol.h"  #include "llvm/MC/MachineLocation.h"  #include "llvm/Support/Casting.h" +#include "llvm/Target/TargetLoweringObjectFile.h"  #include "llvm/Target/TargetMachine.h"  #include "llvm/Target/TargetOptions.h"  #include <algorithm> @@ -94,16 +94,18 @@ void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,                   DIEInteger(0));  } -unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, -                                               StringRef DirName) { +unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {    // 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. +  unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID(); +  if (!File) +    return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, None, CUID);    return Asm->OutStreamer->EmitDwarfFileDirective( -      0, DirName, FileName, -      Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID()); +      0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File), +      File->getSource(), CUID);  }  DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( @@ -190,10 +192,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(        DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);      } +    if (Expr) +      DwarfExpr->addFragmentOffset(Expr); +      if (Global) {        const MCSymbol *Sym = Asm->getSymbol(Global);        if (Global->isThreadLocal()) { -        if (Asm->TM.Options.EmulatedTLS) { +        if (Asm->TM.useEmulatedTLS()) {            // TODO: add debug info for emulated thread local mode.          } else {            // FIXME: Make this work with -gsplit-dwarf. @@ -225,10 +230,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(          addOpAddress(*Loc, Sym);        }      } -    if (Expr) { -      DwarfExpr->addFragmentOffset(Expr); -      DwarfExpr->addExpression(Expr); -    } +    // Global variables attached to symbols are memory locations. +    // It would be better if this were unconditional, but malformed input that +    // mixes non-fragments and fragments for the same variable is too expensive +    // to detect in the verifier. +    if (DwarfExpr->isUnknownLocation()) +      DwarfExpr->setMemoryLocationKind(); +    DwarfExpr->addExpression(Expr);    }    if (Loc)      addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize()); @@ -241,7 +249,8 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(      // If the linkage name is different than the name, go ahead and output      // that as well into the name table. -    if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName()) +    if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() && +        DD->useAllLinkageNames())        DD->addAccelName(GV->getLinkageName(), *VariableDIE);    } @@ -267,15 +276,20 @@ void DwarfCompileUnit::addRange(RangeSpan Range) {  void DwarfCompileUnit::initStmtList() {    // Define start line table label for each Compile Unit. -  MCSymbol *LineTableStartSym = -      Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID()); +  MCSymbol *LineTableStartSym; +  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); +  if (DD->useSectionsAsReferences()) { +    LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol(); +  } else { +    LineTableStartSym = +        Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID()); +  }    // DW_AT_stmt_list is a offset of line number information for this    // compile unit in debug_line section. For split dwarf this is    // left in the skeleton CU and so not included.    // The line table entries are not always emitted in assembly, so it    // is not okay to use line_table_start here. -  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();    StmtListValue =        addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym,                        TLOF.getDwarfLineSection()->getBeginSymbol()); @@ -313,10 +327,16 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {    // Only include DW_AT_frame_base in full debug info    if (!includeMinimalInlineScopes()) { -    const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); -    MachineLocation Location(RI->getFrameRegister(*Asm->MF)); -    if (RI->isPhysicalRegister(Location.getReg())) -      addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); +    if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) { +      DIELoc *Loc = new (DIEValueAllocator) DIELoc; +      addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa); +      addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc); +    } else { +      const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); +      MachineLocation Location(RI->getFrameRegister(*Asm->MF)); +      if (RI->isPhysicalRegister(Location.getReg())) +        addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); +    }    }    // Add name to the name table, we do this here because we're guaranteed @@ -385,21 +405,28 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,                                           SmallVector<RangeSpan, 2> Range) {    const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); -  // Emit offset in .debug_range as a relocatable label. emitDIE will handle -  // emitting it appropriately. +  // Emit the offset into .debug_ranges or .debug_rnglists as a relocatable +  // label. emitDIE() will handle emitting it appropriately.    const MCSymbol *RangeSectionSym = -      TLOF.getDwarfRangesSection()->getBeginSymbol(); +      DD->getDwarfVersion() >= 5 +          ? TLOF.getDwarfRnglistsSection()->getBeginSymbol() +          : TLOF.getDwarfRangesSection()->getBeginSymbol();    RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range));    // Under fission, ranges are specified by constant offsets relative to the    // CU's DW_AT_GNU_ranges_base. -  if (isDwoUnit()) -    addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), -                    RangeSectionSym); -  else +  // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under +  // fission until we support the forms using the .debug_addr section +  // (DW_RLE_startx_endx etc.). +  if (isDwoUnit()) { +    if (DD->getDwarfVersion() < 5) +      addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), +                      RangeSectionSym); +  } else {      addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),                      RangeSectionSym); +  }    // Add the range list to the set of ranges to be emitted.    (Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List)); @@ -407,9 +434,10 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,  void DwarfCompileUnit::attachRangesOrLowHighPC(      DIE &Die, SmallVector<RangeSpan, 2> Ranges) { -  if (Ranges.size() == 1) { -    const auto &single = Ranges.front(); -    attachLowHighPC(Die, single.getStart(), single.getEnd()); +  if (Ranges.size() == 1 || !DD->useRangesSection()) { +    const RangeSpan &Front = Ranges.front(); +    const RangeSpan &Back = Ranges.back(); +    attachLowHighPC(Die, Front.getStart(), Back.getEnd());    } else      addScopeRangeList(Die, std::move(Ranges));  } @@ -443,7 +471,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {    // Add the call site information to the DIE.    const DILocation *IA = Scope->getInlinedAt();    addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None, -          getOrCreateSourceID(IA->getFilename(), IA->getDirectory())); +          getOrCreateSourceID(IA->getFile()));    addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());    if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4)      addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None, @@ -482,6 +510,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,                                                  bool Abstract) {    // Define variable debug information entry.    auto VariableDie = DIE::get(DIEValueAllocator, DV.getTag()); +  insertDIE(DV.getVariable(), VariableDie);    if (Abstract) {      applyVariableAttributes(DV, *VariableDie); @@ -547,8 +576,11 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,      Ops.append(Expr->elements_begin(), Expr->elements_end());      DIExpressionCursor Cursor(Ops);      DwarfExpr.setMemoryLocationKind(); -    DwarfExpr.addMachineRegExpression( -        *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg); +    if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol()) +      addOpAddress(*Loc, FrameSymbol); +    else +      DwarfExpr.addMachineRegExpression( +          *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);      DwarfExpr.addExpression(std::move(Cursor));    }    addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); @@ -565,13 +597,95 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,    return Var;  } +/// Return all DIVariables that appear in count: expressions. +static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) { +  SmallVector<const DIVariable *, 2> Result; +  auto *Array = dyn_cast<DICompositeType>(Var->getType()); +  if (!Array || Array->getTag() != dwarf::DW_TAG_array_type) +    return Result; +  for (auto *El : Array->getElements()) { +    if (auto *Subrange = dyn_cast<DISubrange>(El)) { +      auto Count = Subrange->getCount(); +      if (auto *Dependency = Count.dyn_cast<DIVariable *>()) +        Result.push_back(Dependency); +    } +  } +  return Result; +} + +/// Sort local variables so that variables appearing inside of helper +/// expressions come first. +static SmallVector<DbgVariable *, 8> +sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) { +  SmallVector<DbgVariable *, 8> Result; +  SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList; +  // Map back from a DIVariable to its containing DbgVariable. +  SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar; +  // Set of DbgVariables in Result. +  SmallDenseSet<DbgVariable *, 8> Visited; +  // For cycle detection. +  SmallDenseSet<DbgVariable *, 8> Visiting; + +  // Initialize the worklist and the DIVariable lookup table. +  for (auto Var : reverse(Input)) { +    DbgVar.insert({Var->getVariable(), Var}); +    WorkList.push_back({Var, 0}); +  } + +  // Perform a stable topological sort by doing a DFS. +  while (!WorkList.empty()) { +    auto Item = WorkList.back(); +    DbgVariable *Var = Item.getPointer(); +    bool visitedAllDependencies = Item.getInt(); +    WorkList.pop_back(); + +    // Dependency is in a different lexical scope or a global. +    if (!Var) +      continue; + +    // Already handled. +    if (Visited.count(Var)) +      continue; + +    // Add to Result if all dependencies are visited. +    if (visitedAllDependencies) { +      Visited.insert(Var); +      Result.push_back(Var); +      continue; +    } + +    // Detect cycles. +    auto Res = Visiting.insert(Var); +    if (!Res.second) { +      assert(false && "dependency cycle in local variables"); +      return Result; +    } + +    // Push dependencies and this node onto the worklist, so that this node is +    // visited again after all of its dependencies are handled. +    WorkList.push_back({Var, 1}); +    for (auto *Dependency : dependencies(Var)) { +      auto Dep = dyn_cast_or_null<const DILocalVariable>(Dependency); +      WorkList.push_back({DbgVar[Dep], 0}); +    } +  } +  return Result; +} +  DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,                                                SmallVectorImpl<DIE *> &Children,                                                bool *HasNonScopeChildren) {    assert(Children.empty());    DIE *ObjectPointer = nullptr; -  for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope)) +  // Emit function arguments (order is significant). +  auto Vars = DU->getScopeVariables().lookup(Scope); +  for (auto &DV : Vars.Args) +    Children.push_back(constructVariableDIE(*DV.second, *Scope, ObjectPointer)); + +  // Emit local variables. +  auto Locals = sortLocalVars(Vars.Locals); +  for (DbgVariable *DV : Locals)      Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));    // Skip imported directives in gmlt-like data. @@ -687,9 +801,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(    else      EntityDie = getDIE(Entity);    assert(EntityDie); -  auto *File = Module->getFile(); -  addSourceLine(*IMDie, Module->getLine(), File ? File->getFilename() : "", -                File ? File->getDirectory() : ""); +  addSourceLine(*IMDie, Module->getLine(), Module->getFile());    addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);    StringRef Name = Module->getName();    if (!Name.empty()) @@ -750,7 +862,7 @@ void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var,  void DwarfCompileUnit::emitHeader(bool UseOffsets) {    // Don't bother labeling the .dwo unit, as its offset isn't used. -  if (!Skeleton) { +  if (!Skeleton && !DD->useSectionsAsReferences()) {      LabelBegin = Asm->createTempSymbol("cu_begin");      Asm->OutStreamer->EmitLabel(LabelBegin);    } @@ -759,6 +871,8 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) {                                  : DD->useSplitDwarf() ? dwarf::DW_UT_skeleton                                                        : dwarf::DW_UT_compile;    DwarfUnit::emitCommonHeader(UseOffsets, UT); +  if (DD->getDwarfVersion() >= 5 && UT != dwarf::DW_UT_compile) +    Asm->emitInt64(getDWOId());  }  bool DwarfCompileUnit::hasDwarfPubSections() const { @@ -767,7 +881,8 @@ bool DwarfCompileUnit::hasDwarfPubSections() const {    if (CUNode->getGnuPubnames())      return true; -  return DD->tuneForGDB() && !includeMinimalInlineScopes(); +  return DD->tuneForGDB() && DD->usePubSections() && +         !includeMinimalInlineScopes();  }  /// addGlobalName - Add a new global name to the compile unit.  | 
