Skip to content
DwarfDebug.cpp 86.4 KiB
Newer Older
//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for writing dwarf debug info into asm files.
//
//===----------------------------------------------------------------------===//
Devang Patel's avatar
Devang Patel committed
#define DEBUG_TYPE "dwarfdebug"
#include "DwarfCompileUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/DataLayout.h"
#include "llvm/DebugInfo.h"
#include "llvm/Instructions.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
Daniel Dunbar's avatar
Daniel Dunbar committed
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print",
Devang Patel's avatar
Devang Patel committed
                                              cl::Hidden,
static cl::opt<bool> UnknownLocations("use-unknown-locations", cl::Hidden,
     cl::desc("Make an absence of debug location information explicit."),
namespace {
  enum DefaultOnOff {
    Default, Enable, Disable
  };
}
static cl::opt<DefaultOnOff> DwarfAccelTables("dwarf-accel-tables", cl::Hidden,
     cl::desc("Output prototype dwarf accelerator tables."),
     cl::values(
                clEnumVal(Default, "Default for platform"),
                clEnumVal(Enable, "Enabled"),
                clEnumVal(Disable, "Disabled"),
                clEnumValEnd),
     cl::init(Default));

static cl::opt<DefaultOnOff> DarwinGDBCompat("darwin-gdb-compat", cl::Hidden,
     cl::desc("Compatibility with Darwin gdb."),
     cl::values(
                clEnumVal(Default, "Default for platform"),
                clEnumVal(Enable, "Enabled"),
                clEnumVal(Disable, "Disabled"),
                clEnumValEnd),
     cl::init(Default));
static cl::opt<DefaultOnOff> DwarfFission("dwarf-fission", cl::Hidden,
     cl::desc("Output prototype dwarf fission."),
     cl::values(
                clEnumVal(Default, "Default for platform"),
                clEnumVal(Enable, "Enabled"),
                clEnumVal(Disable, "Disabled"),
                clEnumValEnd),
     cl::init(Default));

namespace {
  const char *DWARFGroupName = "DWARF Emission";
  const char *DbgTimerName = "DWARF Debug Writer";
} // end anonymous namespace

//===----------------------------------------------------------------------===//

// Configuration values for initial hash set sizes (log2).
//
static const unsigned InitAbbreviationsSetSize = 9; // log2(512)

namespace llvm {

  DIType Ty = Var.getType();
  // FIXME: isBlockByrefVariable should be reformulated in terms of complex
  // addresses instead.
  if (Var.isBlockByrefVariable()) {
    /* Byref variables, in Blocks, are declared by the programmer as
       "SomeType VarName;", but the compiler creates a
       __Block_byref_x_VarName struct, and gives the variable VarName
       either the struct, or a pointer to the struct, as its type.  This
       is necessary for various behind-the-scenes things the compiler
       needs to do with by-reference variables in blocks.
       However, as far as the original *programmer* is concerned, the
       variable should still have type 'SomeType', as originally declared.
       The following function dives into the __Block_byref_x_VarName
       struct to find the original type of the variable.  This will be
       passed back to the code generating the type for the Debug
       Information Entry for the variable 'VarName'.  'VarName' will then
       have the original type 'SomeType' in its debug information.
       The original type 'SomeType' will be the type of the field named
       'VarName' inside the __Block_byref_x_VarName struct.
       NOTE: In order for this to not completely fail on the debugger
       side, the Debug Information Entry for the variable VarName needs to
       have a DW_AT_location that tells the debugger how to unwind through
       the pointers and __Block_byref_x_VarName struct to find the actual
       value of the variable.  The function addBlockByrefType does this.  */
    DIType subType = Ty;
    unsigned tag = Ty.getTag();
    if (tag == dwarf::DW_TAG_pointer_type) {
      DIDerivedType DTy = DIDerivedType(Ty);
      subType = DTy.getTypeDerivedFrom();
    }
    DICompositeType blockStruct = DICompositeType(subType);
    DIArray Elements = blockStruct.getTypeArray();
    for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
      DIDescriptor Element = Elements.getElement(i);
      DIDerivedType DT = DIDerivedType(Element);
      if (getName() == DT.getName())
        return (DT.getTypeDerivedFrom());
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
  : Asm(A), MMI(Asm->MMI), FirstCU(0), FissionCU(0),
    AbbreviationsSet(InitAbbreviationsSetSize),
    SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator),
  NextStringPoolNumber = 0;
Rafael Espindola's avatar
Rafael Espindola committed
  DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
  DwarfStrSectionSym = TextSectionSym = 0;
  DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0;
  FunctionBeginSym = FunctionEndSym = 0;
  // Turn on accelerator tables and older gdb compatibility
  // for Darwin.
  bool IsDarwin = Triple(M->getTargetTriple()).isOSDarwin();
  if (DarwinGDBCompat == Default) {
    if (IsDarwin)
      IsDarwinGDBCompat = true;
    IsDarwinGDBCompat = DarwinGDBCompat == Enable ? true : false;

  if (DwarfAccelTables == Default) {
    if (IsDarwin)
      HasDwarfAccelTables = true;
    HasDwarfAccelTables = DwarfAccelTables == Enable ? true : false;
    HasDwarfFission = DwarfFission == Enable ? true : false;
  {
    NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
// Switch to the specified MCSection and emit an assembler
// temporary label to it if SymbolStem is specified.
static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section,
                                const char *SymbolStem = 0) {
  Asm->OutStreamer.SwitchSection(Section);
  if (!SymbolStem) return 0;

  MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem);
  Asm->OutStreamer.EmitLabel(TmpSym);
  return TmpSym;
}

MCSymbol *DwarfDebug::getStringPool() {
  return Asm->GetTempSymbol("section_str");
}

MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) {
  std::pair<MCSymbol*, unsigned> &Entry = StringPool[Str];
  if (Entry.first) return Entry.first;

  Entry.second = NextStringPoolNumber++;
  return Entry.first = Asm->GetTempSymbol("string", Entry.second);
// Define a unique number for the abbreviation.
//
void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) {
  // Profile the node so that we can make it unique.
  FoldingSetNodeID ID;
  Abbrev.Profile(ID);

  // Check the set for priors.
  DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);

  // If it's newly added.
  if (InSet == &Abbrev) {
    // Add to abbreviation list.
    Abbreviations.push_back(&Abbrev);

    // Assign the vector position + 1 as its number.
    Abbrev.setNumber(Abbreviations.size());
  } else {
    // Assign existing abbreviation number.
    Abbrev.setNumber(InSet->getNumber());
  }
}

// If special LLVM prefix that is used to inform the asm
// printer to not emit usual symbol prefix before the symbol name is used then
// return linkage name after skipping this special LLVM prefix.
static StringRef getRealLinkageName(StringRef LinkageName) {
  char One = '\1';
  if (LinkageName.startswith(StringRef(&One, 1)))
    return LinkageName.substr(1);
  return LinkageName;
}

static bool isObjCClass(StringRef Name) {
  return Name.startswith("+") || Name.startswith("-");
}

static bool hasObjCCategory(StringRef Name) {
  if (!isObjCClass(Name)) return false;

  size_t pos = Name.find(')');
  if (pos != std::string::npos) {
    if (Name[pos+1] != ' ') return false;
    return true;
  }
  return false;
}

static void getObjCClassCategory(StringRef In, StringRef &Class,
                                 StringRef &Category) {
  if (!hasObjCCategory(In)) {
    Class = In.slice(In.find('[') + 1, In.find(' '));
    Category = "";
    return;
  }

  Class = In.slice(In.find('[') + 1, In.find('('));
  Category = In.slice(In.find('[') + 1, In.find(' '));
  return;
}

static StringRef getObjCMethodName(StringRef In) {
  return In.slice(In.find(' ') + 1, In.find(']'));
}

// Add the various names to the Dwarf accelerator table names.
static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP,
                               DIE* Die) {
  if (!SP.isDefinition()) return;
  TheCU->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())
    TheCU->addAccelName(SP.getLinkageName(), Die);

  // If this is an Objective-C selector name add it to the ObjC accelerator
  // too.
  if (isObjCClass(SP.getName())) {
    StringRef Class, Category;
    getObjCClassCategory(SP.getName(), Class, Category);
    TheCU->addAccelObjC(Class, Die);
    if (Category != "")
      TheCU->addAccelObjC(Category, Die);
    // Also add the base method name to the name table.
    TheCU->addAccelName(getObjCMethodName(SP.getName()), Die);
  }
}

// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
// and DW_AT_high_pc attributes. If there are global variables in this
// scope then create and insert DIEs for these variables.
DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
                                          const MDNode *SPNode) {
  DIE *SPDie = SPCU->getDIE(SPNode);
  assert(SPDie && "Unable to find subprogram DIE!");
  DISubprogram SP(SPNode);
  // If we're updating an abstract DIE, then we will be adding the children and
  // object pointer later on. But what we don't want to do is process the
  // concrete DIE twice.
  if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
    // Pick up abstract subprogram DIE.
    SPDie = new DIE(dwarf::DW_TAG_subprogram);
    SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
                      dwarf::DW_FORM_ref4, AbsSPDIE);
  } else {
    DISubprogram SPDecl = SP.getFunctionDeclaration();
    if (!SPDecl.isSubprogram()) {
      // There is not any need to generate specification DIE for a function
      // defined at compile unit level. If a function is defined inside another
      // function then gdb prefers the definition at top level and but does not
      // expect specification DIE in parent function. So avoid creating
      // specification DIE for a function defined inside a function.
      if (SP.isDefinition() && !SP.getContext().isCompileUnit() &&
          !SP.getContext().isFile() &&
          !isSubprogramContext(SP.getContext())) {
        SPCU->addFlag(SPDie, dwarf::DW_AT_declaration);

        // Add arguments.
        DICompositeType SPTy = SP.getType();
        DIArray Args = SPTy.getTypeArray();
        unsigned SPTag = SPTy.getTag();
        if (SPTag == dwarf::DW_TAG_subroutine_type)
          for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
            DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
            DIType ATy = DIType(Args.getElement(i));
            SPCU->addType(Arg, ATy);
            if (ATy.isArtificial())
              SPCU->addFlag(Arg, dwarf::DW_AT_artificial);
            if (ATy.isObjectPointer())
              SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer,
                                dwarf::DW_FORM_ref4, Arg);
            SPDie->addChild(Arg);
          }
        DIE *SPDeclDie = SPDie;
        SPDie = new DIE(dwarf::DW_TAG_subprogram);
Eric Christopher's avatar
Eric Christopher committed
        SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification,
                          dwarf::DW_FORM_ref4, SPDeclDie);
  SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
                 Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()));
  SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
                 Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()));
  const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
  MachineLocation Location(RI->getFrameRegister(*Asm->MF));
  SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
  // Add name to the name table, we do this here because we're guaranteed
  // to have concrete versions of our DW_TAG_subprogram nodes.
  addSubprogramNames(SPCU, SP, SPDie);
