diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 665 | 
1 files changed, 461 insertions, 204 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 2c9c7d4f31460..8761fae9dd225 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -16,7 +16,6 @@  #include "DIEHash.h"  #include "DebugLocEntry.h"  #include "DebugLocStream.h" -#include "DwarfAccelTable.h"  #include "DwarfCompileUnit.h"  #include "DwarfExpression.h"  #include "DwarfFile.h" @@ -31,6 +30,7 @@  #include "llvm/ADT/Triple.h"  #include "llvm/ADT/Twine.h"  #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/AccelTable.h"  #include "llvm/CodeGen/AsmPrinter.h"  #include "llvm/CodeGen/DIE.h"  #include "llvm/CodeGen/LexicalScopes.h" @@ -39,7 +39,6 @@  #include "llvm/CodeGen/MachineInstr.h"  #include "llvm/CodeGen/MachineModuleInfo.h"  #include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetLoweringObjectFile.h"  #include "llvm/CodeGen/TargetRegisterInfo.h"  #include "llvm/CodeGen/TargetSubtargetInfo.h"  #include "llvm/IR/Constants.h" @@ -66,6 +65,7 @@  #include "llvm/Support/MathExtras.h"  #include "llvm/Support/Timer.h"  #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLoweringObjectFile.h"  #include "llvm/Target/TargetMachine.h"  #include "llvm/Target/TargetOptions.h"  #include <algorithm> @@ -94,6 +94,11 @@ static cl::opt<bool> GenerateARangeSection("generate-arange-section",                                             cl::desc("Generate dwarf aranges"),                                             cl::init(false)); +static cl::opt<bool> +    GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, +                           cl::desc("Generate DWARF4 type units."), +                           cl::init(false)); +  static cl::opt<bool> SplitDwarfCrossCuReferences(      "split-dwarf-cross-cu-references", cl::Hidden,      cl::desc("Enable cross-cu references in DWO files"), cl::init(false)); @@ -107,14 +112,40 @@ static cl::opt<DefaultOnOff> UnknownLocations(                 clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")),      cl::init(Default)); +static cl::opt<AccelTableKind> AccelTables( +    "accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."), +    cl::values(clEnumValN(AccelTableKind::Default, "Default", +                          "Default for platform"), +               clEnumValN(AccelTableKind::None, "Disable", "Disabled."), +               clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), +               clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")), +    cl::init(AccelTableKind::Default)); +  static cl::opt<DefaultOnOff> -DwarfAccelTables("dwarf-accel-tables", cl::Hidden, -                 cl::desc("Output prototype dwarf accelerator tables."), +DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, +                 cl::desc("Use inlined strings rather than string section."),                   cl::values(clEnumVal(Default, "Default for platform"),                              clEnumVal(Enable, "Enabled"),                              clEnumVal(Disable, "Disabled")),                   cl::init(Default)); +static cl::opt<bool> +    NoDwarfPubSections("no-dwarf-pub-sections", cl::Hidden, +                       cl::desc("Disable emission of DWARF pub sections."), +                       cl::init(false)); + +static cl::opt<bool> +    NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden, +                         cl::desc("Disable emission .debug_ranges section."), +                         cl::init(false)); + +static cl::opt<DefaultOnOff> DwarfSectionsAsReferences( +    "dwarf-sections-as-references", cl::Hidden, +    cl::desc("Use sections+offset as references rather than labels."), +    cl::values(clEnumVal(Default, "Default for platform"), +               clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), +    cl::init(Default)); +  enum LinkageNameOption {    DefaultLinkageNames,    AllLinkageNames, @@ -215,11 +246,11 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {                          return A.Expr->isFragment();                        }) &&           "multiple FI expressions without DW_OP_LLVM_fragment"); -  std::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(), -            [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool { -              return A.Expr->getFragmentInfo()->OffsetInBits < -                     B.Expr->getFragmentInfo()->OffsetInBits; -            }); +  llvm::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(), +             [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool { +               return A.Expr->getFragmentInfo()->OffsetInBits < +                      B.Expr->getFragmentInfo()->OffsetInBits; +             });    return FrameIndexExprs;  } @@ -258,23 +289,34 @@ void DbgVariable::addMMIEntry(const DbgVariable &V) {           "conflicting locations for variable");  } -static const DwarfAccelTable::Atom TypeAtoms[] = { -    DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), -    DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), -    DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; +static AccelTableKind computeAccelTableKind(unsigned DwarfVersion, +                                            bool GenerateTypeUnits, +                                            DebuggerKind Tuning, +                                            const Triple &TT) { +  // Honor an explicit request. +  if (AccelTables != AccelTableKind::Default) +    return AccelTables; + +  // Accelerator tables with type units are currently not supported. +  if (GenerateTypeUnits) +    return AccelTableKind::None; + +  // Accelerator tables get emitted if targetting DWARF v5 or LLDB.  DWARF v5 +  // always implies debug_names. For lower standard versions we use apple +  // accelerator tables on apple platforms and debug_names elsewhere. +  if (DwarfVersion >= 5) +    return AccelTableKind::Dwarf; +  if (Tuning == DebuggerKind::LLDB) +    return TT.isOSBinFormatMachO() ? AccelTableKind::Apple +                                   : AccelTableKind::Dwarf; +  return AccelTableKind::None; +}  DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)      : DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()),        InfoHolder(A, "info_string", DIEValueAllocator),        SkeletonHolder(A, "skel_string", DIEValueAllocator), -      IsDarwin(A->TM.getTargetTriple().isOSDarwin()), -      AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, -                                       dwarf::DW_FORM_data4)), -      AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, -                                      dwarf::DW_FORM_data4)), -      AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, -                                           dwarf::DW_FORM_data4)), -      AccelTypes(TypeAtoms) { +      IsDarwin(A->TM.getTargetTriple().isOSDarwin()) {    const Triple &TT = Asm->TM.getTargetTriple();    // Make sure we know our "debugger tuning."  The target option takes @@ -288,11 +330,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)    else      DebuggerTuning = DebuggerKind::GDB; -  // Turn on accelerator tables for LLDB by default. -  if (DwarfAccelTables == Default) -    HasDwarfAccelTables = tuneForLLDB(); +  if (DwarfInlinedStrings == Default) +    UseInlineStrings = TT.isNVPTX();    else -    HasDwarfAccelTables = DwarfAccelTables == Enable; +    UseInlineStrings = DwarfInlinedStrings == Enable; + +  UseLocSection = !TT.isNVPTX();    HasAppleExtensionAttributes = tuneForLLDB(); @@ -308,8 +351,23 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)    unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion;    unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber                                      : MMI->getModule()->getDwarfVersion(); -  // Use dwarf 4 by default if nothing is requested. -  DwarfVersion = DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION; +  // Use dwarf 4 by default if nothing is requested. For NVPTX, use dwarf 2. +  DwarfVersion = +      TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION); + +  UsePubSections = !NoDwarfPubSections && !TT.isNVPTX(); +  UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX(); + +  // Use sections as references. Force for NVPTX. +  if (DwarfSectionsAsReferences == Default) +    UseSectionsAsReferences = TT.isNVPTX(); +  else +    UseSectionsAsReferences = DwarfSectionsAsReferences == Enable; + +  GenerateTypeUnits = GenerateDwarfTypeUnits; + +  TheAccelTableKind = computeAccelTableKind( +      DwarfVersion, GenerateTypeUnits, DebuggerTuning, A->TM.getTargetTriple());    // Work around a GDB bug. GDB doesn't support the standard opcode;    // SCE doesn't support GNU's; LLDB prefers the standard opcode, which @@ -321,6 +379,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)    // GDB does not fully support the DWARF 4 representation for bitfields.    UseDWARF2Bitfields = (DwarfVersion < 4) || tuneForGDB(); +  // The DWARF v5 string offsets table has - possibly shared - contributions +  // from each compile and type unit each preceded by a header. The string +  // offsets table used by the pre-DWARF v5 split-DWARF implementation uses +  // a monolithic string offsets table without any header. +  UseSegmentedStringOffsetsTable = DwarfVersion >= 5; +    Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);  } @@ -355,17 +419,18 @@ static StringRef getObjCMethodName(StringRef In) {  }  // Add the various names to the Dwarf accelerator table names. -// TODO: Determine whether or not we should add names for programs -// that do not have a DW_AT_name or DW_AT_linkage_name field - this -// is only slightly different than the lookup of non-standard ObjC names.  void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) {    if (!SP->isDefinition())      return; -  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()) +  if (SP->getName() != "") +    addAccelName(SP->getName(), Die); + +  // If the linkage name is different than the name, go ahead and output that as +  // well into the name table. Only do that if we are going to actually emit +  // that name. +  if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() && +      (useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP)))      addAccelName(SP->getLinkageName(), Die);    // If this is an Objective-C selector name add it to the ObjC accelerator @@ -471,8 +536,9 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {    // explicitly describe the directory of all files, never relying on the    // compilation directory.    if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) -    Asm->OutStreamer->getContext().setMCLineTableCompilationDir( -        NewCU.getUniqueID(), CompilationDir); +    Asm->OutStreamer->emitDwarfFile0Directive( +        CompilationDir, FN, NewCU.getMD5AsBytes(DIUnit->getFile()), +        DIUnit->getSource(), NewCU.getUniqueID());    StringRef Producer = DIUnit->getProducer();    StringRef Flags = DIUnit->getFlags(); @@ -486,6 +552,10 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {                  DIUnit->getSourceLanguage());    NewCU.addString(Die, dwarf::DW_AT_name, FN); +  // Add DW_str_offsets_base to the unit DIE, except for split units. +  if (useSegmentedStringOffsetsTable() && !useSplitDwarf()) +    NewCU.addStringOffsetsStart(); +    if (!useSplitDwarf()) {      NewCU.initStmtList(); @@ -541,21 +611,22 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,  /// Sort and unique GVEs by comparing their fragment offset.  static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &  sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) { -  std::sort(GVEs.begin(), GVEs.end(), -            [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { -              // Sort order: first null exprs, then exprs without fragment -              // info, then sort by fragment offset in bits. -              // FIXME: Come up with a more comprehensive comparator so -              // the sorting isn't non-deterministic, and so the following -              // std::unique call works correctly. -              if (!A.Expr || !B.Expr) -                return !!B.Expr; -              auto FragmentA = A.Expr->getFragmentInfo(); -              auto FragmentB = B.Expr->getFragmentInfo(); -              if (!FragmentA || !FragmentB) -                return !!FragmentB; -              return FragmentA->OffsetInBits < FragmentB->OffsetInBits; -            }); +  llvm::sort(GVEs.begin(), GVEs.end(), +             [](DwarfCompileUnit::GlobalExpr A, +                DwarfCompileUnit::GlobalExpr B) { +               // Sort order: first null exprs, then exprs without fragment +               // info, then sort by fragment offset in bits. +               // FIXME: Come up with a more comprehensive comparator so +               // the sorting isn't non-deterministic, and so the following +               // std::unique call works correctly. +               if (!A.Expr || !B.Expr) +                 return !!B.Expr; +               auto FragmentA = A.Expr->getFragmentInfo(); +               auto FragmentB = B.Expr->getFragmentInfo(); +               if (!FragmentA || !FragmentB) +                 return !!FragmentB; +               return FragmentA->OffsetInBits < FragmentB->OffsetInBits; +             });    GVEs.erase(std::unique(GVEs.begin(), GVEs.end(),                           [](DwarfCompileUnit::GlobalExpr A,                              DwarfCompileUnit::GlobalExpr B) { @@ -590,6 +661,19 @@ void DwarfDebug::beginModule() {        GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()});    } +  // Create the symbol that designates the start of the unit's contribution +  // to the string offsets table. In a split DWARF scenario, only the skeleton +  // unit has the DW_AT_str_offsets_base attribute (and hence needs the symbol). +  if (useSegmentedStringOffsetsTable()) +    (useSplitDwarf() ? SkeletonHolder : InfoHolder) +        .setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base")); + +  // Create the symbol that designates the start of the DWARF v5 range list +  // table. It is located past the header and before the offsets table. +  if (getDwarfVersion() >= 5) +    (useSplitDwarf() ? SkeletonHolder : InfoHolder) +        .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base")); +    for (DICompileUnit *CUNode : M->debug_compile_units()) {      // FIXME: Move local imported entities into a list attached to the      // subprogram, then this search won't be needed and a @@ -694,11 +778,15 @@ void DwarfDebug::finalizeModuleInfo() {        // Emit a unique identifier for this CU.        uint64_t ID =            DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie()); -      TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id, -                    dwarf::DW_FORM_data8, ID); -      SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, -                    dwarf::DW_FORM_data8, ID); - +      if (getDwarfVersion() >= 5) { +        TheCU.setDWOId(ID); +        SkCU->setDWOId(ID); +      } else { +        TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id, +                      dwarf::DW_FORM_data8, ID); +        SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, +                      dwarf::DW_FORM_data8, ID); +      }        // We don't keep track of which addresses are used in which CU so this        // is a bit pessimistic under LTO.        if (!AddrPool.isEmpty()) { @@ -706,7 +794,7 @@ void DwarfDebug::finalizeModuleInfo() {          SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base,                                Sym, Sym);        } -      if (!SkCU->getRangeLists().empty()) { +      if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) {          const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol();          SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,                                Sym, Sym); @@ -721,7 +809,7 @@ void DwarfDebug::finalizeModuleInfo() {      // ranges for all subprogram DIEs for mach-o.      DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;      if (unsigned NumRanges = TheCU.getRanges().size()) { -      if (NumRanges > 1) +      if (NumRanges > 1 && useRangesSection())          // 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 @@ -732,6 +820,10 @@ void DwarfDebug::finalizeModuleInfo() {        U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());      } +    if (getDwarfVersion() >= 5 && !useSplitDwarf() && +        !U.getRangeLists().empty()) +      U.addRnglistsBase(); +      auto *CUNode = cast<DICompileUnit>(P.first);      // If compile Unit has macros, emit "DW_AT_macro_info" attribute.      if (CUNode->getMacros()) @@ -799,11 +891,20 @@ void DwarfDebug::endModule() {    }    // Emit info into the dwarf accelerator table sections. -  if (useDwarfAccelTables()) { +  switch (getAccelTableKind()) { +  case AccelTableKind::Apple:      emitAccelNames();      emitAccelObjC();      emitAccelNamespaces();      emitAccelTypes(); +    break; +  case AccelTableKind::Dwarf: +    emitAccelDebugNames(); +    break; +  case AccelTableKind::None: +    break; +  case AccelTableKind::Default: +    llvm_unreachable("Default should have already been resolved.");    }    // Emit the pubnames and pubtypes sections if requested. @@ -887,7 +988,7 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {    llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");  } -/// \brief If this and Next are describing different fragments of the same +/// If this and Next are describing different fragments of the same  /// variable, merge them by appending Next's values to the current  /// list of values.  /// Return true if the merge was successful. @@ -903,8 +1004,7 @@ bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) {      // sorted.      for (unsigned i = 0, j = 0; i < Values.size(); ++i) {        for (; j < Next.Values.size(); ++j) { -        int res = DebugHandlerBase::fragmentCmp( -            cast<DIExpression>(Values[i].Expression), +        int res = cast<DIExpression>(Values[i].Expression)->fragmentCmp(              cast<DIExpression>(Next.Values[j].Expression));          if (res == 0) // The two expressions overlap, we can't merge.            return false; @@ -967,7 +1067,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,      // If this fragment overlaps with any open ranges, truncate them.      const DIExpression *DIExpr = Begin->getDebugExpression();      auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) { -      return fragmentsOverlap(DIExpr, R.getExpression()); +      return DIExpr->fragmentsOverlap(R.getExpression());      });      OpenRanges.erase(Last, OpenRanges.end()); @@ -983,7 +1083,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,        EndLabel = getLabelBeforeInsn(std::next(I)->first);      assert(EndLabel && "Forgot label after instruction ending a range!"); -    DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); +    LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");      auto Value = getDebugLocValue(Begin);      DebugLocEntry Loc(StartLabel, EndLabel, Value); @@ -1012,7 +1112,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,      // Attempt to coalesce the ranges of two otherwise identical      // DebugLocEntries.      auto CurEntry = DebugLoc.rbegin(); -    DEBUG({ +    LLVM_DEBUG({        dbgs() << CurEntry->getValues().size() << " Values:\n";        for (auto &Value : CurEntry->getValues())          Value.dump(); @@ -1131,6 +1231,9 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,        RegVar->initializeDbgValue(MInsn);        continue;      } +    // Do not emit location lists if .debug_loc secton is disabled. +    if (!useLocSection()) +      continue;      // Handle multiple DBG_VALUE instructions describing one variable.      DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn); @@ -1151,10 +1254,12 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,    }    // Collect info for variables that were optimized out. -  for (const DILocalVariable *DV : SP->getVariables()) { -    if (Processed.insert(InlinedVariable(DV, nullptr)).second) -      if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) -        createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr)); +  for (const DINode *DN : SP->getRetainedNodes()) { +    if (auto *DV = dyn_cast<DILocalVariable>(DN)) { +      if (Processed.insert(InlinedVariable(DV, nullptr)).second) +        if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) +          createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr)); +    }    }  } @@ -1168,7 +1273,9 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {      return;    // Check if source location changes, but ignore DBG_VALUE and CFI locations. -  if (MI->isMetaInstruction()) +  // If the instruction is part of the function frame setup code, do not emit +  // any line record, as there is no correspondence with any user code. +  if (MI->isMetaInstruction() || MI->getFlag(MachineInstr::FrameSetup))      return;    const DebugLoc &DL = MI->getDebugLoc();    // When we emit a line-0 record, we don't update PrevInstLoc; so look at @@ -1333,14 +1440,16 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {    // Construct abstract scopes.    for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {      auto *SP = cast<DISubprogram>(AScope->getScopeNode()); -    // Collect info for variables that were optimized out. -    for (const DILocalVariable *DV : SP->getVariables()) { -      if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) -        continue; -      ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr), -                                      DV->getScope()); -      assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes -             && "ensureAbstractVariableIsCreated inserted abstract scopes"); +    for (const DINode *DN : SP->getRetainedNodes()) { +      if (auto *DV = dyn_cast<DILocalVariable>(DN)) { +        // Collect info for variables that were optimized out. +        if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) +          continue; +        ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr), +                                        DV->getScope()); +        assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes +               && "ensureAbstractVariableIsCreated inserted abstract scopes"); +      }      }      constructAbstractSubprogramScopeDIE(TheCU, AScope);    } @@ -1366,21 +1475,19 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {  void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,                                    unsigned Flags) {    StringRef Fn; -  StringRef Dir; -  unsigned Src = 1; +  unsigned FileNo = 1;    unsigned Discriminator = 0;    if (auto *Scope = cast_or_null<DIScope>(S)) {      Fn = Scope->getFilename(); -    Dir = Scope->getDirectory();      if (Line != 0 && getDwarfVersion() >= 4)        if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))          Discriminator = LBF->getDiscriminator();      unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID(); -    Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID]) -              .getOrCreateSourceID(Fn, Dir); +    FileNo = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID]) +              .getOrCreateSourceID(Scope->getFile());    } -  Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0, +  Asm->OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0,                                            Discriminator, Fn);  } @@ -1401,13 +1508,30 @@ void DwarfDebug::emitAbbreviations() {    Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());  } -void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section, +void DwarfDebug::emitStringOffsetsTableHeader() { +  DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; +  Holder.getStringPool().emitStringOffsetsTableHeader( +      *Asm, Asm->getObjFileLowering().getDwarfStrOffSection(), +      Holder.getStringOffsetsStartSym()); +} + +template <typename AccelTableT> +void DwarfDebug::emitAccel(AccelTableT &Accel, MCSection *Section,                             StringRef TableName) { -  Accel.FinalizeTable(Asm, TableName);    Asm->OutStreamer->SwitchSection(Section);    // Emit the full data. -  Accel.emit(Asm, Section->getBeginSymbol(), this); +  emitAppleAccelTable(Asm, Accel, TableName, Section->getBeginSymbol()); +} + +void DwarfDebug::emitAccelDebugNames() { +  // Don't emit anything if we have no compilation units to index. +  if (getUnits().empty()) +    return; + +  Asm->OutStreamer->SwitchSection( +      Asm->getObjFileLowering().getDwarfDebugNamesSection()); +  emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits());  }  // Emit visible names into a hashed accelerator table section. @@ -1525,6 +1649,14 @@ void DwarfDebug::emitDebugPubSections() {    }  } +void DwarfDebug::emitSectionReference(const DwarfCompileUnit &CU) { +  if (useSectionsAsReferences()) +    Asm->EmitDwarfOffset(CU.getSection()->getBeginSymbol(), +                         CU.getDebugSectionOffset()); +  else +    Asm->emitDwarfSymbolReference(CU.getLabelBegin()); +} +  void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,                                       DwarfCompileUnit *TheU,                                       const StringMap<const DIE *> &Globals) { @@ -1540,13 +1672,13 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,    Asm->OutStreamer->EmitLabel(BeginLabel);    Asm->OutStreamer->AddComment("DWARF Version"); -  Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); +  Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION);    Asm->OutStreamer->AddComment("Offset of Compilation Unit Info"); -  Asm->emitDwarfSymbolReference(TheU->getLabelBegin()); +  emitSectionReference(*TheU);    Asm->OutStreamer->AddComment("Compilation Unit Length"); -  Asm->EmitInt32(TheU->getLength()); +  Asm->emitInt32(TheU->getLength());    // Emit the pubnames for this compilation unit.    for (const auto &GI : Globals) { @@ -1554,14 +1686,14 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,      const DIE *Entity = GI.second;      Asm->OutStreamer->AddComment("DIE offset"); -    Asm->EmitInt32(Entity->getOffset()); +    Asm->emitInt32(Entity->getOffset());      if (GnuStyle) {        dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);        Asm->OutStreamer->AddComment(            Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +            dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); -      Asm->EmitInt8(Desc.toBits()); +      Asm->emitInt8(Desc.toBits());      }      Asm->OutStreamer->AddComment("External Name"); @@ -1569,14 +1701,20 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,    }    Asm->OutStreamer->AddComment("End Mark"); -  Asm->EmitInt32(0); +  Asm->emitInt32(0);    Asm->OutStreamer->EmitLabel(EndLabel);  }  /// Emit null-terminated strings into a debug str section.  void DwarfDebug::emitDebugStr() { +  MCSection *StringOffsetsSection = nullptr; +  if (useSegmentedStringOffsetsTable()) { +    emitStringOffsetsTableHeader(); +    StringOffsetsSection = Asm->getObjFileLowering().getDwarfStrOffSection(); +  }    DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; -  Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); +  Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection(), +                     StringOffsetsSection, /* UseRelativeOffsets = */ true);  }  void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, @@ -1589,7 +1727,6 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,  }  static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, -                              ByteStreamer &Streamer,                                const DebugLocEntry::Value &Value,                                DwarfExpression &DwarfExpr) {    auto *DIExpr = Value.getExpression(); @@ -1634,11 +1771,11 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,             "fragments are expected to be sorted");      for (auto Fragment : Values) -      emitDebugLocValue(AP, BT, Streamer, Fragment, DwarfExpr); +      emitDebugLocValue(AP, BT, Fragment, DwarfExpr);    } else {      assert(Values.size() == 1 && "only fragments may have >1 value"); -    emitDebugLocValue(AP, BT, Streamer, Value, DwarfExpr); +    emitDebugLocValue(AP, BT, Value, DwarfExpr);    }    DwarfExpr.finalize();  } @@ -1646,7 +1783,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,  void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {    // Emit the size.    Asm->OutStreamer->AddComment("Loc expr size"); -  Asm->EmitInt16(DebugLocs.getBytes(Entry).size()); +  Asm->emitInt16(DebugLocs.getBytes(Entry).size());    // Emit the entry.    APByteStreamer Streamer(*Asm); @@ -1694,14 +1831,14 @@ void DwarfDebug::emitDebugLocDWO() {        // rather than two. We could get fancier and try to, say, reuse an        // address we know we've emitted elsewhere (the start of the function?        // The start of the CU or CU subrange that encloses this range?) -      Asm->EmitInt8(dwarf::DW_LLE_startx_length); +      Asm->emitInt8(dwarf::DW_LLE_startx_length);        unsigned idx = AddrPool.getIndex(Entry.BeginSym);        Asm->EmitULEB128(idx);        Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4);        emitDebugLocEntryLocation(Entry);      } -    Asm->EmitInt8(dwarf::DW_LLE_end_of_list); +    Asm->emitInt8(dwarf::DW_LLE_end_of_list);    }  } @@ -1752,7 +1889,7 @@ void DwarfDebug::emitDebugARanges() {      }      // Sort the symbols by offset within the section. -    std::sort( +    std::stable_sort(          List.begin(), List.end(), [&](const SymbolCU &A, const SymbolCU &B) {            unsigned IA = A.Sym ? Asm->OutStreamer->GetSymbolOrder(A.Sym) : 0;            unsigned IB = B.Sym ? Asm->OutStreamer->GetSymbolOrder(B.Sym) : 0; @@ -1801,10 +1938,10 @@ void DwarfDebug::emitDebugARanges() {    }    // Sort the CU list (again, to ensure consistent output order). -  std::sort(CUs.begin(), CUs.end(), -            [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { -              return A->getUniqueID() < B->getUniqueID(); -            }); +  llvm::sort(CUs.begin(), CUs.end(), +             [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { +               return A->getUniqueID() < B->getUniqueID(); +             });    // Emit an arange table for each CU we used.    for (DwarfCompileUnit *CU : CUs) { @@ -1832,15 +1969,15 @@ void DwarfDebug::emitDebugARanges() {      // For each compile unit, write the list of spans it covers.      Asm->OutStreamer->AddComment("Length of ARange Set"); -    Asm->EmitInt32(ContentSize); +    Asm->emitInt32(ContentSize);      Asm->OutStreamer->AddComment("DWARF Arange version number"); -    Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); +    Asm->emitInt16(dwarf::DW_ARANGES_VERSION);      Asm->OutStreamer->AddComment("Offset Into Debug Info Section"); -    Asm->emitDwarfSymbolReference(CU->getLabelBegin()); +    emitSectionReference(*CU);      Asm->OutStreamer->AddComment("Address Size (in bytes)"); -    Asm->EmitInt8(PtrSize); +    Asm->emitInt8(PtrSize);      Asm->OutStreamer->AddComment("Segment Size (in bytes)"); -    Asm->EmitInt8(0); +    Asm->emitInt8(0);      Asm->OutStreamer->emitFill(Padding, 0xff); @@ -1867,17 +2004,151 @@ void DwarfDebug::emitDebugARanges() {    }  } -/// Emit address ranges into a debug ranges section. +/// Emit a single range list. We handle both DWARF v5 and earlier. +static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, +                          const RangeSpanList &List) { + +  auto DwarfVersion = CU->getDwarfVersion(); +  // Emit our symbol so we can find the beginning of the range. +  Asm->OutStreamer->EmitLabel(List.getSym()); +  // Gather all the ranges that apply to the same section so they can share +  // a base address entry. +  MapVector<const MCSection *, std::vector<const RangeSpan *>> SectionRanges; +  // Size for our labels. +  auto Size = Asm->MAI->getCodePointerSize(); + +  for (const RangeSpan &Range : List.getRanges()) +    SectionRanges[&Range.getStart()->getSection()].push_back(&Range); + +  auto *CUBase = CU->getBaseAddress(); +  bool BaseIsSet = false; +  for (const auto &P : SectionRanges) { +    // Don't bother with a base address entry if there's only one range in +    // this section in this range list - for example ranges for a CU will +    // usually consist of single regions from each of many sections +    // (-ffunction-sections, or just C++ inline functions) except under LTO +    // or optnone where there may be holes in a single CU's section +    // contributions. +    auto *Base = CUBase; +    if (!Base && P.second.size() > 1 && +        (UseDwarfRangesBaseAddressSpecifier || DwarfVersion >= 5)) { +      BaseIsSet = true; +      // FIXME/use care: This may not be a useful base address if it's not +      // the lowest address/range in this object. +      Base = P.second.front()->getStart(); +      if (DwarfVersion >= 5) { +        Asm->OutStreamer->AddComment("DW_RLE_base_address"); +        Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1); +      } else +        Asm->OutStreamer->EmitIntValue(-1, Size); +      Asm->OutStreamer->AddComment("  base address"); +      Asm->OutStreamer->EmitSymbolValue(Base, Size); +    } else if (BaseIsSet && DwarfVersion < 5) { +      BaseIsSet = false; +      assert(!Base); +      Asm->OutStreamer->EmitIntValue(-1, Size); +      Asm->OutStreamer->EmitIntValue(0, Size); +    } + +    for (const auto *RS : P.second) { +      const MCSymbol *Begin = RS->getStart(); +      const MCSymbol *End = RS->getEnd(); +      assert(Begin && "Range without a begin symbol?"); +      assert(End && "Range without an end symbol?"); +      if (Base) { +        if (DwarfVersion >= 5) { +          // Emit DW_RLE_offset_pair when we have a base. +          Asm->OutStreamer->AddComment("DW_RLE_offset_pair"); +          Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_offset_pair, 1); +          Asm->OutStreamer->AddComment("  starting offset"); +          Asm->EmitLabelDifferenceAsULEB128(Begin, Base); +          Asm->OutStreamer->AddComment("  ending offset"); +          Asm->EmitLabelDifferenceAsULEB128(End, Base); +        } else { +          Asm->EmitLabelDifference(Begin, Base, Size); +          Asm->EmitLabelDifference(End, Base, Size); +        } +      } else if (DwarfVersion >= 5) { +        Asm->OutStreamer->AddComment("DW_RLE_start_length"); +        Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1); +        Asm->OutStreamer->AddComment("  start"); +        Asm->OutStreamer->EmitSymbolValue(Begin, Size); +        Asm->OutStreamer->AddComment("  length"); +        Asm->EmitLabelDifferenceAsULEB128(End, Begin); +      } else { +        Asm->OutStreamer->EmitSymbolValue(Begin, Size); +        Asm->OutStreamer->EmitSymbolValue(End, Size); +      } +    } +  } +  if (DwarfVersion >= 5) { +    Asm->OutStreamer->AddComment("DW_RLE_end_of_list"); +    Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_end_of_list, 1); +  } else { +    // Terminate the list with two 0 values. +    Asm->OutStreamer->EmitIntValue(0, Size); +    Asm->OutStreamer->EmitIntValue(0, Size); +  } +} + +// Emit the header of a DWARF 5 range list table. Returns the symbol that +// designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, DwarfFile &Holder) { +  // The length is described by a starting label right after the length field +  // and an end label. +  MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); +  MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); +  // Build the range table header, which starts with the length field. +  Asm->EmitLabelDifference(TableEnd, TableStart, 4); +  Asm->OutStreamer->EmitLabel(TableStart); +  // Version number (DWARF v5 and later). +  Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); +  // Address size. +  Asm->emitInt8(Asm->MAI->getCodePointerSize()); +  // Segment selector size. +  Asm->emitInt8(0); + +  MCSymbol *RnglistTableBaseSym = Holder.getRnglistsTableBaseSym(); + +  // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the +  // DW_AT_ranges attribute. Until then set the number of offsets to 0. +  Asm->emitInt32(0); +  Asm->OutStreamer->EmitLabel(RnglistTableBaseSym); +  return TableEnd; +} + +/// Emit address ranges into the .debug_ranges section or into the DWARF v5 +/// .debug_rnglists section.  void DwarfDebug::emitDebugRanges() {    if (CUMap.empty())      return; -  // Start the dwarf ranges section. -  Asm->OutStreamer->SwitchSection( -      Asm->getObjFileLowering().getDwarfRangesSection()); +  auto NoRangesPresent = [this]() { +    return llvm::all_of( +        CUMap, [](const decltype(CUMap)::const_iterator::value_type &Pair) { +          return Pair.second->getRangeLists().empty(); +        }); +  }; -  // Size for our labels. -  unsigned char Size = Asm->MAI->getCodePointerSize(); +  if (!useRangesSection()) { +    assert(NoRangesPresent() && "No debug ranges expected."); +    return; +  } + +  if (getDwarfVersion() >= 5 && NoRangesPresent()) +    return; + +  // Start the dwarf ranges section. +  MCSymbol *TableEnd = nullptr; +  if (getDwarfVersion() >= 5) { +    Asm->OutStreamer->SwitchSection( +        Asm->getObjFileLowering().getDwarfRnglistsSection()); +    TableEnd = emitRnglistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder +                                                            : InfoHolder); +  } else +    Asm->OutStreamer->SwitchSection( +        Asm->getObjFileLowering().getDwarfRangesSection());    // Grab the specific ranges for the compile units in the module.    for (const auto &I : CUMap) { @@ -1887,61 +2158,12 @@ void DwarfDebug::emitDebugRanges() {        TheCU = Skel;      // Iterate over the misc ranges for the compile units in the module. -    for (const RangeSpanList &List : TheCU->getRangeLists()) { -      // Emit our symbol so we can find the beginning of the range. -      Asm->OutStreamer->EmitLabel(List.getSym()); - -      // Gather all the ranges that apply to the same section so they can share -      // a base address entry. -      MapVector<const MCSection *, std::vector<const RangeSpan *>> MV; -      for (const RangeSpan &Range : List.getRanges()) { -        MV[&Range.getStart()->getSection()].push_back(&Range); -      } - -      auto *CUBase = TheCU->getBaseAddress(); -      bool BaseIsSet = false; -      for (const auto &P : MV) { -        // Don't bother with a base address entry if there's only one range in -        // this section in this range list - for example ranges for a CU will -        // usually consist of single regions from each of many sections -        // (-ffunction-sections, or just C++ inline functions) except under LTO -        // or optnone where there may be holes in a single CU's section -        // contrubutions. -        auto *Base = CUBase; -        if (!Base && P.second.size() > 1 && -            UseDwarfRangesBaseAddressSpecifier) { -          BaseIsSet = true; -          // FIXME/use care: This may not be a useful base address if it's not -          // the lowest address/range in this object. -          Base = P.second.front()->getStart(); -          Asm->OutStreamer->EmitIntValue(-1, Size); -          Asm->OutStreamer->EmitSymbolValue(Base, Size); -        } else if (BaseIsSet) { -          BaseIsSet = false; -          Asm->OutStreamer->EmitIntValue(-1, Size); -          Asm->OutStreamer->EmitIntValue(0, Size); -        } - -        for (const auto *RS : P.second) { -          const MCSymbol *Begin = RS->getStart(); -          const MCSymbol *End = RS->getEnd(); -          assert(Begin && "Range without a begin symbol?"); -          assert(End && "Range without an end symbol?"); -          if (Base) { -            Asm->EmitLabelDifference(Begin, Base, Size); -            Asm->EmitLabelDifference(End, Base, Size); -          } else { -            Asm->OutStreamer->EmitSymbolValue(Begin, Size); -            Asm->OutStreamer->EmitSymbolValue(End, Size); -          } -        } -      } - -      // And terminate the list with two 0 values. -      Asm->OutStreamer->EmitIntValue(0, Size); -      Asm->OutStreamer->EmitIntValue(0, Size); -    } +    for (const RangeSpanList &List : TheCU->getRangeLists()) +      emitRangeList(Asm, TheCU, List);    } + +  if (TableEnd) +    Asm->OutStreamer->EmitLabel(TableEnd);  }  void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { @@ -1963,20 +2185,17 @@ void DwarfDebug::emitMacro(DIMacro &M) {    Asm->OutStreamer->EmitBytes(Name);    if (!Value.empty()) {      // There should be one space between macro name and macro value. -    Asm->EmitInt8(' '); +    Asm->emitInt8(' ');      Asm->OutStreamer->EmitBytes(Value);    } -  Asm->EmitInt8('\0'); +  Asm->emitInt8('\0');  }  void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) {    assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file);    Asm->EmitULEB128(dwarf::DW_MACINFO_start_file);    Asm->EmitULEB128(F.getLine()); -  DIFile *File = F.getFile(); -  unsigned FID = -      U.getOrCreateSourceID(File->getFilename(), File->getDirectory()); -  Asm->EmitULEB128(FID); +  Asm->EmitULEB128(U.getOrCreateSourceID(F.getFile()));    handleMacroNodes(F.getElements(), U);    Asm->EmitULEB128(dwarf::DW_MACINFO_end_file);  } @@ -1995,11 +2214,14 @@ void DwarfDebug::emitDebugMacinfo() {      auto *SkCU = TheCU.getSkeleton();      DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;      auto *CUNode = cast<DICompileUnit>(P.first); -    Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); -    handleMacroNodes(CUNode->getMacros(), U); +    DIMacroNodeArray Macros = CUNode->getMacros(); +    if (!Macros.empty()) { +      Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); +      handleMacroNodes(Macros, U); +    }    }    Asm->OutStreamer->AddComment("End Of Macro List Mark"); -  Asm->EmitInt8(0); +  Asm->emitInt8(0);  }  // DWARF5 Experimental Separate Dwarf emitters. @@ -2017,9 +2239,6 @@ void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,    SkeletonHolder.addUnit(std::move(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_addr_base, DW_AT_ranges_base.  DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {    auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( @@ -2029,6 +2248,9 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {    NewCU.initStmtList(); +  if (useSegmentedStringOffsetsTable()) +    NewCU.addStringOffsetsStart(); +    initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));    return NewCU; @@ -2051,26 +2273,37 @@ void DwarfDebug::emitDebugAbbrevDWO() {  void DwarfDebug::emitDebugLineDWO() {    assert(useSplitDwarf() && "No split dwarf?"); -  Asm->OutStreamer->SwitchSection( +  SplitTypeUnitFileTable.Emit( +      *Asm->OutStreamer, MCDwarfLineTableParams(),        Asm->getObjFileLowering().getDwarfLineDWOSection()); -  SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams()); +} + +void DwarfDebug::emitStringOffsetsTableHeaderDWO() { +  assert(useSplitDwarf() && "No split dwarf?"); +  InfoHolder.getStringPool().emitStringOffsetsTableHeader( +      *Asm, Asm->getObjFileLowering().getDwarfStrOffDWOSection(), +      InfoHolder.getStringOffsetsStartSym());  }  // Emit the .debug_str.dwo section for separated dwarf. This contains the  // string section and is identical in format to traditional .debug_str  // sections.  void DwarfDebug::emitDebugStrDWO() { +  if (useSegmentedStringOffsetsTable()) +    emitStringOffsetsTableHeaderDWO();    assert(useSplitDwarf() && "No split dwarf?");    MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection();    InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), -                         OffSec); +                         OffSec, /* UseRelativeOffsets = */ false);  }  MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {    if (!useSplitDwarf())      return nullptr; -  if (SingleCU) -    SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode()->getDirectory()); +  const DICompileUnit *DIUnit = CU.getCUNode(); +  SplitTypeUnitFileTable.maybeSetRootFile( +      DIUnit->getDirectory(), DIUnit->getFilename(), +      CU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource());    return &SplitTypeUnitFileTable;  } @@ -2119,10 +2352,16 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,    if (useSplitDwarf())      NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());    else { -    CU.applyStmtList(UnitDie);      NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature)); +    // Non-split type units reuse the compile unit's line table. +    CU.applyStmtList(UnitDie);    } +  // Add DW_AT_str_offsets_base to the type unit DIE, but not for split type +  // units. +  if (useSegmentedStringOffsetsTable() && !useSplitDwarf()) +    NewTU.addStringOffsetsStart(); +    NewTU.setType(NewTU.createTypeDIE(CTy));    if (TopLevelType) { @@ -2157,32 +2396,50 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,    CU.addDIETypeSignature(RefDie, Signature);  } -// Accelerator table mutators - add each name along with its companion -// DIE to the proper table while ensuring that the name that we're going -// to reference is in the string table. We do this since the names we -// add may not only be identical to the names in the DIE. -void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { -  if (!useDwarfAccelTables()) +// Add the Name along with its companion DIE to the appropriate accelerator +// table (for AccelTableKind::Dwarf it's always AccelDebugNames, for +// AccelTableKind::Apple, we use the table we got as an argument). If +// accelerator tables are disabled, this function does nothing. +template <typename DataT> +void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name, +                                  const DIE &Die) { +  if (getAccelTableKind() == AccelTableKind::None)      return; -  AccelNames.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); + +  DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; +  DwarfStringPoolEntryRef Ref = +      Holder.getStringPool().getEntry(*Asm, Name); + +  switch (getAccelTableKind()) { +  case AccelTableKind::Apple: +    AppleAccel.addName(Ref, Die); +    break; +  case AccelTableKind::Dwarf: +    AccelDebugNames.addName(Ref, Die); +    break; +  case AccelTableKind::Default: +    llvm_unreachable("Default should have already been resolved."); +  case AccelTableKind::None: +    llvm_unreachable("None handled above"); +  } +} + +void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { +  addAccelNameImpl(AccelNames, Name, Die);  }  void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { -  if (!useDwarfAccelTables()) -    return; -  AccelObjC.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); +  // ObjC names go only into the Apple accelerator tables. +  if (getAccelTableKind() == AccelTableKind::Apple) +    addAccelNameImpl(AccelObjC, Name, Die);  }  void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { -  if (!useDwarfAccelTables()) -    return; -  AccelNamespace.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); +  addAccelNameImpl(AccelNamespace, Name, Die);  }  void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { -  if (!useDwarfAccelTables()) -    return; -  AccelTypes.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die); +  addAccelNameImpl(AccelTypes, Name, Die);  }  uint16_t DwarfDebug::getDwarfVersion() const {  | 