// Construct new DW_TAG_lexical_block for this scope and attach
// DW_AT_low_pc/DW_AT_high_pc labels.
Eric Christopher's avatar
Eric Christopher committed
DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
  DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
  if (Scope->isAbstractScope())
    return ScopeDIE;

  const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
  SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
  if (Ranges.size() > 1) {
    // .debug_range section has not been laid out yet. Emit offset in
    // .debug_range as a uint, size 4, for now. emitDIE will handle
    TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
Eric Christopher's avatar
Eric Christopher committed
                   DebugRangeSymbols.size()
                   * Asm->getDataLayout().getPointerSize());
    for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
      DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
      DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
    }
    DebugRangeSymbols.push_back(NULL);
    DebugRangeSymbols.push_back(NULL);
    return ScopeDIE;
  }

  const MCSymbol *Start = getLabelBeforeInsn(RI->first);
  const MCSymbol *End = getLabelAfterInsn(RI->second);
  if (End == 0) return 0;

  assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
  assert(End->isDefined() && "Invalid end label for an inlined scope!");
  TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start);
  TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End);
// This scope represents inlined body of a function. Construct DIE to
// represent this concrete inlined copy of the function.
DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
                                          LexicalScope *Scope) {
  const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
  assert(Ranges.empty() == false &&
         "LexicalScope does not have instruction markers!");
  if (!Scope->getScopeNode())
    return NULL;
  DIScope DS(Scope->getScopeNode());
  DISubprogram InlinedSP = getDISubprogram(DS);
  DIE *OriginDIE = TheCU->getDIE(InlinedSP);
  if (!OriginDIE) {
Bill Wendling's avatar
Bill Wendling committed
    DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
  SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
  const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
  const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
  if (StartLabel == 0 || EndLabel == 0) {
Bill Wendling's avatar
Bill Wendling committed
    llvm_unreachable("Unexpected Start and End labels for an inlined scope!");
  assert(StartLabel->isDefined() &&
         "Invalid starting label for an inlined scope!");
         "Invalid end label for an inlined scope!");
  DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
  TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
                     dwarf::DW_FORM_ref4, OriginDIE);
  if (Ranges.size() > 1) {
    // .debug_range section has not been laid out yet. Emit offset in
    // .debug_range as a uint, size 4, for now. emitDIE will handle
    // DW_AT_ranges appropriately.
    TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
Eric Christopher's avatar
Eric Christopher committed
                   DebugRangeSymbols.size()
                   * Asm->getDataLayout().getPointerSize());
    for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
         RE = Ranges.end(); RI != RE; ++RI) {
      DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
      DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
    }
    DebugRangeSymbols.push_back(NULL);
    DebugRangeSymbols.push_back(NULL);
  } else {
Eric Christopher's avatar
Eric Christopher committed
    TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
Devang Patel's avatar
Devang Patel committed
                    StartLabel);
Eric Christopher's avatar
Eric Christopher committed
    TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
Devang Patel's avatar
Devang Patel committed
                    EndLabel);

  InlinedSubprogramDIEs.insert(OriginDIE);

  // Track the start label for this inlined function.
  //.debug_inlined section specification does not clearly state how
  // to emit inlined scope that is split into multiple instruction ranges.
  // For now, use first instruction range and emit low_pc/high_pc pair and
  // corresponding .debug_inlined section entry for this pair.
  DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
    I = InlineInfo.find(InlinedSP);

  if (I == InlineInfo.end()) {
    InlineInfo[InlinedSP].push_back(std::make_pair(StartLabel, ScopeDIE));
    InlinedSPNodes.push_back(InlinedSP);
    I->second.push_back(std::make_pair(StartLabel, ScopeDIE));

  DILocation DL(Scope->getInlinedAt());
  TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0,
                 getOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
  TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
  // Add name to the name table, we do this here because we're guaranteed
  // to have concrete versions of our DW_TAG_inlined_subprogram nodes.
  addSubprogramNames(TheCU, InlinedSP, ScopeDIE);
// Construct a DIE for this scope.
DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
  if (!Scope || !Scope->getScopeNode())
    return NULL;
Eric Christopher's avatar
Eric Christopher committed
  DIE *ObjectPointer = NULL;
  if (LScopes.isCurrentFunctionScope(Scope))
    for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
      if (DbgVariable *ArgDV = CurrentFnArguments[i])
Eric Christopher's avatar
Eric Christopher committed
        if (DIE *Arg =
Eric Christopher's avatar
Eric Christopher committed
            TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope())) {
Eric Christopher's avatar
Eric Christopher committed
          if (ArgDV->isObjectPointer()) ObjectPointer = Arg;
        }
Eric Christopher's avatar
Eric Christopher committed
  // Collect lexical scope children first.
  const SmallVector<DbgVariable *, 8> &Variables = ScopeVariables.lookup(Scope);
  for (unsigned i = 0, N = Variables.size(); i < N; ++i)
Eric Christopher's avatar
Eric Christopher committed
    if (DIE *Variable =
        TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) {
      if (Variables[i]->isObjectPointer()) ObjectPointer = Variable;
    }
  const SmallVector<LexicalScope *, 4> &Scopes = Scope->getChildren();
  for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
    if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j]))
  DIScope DS(Scope->getScopeNode());
  DIE *ScopeDIE = NULL;
  if (Scope->getInlinedAt())
    ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
  else if (DS.isSubprogram()) {
    ProcessedSPNodes.insert(DS);
      // Note down abstract DIE.
      if (ScopeDIE)
        AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
    }
      ScopeDIE = updateSubprogramScopeDIE(TheCU, DS);
  else {
    // There is no need to emit empty lexical block DIE.
    if (Children.empty())
      return NULL;
    ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
  // Add children
  for (SmallVector<DIE *, 8>::iterator I = Children.begin(),
         E = Children.end(); I != E; ++I)
    ScopeDIE->addChild(*I);
Devang Patel's avatar
Devang Patel committed

Eric Christopher's avatar
Eric Christopher committed
  if (DS.isSubprogram() && ObjectPointer != NULL)
    TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer,
                       dwarf::DW_FORM_ref4, ObjectPointer);

  if (DS.isSubprogram())
    TheCU->addPubTypes(DISubprogram(DS));
// Look up the source id with the given directory and source file names.
// If none currently exists, create a new id and insert it in the
// SourceIds map. This can update DirectoryNames and SourceFileNames maps
// as well.
unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName,
  // If FE did not provide a file name, then assume stdin.
  if (FileName.empty())
    return getOrCreateSourceID("<stdin>", StringRef());
  // TODO: this might not belong here. See if we can factor this better.
  if (DirName == CompilationDir)
    DirName = "";

  unsigned SrcId = SourceIdMap.size()+1;

  // We look up the file/dir pair by concatenating them with a zero byte.
  SmallString<128> NamePair;
  NamePair += DirName;
  NamePair += '\0'; // Zero bytes are not allowed in paths.
  NamePair += FileName;

  StringMapEntry<unsigned> &Ent = SourceIdMap.GetOrCreateValue(NamePair, SrcId);
  if (Ent.getValue() != SrcId)
    return Ent.getValue();
  // Print out a .file directive to specify files for .loc directives.
  Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName);
// Create new CompileUnit for the given metadata node with tag DW_TAG_compile_unit.
CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
Devang Patel's avatar
Devang Patel committed
  DICompileUnit DIUnit(N);
  StringRef FN = DIUnit.getFilename();
  CompilationDir = DIUnit.getDirectory();
  unsigned ID = getOrCreateSourceID(FN, CompilationDir);
  DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
Eric Christopher's avatar
Eric Christopher committed
  CompileUnit *NewCU = new CompileUnit(ID, DIUnit.getLanguage(), Die,
                                       Asm, this);
  NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
  NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
                 DIUnit.getLanguage());
  NewCU->addString(Die, dwarf::DW_AT_name, FN);
  // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
  // into an entity.
  NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
  // DW_AT_stmt_list is a offset of line number information for this
  // compile unit in debug_line section.
  if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
    NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
    NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
  if (!CompilationDir.empty())
    NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
  if (DIUnit.isOptimized())
    NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized);
  StringRef Flags = DIUnit.getFlags();
  if (!Flags.empty())
    NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
  if (unsigned RVer = DIUnit.getRunTimeVersion())
    NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
            dwarf::DW_FORM_data1, RVer);
  if (!FirstCU)
    FirstCU = NewCU;
  if (useDwarfFission() && !FissionCU)
    FissionCU = constructFissionCU(N);

  CUMap.insert(std::make_pair(N, NewCU));
// Construct subprogram DIE.
Eric Christopher's avatar
Eric Christopher committed
void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU,
Devang Patel's avatar
Devang Patel committed
  DISubprogram SP(N);
  if (!SP.isDefinition())
    // This is a method declaration which will be handled while constructing
    // class type.
Devang Patel's avatar
 
Devang Patel committed
    return;
  DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP);
  TheCU->insertDIE(N, SubprogramDie);
  // Add to context owner.
  TheCU->addToContextOwner(SubprogramDie, SP.getContext());
Devang Patel's avatar
 
Devang Patel committed
  return;
// Collect debug info from named mdnodes such as llvm.dbg.enum and llvm.dbg.ty.
void DwarfDebug::collectInfoFromNamedMDNodes(const Module *M) {
  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"))
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
      const MDNode *N = NMD->getOperand(i);
      if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
        constructSubprogramDIE(CU, N);
    }
  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"))
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
      const MDNode *N = NMD->getOperand(i);
      if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
        CU->createGlobalVariableDIE(N);
Devang Patel's avatar
Devang Patel committed
  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum"))
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
      DIType Ty(NMD->getOperand(i));
      if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
        CU->getOrCreateTypeDIE(Ty);
Devang Patel's avatar
Devang Patel committed
    }
Devang Patel's avatar
Devang Patel committed
  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty"))
    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
      DIType Ty(NMD->getOperand(i));
      if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
        CU->getOrCreateTypeDIE(Ty);
Devang Patel's avatar
Devang Patel committed
    }
}

// Collect debug info using DebugInfoFinder.
// FIXME - Remove this when dragonegg switches to DIBuilder.
bool DwarfDebug::collectLegacyDebugInfo(const Module *M) {
Devang Patel's avatar
Devang Patel committed
  DebugInfoFinder DbgFinder;
  DbgFinder.processModule(*M);
Devang Patel's avatar
Devang Patel committed
  bool HasDebugInfo = false;
  // Scan all the compile-units to see if there are any marked as the main
  // unit. If not, we do not generate debug info.
  for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
         E = DbgFinder.compile_unit_end(); I != E; ++I) {
    if (DICompileUnit(*I).isMain()) {
      HasDebugInfo = true;
      break;
    }
  }
  if (!HasDebugInfo) return false;
Devang Patel's avatar
Devang Patel committed
  // Create all the compile unit DIEs.
  for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
         E = DbgFinder.compile_unit_end(); I != E; ++I)
    constructCompileUnit(*I);
Devang Patel's avatar
Devang Patel committed
  // Create DIEs for each global variable.
  for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
         E = DbgFinder.global_variable_end(); I != E; ++I) {
    const MDNode *N = *I;
    if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
      CU->createGlobalVariableDIE(N);
Devang Patel's avatar
Devang Patel committed
  }
Devang Patel's avatar
Devang Patel committed
  // Create DIEs for each subprogram.
  for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
         E = DbgFinder.subprogram_end(); I != E; ++I) {
    const MDNode *N = *I;
    if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
      constructSubprogramDIE(CU, N);
Devang Patel's avatar
Devang Patel committed
  }

  return HasDebugInfo;
}

// Emit all Dwarf sections that should come prior to the content. Create
// global DIEs and emit initial debug info sections. This is invoked by
// the target AsmPrinter.
  // If module has named metadata anchors then use them, otherwise scan the
  // module using debug info finder to collect debug info.
  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
  if (CU_Nodes) {
    for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
      DICompileUnit CUNode(CU_Nodes->getOperand(i));
      CompileUnit *CU = constructCompileUnit(CUNode);
      DIArray GVs = CUNode.getGlobalVariables();
      for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
        CU->createGlobalVariableDIE(GVs.getElement(i));
      DIArray SPs = CUNode.getSubprograms();
      for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
        constructSubprogramDIE(CU, SPs.getElement(i));
      DIArray EnumTypes = CUNode.getEnumTypes();
      for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
        CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
      DIArray RetainedTypes = CUNode.getRetainedTypes();
      for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
        CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
    }
Devang Patel's avatar
Devang Patel committed
  } else if (!collectLegacyDebugInfo(M))
    return;
Devang Patel's avatar
Devang Patel committed
  collectInfoFromNamedMDNodes(M);
  // Tell MMI that we have debug info.
  MMI->setDebugInfoAvailability(true);
  // Prime section data.
  SectionMap.insert(Asm->getObjFileLowering().getTextSection());
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
void DwarfDebug::computeInlinedDIEs() {
  // Attach DW_AT_inline attribute with inlined subprogram DIEs.
  for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
Eric Christopher's avatar
Eric Christopher committed
         AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
    DIE *ISP = *AI;
    FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
  }
  for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(),
Eric Christopher's avatar
Eric Christopher committed
         AE = AbstractSPDies.end(); AI != AE; ++AI) {
    DIE *ISP = AI->second;
    if (InlinedSubprogramDIEs.count(ISP))
      continue;
    FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
  }
}
// Collect info for variables that were optimized out.
void DwarfDebug::collectDeadVariables() {
  const Module *M = MMI->getModule();
  DenseMap<const MDNode *, LexicalScope *> DeadFnScopeMap;
  if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
    for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
      DICompileUnit TheCU(CU_Nodes->getOperand(i));
      DIArray Subprograms = TheCU.getSubprograms();
      for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) {
Eric Christopher's avatar
Eric Christopher committed
        DISubprogram SP(Subprograms.getElement(i));
        if (ProcessedSPNodes.count(SP) != 0) continue;
        if (!SP.Verify()) continue;
        if (!SP.isDefinition()) continue;
        DIArray Variables = SP.getVariables();
        if (Variables.getNumElements() == 0) continue;

        LexicalScope *Scope =
          new LexicalScope(NULL, DIDescriptor(SP), NULL, false);
        DeadFnScopeMap[SP] = Scope;

        // Construct subprogram DIE and add variables DIEs.
        CompileUnit *SPCU = CUMap.lookup(TheCU);
        assert(SPCU && "Unable to find Compile Unit!");
        constructSubprogramDIE(SPCU, SP);
        DIE *ScopeDIE = SPCU->getDIE(SP);
        for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
          DIVariable DV(Variables.getElement(vi));
          if (!DV.Verify()) continue;
          DbgVariable *NewVar = new DbgVariable(DV, NULL);
          if (DIE *VariableDIE =
              SPCU->constructVariableDIE(NewVar, Scope->isAbstractScope()))
            ScopeDIE->addChild(VariableDIE);
        }
  DeleteContainerSeconds(DeadFnScopeMap);
}

void DwarfDebug::finalizeModuleInfo() {
  // Collect info for variables that were optimized out.
  collectDeadVariables();
  // Attach DW_AT_inline attribute with inlined subprogram DIEs.
  // Emit DW_AT_containing_type attribute to connect types with their
  // vtable holding type.
  for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
Eric Christopher's avatar
Eric Christopher committed
         CUE = CUMap.end(); CUI != CUE; ++CUI) {
    CompileUnit *TheCU = CUI->second;
    TheCU->constructContainingTypeDIEs();
   // Compute DIE offsets and sizes.
  computeSizeAndOffsets();
}

void DwarfDebug::endSections() {
  // Standard sections final addresses.
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end"));
  Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end"));
  // End text sections.
  for (unsigned I = 0, E = SectionMap.size(); I != E; ++I) {
    Asm->OutStreamer.SwitchSection(SectionMap[I]);
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", I+1));
// Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {

  if (!FirstCU) return;

  // End any existing sections.
  // TODO: Does this need to happen?
  endSections();

  // Finalize the debug info for the module.
  finalizeModuleInfo();
  if (!useDwarfFission()) {
    // Emit all the DIEs into a debug info section.
    emitDebugInfo();
    // Corresponding abbreviations into a abbrev section.
    emitAbbreviations();

    // Emit info into a debug loc section.
    emitDebugLoc();

    // Emit info into a debug aranges section.
    emitDebugARanges();

    // Emit info into a debug ranges section.
    emitDebugRanges();

    // Emit info into a debug macinfo section.
    emitDebugMacInfo();

    // Emit inline info.
    // TODO: When we don't need the option anymore we
    // can remove all of the code that this section
    // depends upon.
    if (useDarwinGDBCompat())
      emitDebugInlineInfo();
  } else {
    // TODO: Fill this in for Fission sections and separate
    // out information into new sections.

    // Emit the debug info section and compile units.

    // Corresponding abbreviations into a abbrev section.
    emitAbbreviations();

    // Emit info into a debug loc section.
    emitDebugLoc();

    // Emit info into a debug aranges section.
    emitDebugARanges();

    // Emit info into a debug ranges section.
    emitDebugRanges();

    // Emit info into a debug macinfo section.
    emitDebugMacInfo();

    // Emit inline info.
    // TODO: When we don't need the option anymore we
    // can remove all of the code that this section
    // depends upon.
    if (useDarwinGDBCompat())
      emitDebugInlineInfo();
  }
Eric Christopher's avatar
Eric Christopher committed
  // Emit info into the dwarf accelerator table sections.
    emitAccelNames();
    emitAccelObjC();
    emitAccelNamespaces();
    emitAccelTypes();
  }
Devang Patel's avatar
Devang Patel committed
  // Emit info into a debug pubtypes section.
  // TODO: When we don't need the option anymore we can
  // remove all of the code that adds to the table.
Devang Patel's avatar
Devang Patel committed

  // Finally emit string information into a string table.
  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
         E = CUMap.end(); I != E; ++I)
    delete I->second;
  // Reset these for the next Module if we have one.
  FirstCU = NULL;
  FissionCU = NULL;
// Find abstract variable, if any, associated with Var.
Devang Patel's avatar
 
Devang Patel committed
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
Devang Patel's avatar
 
Devang Patel committed
  LLVMContext &Ctx = DV->getContext();
  // More then one inlined variable corresponds to one abstract variable.
  DIVariable Var = cleanseInlinedVariable(DV, Ctx);
  DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
  LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx));