[llvm-commits] [llvm] r72194 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Bill Wendling isanbard at gmail.com
Wed May 20 16:21:42 PDT 2009


Author: void
Date: Wed May 20 18:21:38 2009
New Revision: 72194

URL: http://llvm.org/viewvc/llvm-project?rev=72194&view=rev
Log:
Move 'Emit' methods down to their own place.

Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=72194&r1=72193&r2=72194&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Wed May 20 18:21:38 2009
@@ -1196,1445 +1196,1445 @@
 #endif
 }
 
-/// EmitInitial - Emit initial Dwarf declarations.  This is necessary for cc
-/// tools to recognize the object file contains Dwarf information.
-void DwarfDebug::EmitInitial() {
-  // Check to see if we already emitted intial headers.
-  if (didInitial) return;
-  didInitial = true;
-
-  // Dwarf sections base addresses.
-  if (TAI->doesDwarfRequireFrameSection()) {
-    Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
-    EmitLabel("section_debug_frame", 0);
+/// GetOrCreateSourceID - 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(const std::string &DirName,
+                                         const std::string &FileName) {
+  unsigned DId;
+  StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName);
+  if (DI != DirectoryIdMap.end()) {
+    DId = DI->getValue();
+  } else {
+    DId = DirectoryNames.size() + 1;
+    DirectoryIdMap[DirName] = DId;
+    DirectoryNames.push_back(DirName);
   }
 
-  Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
-  EmitLabel("section_info", 0);
-  Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection());
-  EmitLabel("section_abbrev", 0);
-  Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
-  EmitLabel("section_aranges", 0);
-
-  if (TAI->doesSupportMacInfoSection()) {
-    Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());
-    EmitLabel("section_macinfo", 0);
+  unsigned FId;
+  StringMap<unsigned>::iterator FI = SourceFileIdMap.find(FileName);
+  if (FI != SourceFileIdMap.end()) {
+    FId = FI->getValue();
+  } else {
+    FId = SourceFileNames.size() + 1;
+    SourceFileIdMap[FileName] = FId;
+    SourceFileNames.push_back(FileName);
   }
 
-  Asm->SwitchToDataSection(TAI->getDwarfLineSection());
-  EmitLabel("section_line", 0);
-  Asm->SwitchToDataSection(TAI->getDwarfLocSection());
-  EmitLabel("section_loc", 0);
-  Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection());
-  EmitLabel("section_pubnames", 0);
-  Asm->SwitchToDataSection(TAI->getDwarfStrSection());
-  EmitLabel("section_str", 0);
-  Asm->SwitchToDataSection(TAI->getDwarfRangesSection());
-  EmitLabel("section_ranges", 0);
-
-  Asm->SwitchToSection(TAI->getTextSection());
-  EmitLabel("text_begin", 0);
-  Asm->SwitchToSection(TAI->getDataSection());
-  EmitLabel("data_begin", 0);
-}
+  DenseMap<std::pair<unsigned, unsigned>, unsigned>::iterator SI =
+    SourceIdMap.find(std::make_pair(DId, FId));
+  if (SI != SourceIdMap.end())
+    return SI->second;
 
-/// EmitDIE - Recusively Emits a debug information entry.
-///
-void DwarfDebug::EmitDIE(DIE *Die) {
-  // Get the abbreviation for this DIE.
-  unsigned AbbrevNumber = Die->getAbbrevNumber();
-  const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+  unsigned SrcId = SourceIds.size() + 1;  // DW_AT_decl_file cannot be 0.
+  SourceIdMap[std::make_pair(DId, FId)] = SrcId;
+  SourceIds.push_back(std::make_pair(DId, FId));
 
-  Asm->EOL();
+  return SrcId;
+}
 
-  // Emit the code (index) for the abbreviation.
-  Asm->EmitULEB128Bytes(AbbrevNumber);
+void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) {
+  DICompileUnit DIUnit(GV);
+  std::string Dir, FN, Prod;
+  unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir),
+                                    DIUnit.getFilename(FN));
 
-  if (Asm->isVerbose())
-    Asm->EOL(std::string("Abbrev [" +
-                         utostr(AbbrevNumber) +
-                         "] 0x" + utohexstr(Die->getOffset()) +
-                         ":0x" + utohexstr(Die->getSize()) + " " +
-                         dwarf::TagString(Abbrev->getTag())));
-  else
-    Asm->EOL();
+  DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+  AddSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+                   DWLabel("section_line", 0), DWLabel("section_line", 0),
+                   false);
+  AddString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
+            DIUnit.getProducer(Prod));
+  AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
+          DIUnit.getLanguage());
+  AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
 
-  SmallVector<DIEValue*, 32> &Values = Die->getValues();
-  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
+  if (!Dir.empty())
+    AddString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
+  if (DIUnit.isOptimized())
+    AddUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
 
-  // Emit the DIE attribute values.
-  for (unsigned i = 0, N = Values.size(); i < N; ++i) {
-    unsigned Attr = AbbrevData[i].getAttribute();
-    unsigned Form = AbbrevData[i].getForm();
-    assert(Form && "Too many attributes for DIE (check abbreviation)");
+  std::string Flags;
+  DIUnit.getFlags(Flags);
+  if (!Flags.empty())
+    AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
 
-    switch (Attr) {
-    case dwarf::DW_AT_sibling:
-      Asm->EmitInt32(Die->SiblingOffset());
-      break;
-    case dwarf::DW_AT_abstract_origin: {
-      DIEEntry *E = cast<DIEEntry>(Values[i]);
-      DIE *Origin = E->getEntry();
-      unsigned Addr =
-        CompileUnitOffsets[Die->getAbstractCompileUnit()] +
-        Origin->getOffset();
+  unsigned RVer = DIUnit.getRunTimeVersion();
+  if (RVer)
+    AddUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
+            dwarf::DW_FORM_data1, RVer);
 
-      Asm->EmitInt32(Addr);
-      break;
-    }
-    default:
-      // Emit an attribute using the defined form.
-      Values[i]->EmitValue(this, Form);
-      break;
+  CompileUnit *Unit = new CompileUnit(ID, Die);
+  if (DIUnit.isMain()) {
+    assert(!MainCU && "Multiple main compile units are found!");
+    MainCU = Unit;
     }
 
-    Asm->EOL(dwarf::AttributeString(Attr));
-  }
-
-  // Emit the DIE children if any.
-  if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
-    const std::vector<DIE *> &Children = Die->getChildren();
-
-    for (unsigned j = 0, M = Children.size(); j < M; ++j)
-      EmitDIE(Children[j]);
-
-    Asm->EmitInt8(0); Asm->EOL("End Of Children Mark");
-  }
+  CompileUnitMap[DIUnit.getGV()] = Unit;
+  CompileUnits.push_back(Unit);
 }
 
-/// SizeAndOffsetDie - Compute the size and offset of a DIE.
-///
-unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) {
-  // Get the children.
-  const std::vector<DIE *> &Children = Die->getChildren();
-
-  // If not last sibling and has children then add sibling offset attribute.
-  if (!Last && !Children.empty()) Die->AddSiblingOffset();
-
-  // Record the abbreviation.
-  AssignAbbrevNumber(Die->getAbbrev());
-
-  // Get the abbreviation for this DIE.
-  unsigned AbbrevNumber = Die->getAbbrevNumber();
-  const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+/// ConstructCompileUnits - Create a compile unit DIEs.
+void DwarfDebug::ConstructCompileUnits() {
+  GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.compile_units");
+  if (!Root)
+    return;
+  assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
+         "Malformed compile unit descriptor anchor type");
+  Constant *RootC = cast<Constant>(*Root->use_begin());
+  assert(RootC->hasNUsesOrMore(1) &&
+         "Malformed compile unit descriptor anchor type");
 
-  // Set DIE offset
-  Die->setOffset(Offset);
+  for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
+       UI != UE; ++UI)
+    for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
+         UUI != UUE; ++UUI) {
+      GlobalVariable *GV = cast<GlobalVariable>(*UUI);
+      ConstructCompileUnit(GV);
+    }
+}
 
-  // Start the size with the size of abbreviation code.
-  Offset += TargetAsmInfo::getULEB128Size(AbbrevNumber);
+bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) {
+  DIGlobalVariable DI_GV(GV);
+  CompileUnit *DW_Unit = MainCU;
+  if (!DW_Unit)
+    DW_Unit = &FindCompileUnit(DI_GV.getCompileUnit());
 
-  const SmallVector<DIEValue*, 32> &Values = Die->getValues();
-  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
+  // Check for pre-existence.
+  DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV());
+  if (Slot)
+    return false;
 
-  // Size the DIE attribute values.
-  for (unsigned i = 0, N = Values.size(); i < N; ++i)
-    // Size attribute value.
-    Offset += Values[i]->SizeOf(TD, AbbrevData[i].getForm());
+  DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV);
 
-  // Size the DIE children if any.
-  if (!Children.empty()) {
-    assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
-           "Children flag not set");
+  // Add address.
+  DIEBlock *Block = new DIEBlock();
+  AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
+  std::string GLN;
+  AddObjectLabel(Block, 0, dwarf::DW_FORM_udata,
+                 Asm->getGlobalLinkName(DI_GV.getGlobal(), GLN));
+  AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
 
-    for (unsigned j = 0, M = Children.size(); j < M; ++j)
-      Offset = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
+  // Add to map.
+  Slot = VariableDie;
 
-    // End of children marker.
-    Offset += sizeof(int8_t);
-  }
+  // Add to context owner.
+  DW_Unit->getDie()->AddChild(VariableDie);
 
-  Die->setSize(Offset - Die->getOffset());
-  return Offset;
+  // Expose as global. FIXME - need to check external flag.
+  std::string Name;
+  DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie);
+  return true;
 }
 
-/// SizeAndOffsets - Compute the size and offset of all the DIEs.
-///
-void DwarfDebug::SizeAndOffsets() {
-  // Compute size of compile unit header.
-  static unsigned Offset =
-    sizeof(int32_t) + // Length of Compilation Unit Info
-    sizeof(int16_t) + // DWARF version number
-    sizeof(int32_t) + // Offset Into Abbrev. Section
-    sizeof(int8_t);   // Pointer Size (in bytes)
+/// ConstructGlobalVariableDIEs - Create DIEs for each of the externally visible
+/// global variables. Return true if at least one global DIE is created.
+bool DwarfDebug::ConstructGlobalVariableDIEs() {
+  GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables");
+  if (!Root)
+    return false;
 
-  // Process base compile unit.
-  if (MainCU) {
-    SizeAndOffsetDie(MainCU->getDie(), Offset, true);
-    CompileUnitOffsets[MainCU] = 0;
-    return;
-  }
+  assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
+         "Malformed global variable descriptor anchor type");
+  Constant *RootC = cast<Constant>(*Root->use_begin());
+  assert(RootC->hasNUsesOrMore(1) &&
+         "Malformed global variable descriptor anchor type");
 
-  // Process all compile units.
-  unsigned PrevOffset = 0;
+  bool Result = false;
+  for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
+       UI != UE; ++UI)
+    for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
+         UUI != UUE; ++UUI)
+      Result |= ConstructGlobalVariableDIE(cast<GlobalVariable>(*UUI));
 
-  for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) {
-    CompileUnit *Unit = CompileUnits[i];
-    CompileUnitOffsets[Unit] = PrevOffset;
-    PrevOffset += SizeAndOffsetDie(Unit->getDie(), Offset, true)
-      + sizeof(int32_t);  // FIXME - extra pad for gdb bug.
-  }
+  return Result;
 }
 
-/// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section.
-///
-void DwarfDebug::EmitDebugInfoPerCU(CompileUnit *Unit) {
-  DIE *Die = Unit->getDie();
-
-  // Emit the compile units header.
-  EmitLabel("info_begin", Unit->getID());
-
-  // Emit size of content not including length itself
-  unsigned ContentSize = Die->getSize() +
-    sizeof(int16_t) + // DWARF version number
-    sizeof(int32_t) + // Offset Into Abbrev. Section
-    sizeof(int8_t) +  // Pointer Size (in bytes)
-    sizeof(int32_t);  // FIXME - extra pad for gdb bug.
+bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) {
+  DISubprogram SP(GV);
+  CompileUnit *Unit = MainCU;
+  if (!Unit)
+    Unit = &FindCompileUnit(SP.getCompileUnit());
 
-  Asm->EmitInt32(ContentSize);  Asm->EOL("Length of Compilation Unit Info");
-  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
-  EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false);
-  Asm->EOL("Offset Into Abbrev. Section");
-  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
+  // Check for pre-existence.
+  DIE *&Slot = Unit->getDieMapSlotFor(GV);
+  if (Slot)
+    return false;
 
-  EmitDIE(Die);
-  // FIXME - extra padding for gdb bug.
-  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
-  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
-  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
-  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
-  EmitLabel("info_end", Unit->getID());
+  if (!SP.isDefinition())
+    // This is a method declaration which will be handled while constructing
+    // class type.
+    return false;
 
-  Asm->EOL();
-}
+  DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP);
 
-void DwarfDebug::EmitDebugInfo() {
-  // Start debug info section.
-  Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
+  // Add to map.
+  Slot = SubprogramDie;
 
-  if (MainCU) {
-    EmitDebugInfoPerCU(MainCU);
-    return;
-  }
+  // Add to context owner.
+  Unit->getDie()->AddChild(SubprogramDie);
 
-  for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i)
-    EmitDebugInfoPerCU(CompileUnits[i]);
+  // Expose as global.
+  std::string Name;
+  Unit->AddGlobal(SP.getName(Name), SubprogramDie);
+  return true;
 }
 
-/// EmitAbbreviations - Emit the abbreviation section.
-///
-void DwarfDebug::EmitAbbreviations() const {
-  // Check to see if it is worth the effort.
-  if (!Abbreviations.empty()) {
-    // Start the debug abbrev section.
-    Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection());
-
-    EmitLabel("abbrev_begin", 0);
-
-    // For each abbrevation.
-    for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
-      // Get abbreviation data
-      const DIEAbbrev *Abbrev = Abbreviations[i];
-
-      // Emit the abbrevations code (base 1 index.)
-      Asm->EmitULEB128Bytes(Abbrev->getNumber());
-      Asm->EOL("Abbreviation Code");
-
-      // Emit the abbreviations data.
-      Abbrev->Emit(Asm);
-
-      Asm->EOL();
-    }
-
-    // Mark end of abbreviations.
-    Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
+/// ConstructSubprograms - Create DIEs for each of the externally visible
+/// subprograms. Return true if at least one subprogram DIE is created.
+bool DwarfDebug::ConstructSubprograms() {
+  GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms");
+  if (!Root)
+    return false;
 
-    EmitLabel("abbrev_end", 0);
-    Asm->EOL();
-  }
-}
+  assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
+         "Malformed subprogram descriptor anchor type");
+  Constant *RootC = cast<Constant>(*Root->use_begin());
+  assert(RootC->hasNUsesOrMore(1) &&
+         "Malformed subprogram descriptor anchor type");
 
-/// EmitEndOfLineMatrix - Emit the last address of the section and the end of
-/// the line matrix.
-///
-void DwarfDebug::EmitEndOfLineMatrix(unsigned SectionEnd) {
-  // Define last address of section.
-  Asm->EmitInt8(0); Asm->EOL("Extended Op");
-  Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
-  Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
-  EmitReference("section_end", SectionEnd); Asm->EOL("Section end label");
+  bool Result = false;
+  for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
+       UI != UE; ++UI)
+    for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
+         UUI != UUE; ++UUI)
+      Result |= ConstructSubprogram(cast<GlobalVariable>(*UUI));
 
-  // Mark end of matrix.
-  Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence");
-  Asm->EmitULEB128Bytes(1); Asm->EOL();
-  Asm->EmitInt8(1); Asm->EOL();
+  return Result;
 }
 
-/// EmitDebugLines - Emit source line information.
-///
-void DwarfDebug::EmitDebugLines() {
-  // If the target is using .loc/.file, the assembler will be emitting the
-  // .debug_line table automatically.
-  if (TAI->hasDotLocAndDotFile())
-    return;
-
-  // Minimum line delta, thus ranging from -10..(255-10).
-  const int MinLineDelta = -(dwarf::DW_LNS_fixed_advance_pc + 1);
-  // Maximum line delta, thus ranging from -10..(255-10).
-  const int MaxLineDelta = 255 + MinLineDelta;
-
-  // Start the dwarf line section.
-  Asm->SwitchToDataSection(TAI->getDwarfLineSection());
-
-  // Construct the section header.
-  EmitDifference("line_end", 0, "line_begin", 0, true);
-  Asm->EOL("Length of Source Line Info");
-  EmitLabel("line_begin", 0);
-
-  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
-
-  EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true);
-  Asm->EOL("Prolog Length");
-  EmitLabel("line_prolog_begin", 0);
+/// SetDebugInfo - Create global DIEs and emit initial debug info sections.
+/// This is inovked by the target AsmPrinter.
+void DwarfDebug::SetDebugInfo(MachineModuleInfo *mmi) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length");
+  // Create all the compile unit DIEs.
+  ConstructCompileUnits();
 
-  Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag");
+  if (CompileUnits.empty()) {
+    if (TimePassesIsEnabled)
+      DebugTimer->stopTimer();
 
-  Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)");
+    return;
+  }
 
-  Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)");
+  // Create DIEs for each of the externally visible global variables.
+  bool globalDIEs = ConstructGlobalVariableDIEs();
 
-  Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base");
+  // Create DIEs for each of the externally visible subprograms.
+  bool subprogramDIEs = ConstructSubprograms();
 
-  // Line number standard opcode encodings argument count
-  Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count");
-  Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count");
-  Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count");
-  Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count");
-  Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count");
-  Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count");
-  Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count");
-  Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count");
-  Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count");
+  // If there is not any debug info available for any global variables and any
+  // subprograms then there is not any debug info to emit.
+  if (!globalDIEs && !subprogramDIEs) {
+    if (TimePassesIsEnabled)
+      DebugTimer->stopTimer();
 
-  // Emit directories.
-  for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
-    Asm->EmitString(getSourceDirectoryName(DI));
-    Asm->EOL("Directory");
+    return;
   }
 
-  Asm->EmitInt8(0); Asm->EOL("End of directories");
+  MMI = mmi;
+  shouldEmit = true;
+  MMI->setDebugInfoAvailability(true);
 
-  // Emit files.
-  for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
-    // Remember source id starts at 1.
-    std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI);
-    Asm->EmitString(getSourceFileName(Id.second));
-    Asm->EOL("Source");
-    Asm->EmitULEB128Bytes(Id.first);
-    Asm->EOL("Directory #");
-    Asm->EmitULEB128Bytes(0);
-    Asm->EOL("Mod date");
-    Asm->EmitULEB128Bytes(0);
-    Asm->EOL("File size");
+  // Prime section data.
+  SectionMap.insert(TAI->getTextSection());
+
+  // Print out .file directives to specify files for .loc directives. These are
+  // printed out early so that they precede any .loc directives.
+  if (TAI->hasDotLocAndDotFile()) {
+    for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) {
+      // Remember source id starts at 1.
+      std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i);
+      sys::Path FullPath(getSourceDirectoryName(Id.first));
+      bool AppendOk =
+        FullPath.appendComponent(getSourceFileName(Id.second));
+      assert(AppendOk && "Could not append filename to directory!");
+      AppendOk = false;
+      Asm->EmitFile(i, FullPath.toString());
+      Asm->EOL();
+    }
   }
 
-  Asm->EmitInt8(0); Asm->EOL("End of files");
+  // Emit initial sections
+  EmitInitial();
 
-  EmitLabel("line_prolog_end", 0);
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
+}
 
-  // A sequence for each text section.
-  unsigned SecSrcLinesSize = SectionSourceLines.size();
+/// EndModule - Emit all Dwarf sections that should come after the content.
+///
+void DwarfDebug::EndModule() {
+  if (!ShouldEmitDwarfDebug())
+    return;
 
-  for (unsigned j = 0; j < SecSrcLinesSize; ++j) {
-    // Isolate current sections line info.
-    const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-    if (Asm->isVerbose()) {
-      const Section* S = SectionMap[j + 1];
-      O << '\t' << TAI->getCommentString() << " Section"
-        << S->getName() << '\n';
-    } else {
-      Asm->EOL();
-    }
+  // Standard sections final addresses.
+  Asm->SwitchToSection(TAI->getTextSection());
+  EmitLabel("text_end", 0);
+  Asm->SwitchToSection(TAI->getDataSection());
+  EmitLabel("data_end", 0);
 
-    // Dwarf assumes we start with first line of first source file.
-    unsigned Source = 1;
-    unsigned Line = 1;
+  // End text sections.
+  for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
+    Asm->SwitchToSection(SectionMap[i]);
+    EmitLabel("section_end", i);
+  }
 
-    // Construct rows of the address, source, line, column matrix.
-    for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
-      const SrcLineInfo &LineInfo = LineInfos[i];
-      unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID());
-      if (!LabelID) continue;
+  // Emit common frame information.
+  EmitCommonDebugFrame();
 
-      if (!Asm->isVerbose())
-        Asm->EOL();
-      else {
-        std::pair<unsigned, unsigned> SourceID =
-          getSourceDirectoryAndFileIds(LineInfo.getSourceID());
-        O << '\t' << TAI->getCommentString() << ' '
-          << getSourceDirectoryName(SourceID.first) << ' '
-          << getSourceFileName(SourceID.second)
-          <<" :" << utostr_32(LineInfo.getLine()) << '\n';
-      }
+  // Emit function debug frame information
+  for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
+         E = DebugFrames.end(); I != E; ++I)
+    EmitFunctionDebugFrame(*I);
 
-      // Define the line address.
-      Asm->EmitInt8(0); Asm->EOL("Extended Op");
-      Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
-      Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
-      EmitReference("label",  LabelID); Asm->EOL("Location label");
+  // Compute DIE offsets and sizes.
+  SizeAndOffsets();
 
-      // If change of source, then switch to the new source.
-      if (Source != LineInfo.getSourceID()) {
-        Source = LineInfo.getSourceID();
-        Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file");
-        Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source");
-      }
+  // Emit all the DIEs into a debug info section
+  EmitDebugInfo();
 
-      // If change of line.
-      if (Line != LineInfo.getLine()) {
-        // Determine offset.
-        int Offset = LineInfo.getLine() - Line;
-        int Delta = Offset - MinLineDelta;
+  // Corresponding abbreviations into a abbrev section.
+  EmitAbbreviations();
 
-        // Update line.
-        Line = LineInfo.getLine();
+  // Emit source line correspondence into a debug line section.
+  EmitDebugLines();
 
-        // If delta is small enough and in range...
-        if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
-          // ... then use fast opcode.
-          Asm->EmitInt8(Delta - MinLineDelta); Asm->EOL("Line Delta");
-        } else {
-          // ... otherwise use long hand.
-          Asm->EmitInt8(dwarf::DW_LNS_advance_line);
-          Asm->EOL("DW_LNS_advance_line");
-          Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset");
-          Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
-        }
-      } else {
-        // Copy the previous row (different address or source)
-        Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
-      }
-    }
+  // Emit info into a debug pubnames section.
+  EmitDebugPubNames();
 
-    EmitEndOfLineMatrix(j + 1);
-  }
+  // Emit info into a debug str section.
+  EmitDebugStr();
 
-  if (SecSrcLinesSize == 0)
-    // Because we're emitting a debug_line section, we still need a line
-    // table. The linker and friends expect it to exist. If there's nothing to
-    // put into it, emit an empty table.
-    EmitEndOfLineMatrix(1);
+  // Emit info into a debug loc section.
+  EmitDebugLoc();
 
-  EmitLabel("line_end", 0);
-  Asm->EOL();
-}
+  // Emit info into a debug aranges section.
+  EmitDebugARanges();
 
-/// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
-///
-void DwarfDebug::EmitCommonDebugFrame() {
-  if (!TAI->doesDwarfRequireFrameSection())
-    return;
+  // Emit info into a debug ranges section.
+  EmitDebugRanges();
 
-  int stackGrowth =
-    Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
-      TargetFrameInfo::StackGrowsUp ?
-    TD->getPointerSize() : -TD->getPointerSize();
+  // Emit info into a debug macinfo section.
+  EmitDebugMacInfo();
 
-  // Start the dwarf frame section.
-  Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
+  // Emit inline info.
+  EmitDebugInlineInfo();
 
-  EmitLabel("debug_frame_common", 0);
-  EmitDifference("debug_frame_common_end", 0,
-                 "debug_frame_common_begin", 0, true);
-  Asm->EOL("Length of Common Information Entry");
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
+}
 
-  EmitLabel("debug_frame_common_begin", 0);
-  Asm->EmitInt32((int)dwarf::DW_CIE_ID);
-  Asm->EOL("CIE Identifier Tag");
-  Asm->EmitInt8(dwarf::DW_CIE_VERSION);
-  Asm->EOL("CIE Version");
-  Asm->EmitString("");
-  Asm->EOL("CIE Augmentation");
-  Asm->EmitULEB128Bytes(1);
-  Asm->EOL("CIE Code Alignment Factor");
-  Asm->EmitSLEB128Bytes(stackGrowth);
-  Asm->EOL("CIE Data Alignment Factor");
-  Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
-  Asm->EOL("CIE RA Column");
+/// BeginFunction - Gather pre-function debug information.  Assumes being
+/// emitted immediately after the function entry point.
+void DwarfDebug::BeginFunction(MachineFunction *MF) {
+  this->MF = MF;
 
-  std::vector<MachineMove> Moves;
-  RI->getInitialFrameState(Moves);
+  if (!ShouldEmitDwarfDebug()) return;
 
-  EmitFrameMoves(NULL, 0, Moves, false);
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  Asm->EmitAlignment(2, 0, 0, false);
-  EmitLabel("debug_frame_common_end", 0);
+  // Begin accumulating function debug information.
+  MMI->BeginFunction(MF);
 
-  Asm->EOL();
+  // Assumes in correct section after the entry point.
+  EmitLabel("func_begin", ++SubprogramCount);
+
+  // Emit label for the implicitly defined dbg.stoppoint at the start of the
+  // function.
+  DebugLoc FDL = MF->getDefaultDebugLoc();
+  if (!FDL.isUnknown()) {
+    DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
+    unsigned LabelID = RecordSourceLine(DLT.Line, DLT.Col,
+                                        DICompileUnit(DLT.CompileUnit));
+    Asm->printLabel(LabelID);
+  }
+
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 }
 
-/// EmitFunctionDebugFrame - Emit per function frame info into a debug frame
-/// section.
-void
-DwarfDebug::EmitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
-  if (!TAI->doesDwarfRequireFrameSection())
-    return;
+/// EndFunction - Gather and emit post-function debug information.
+///
+void DwarfDebug::EndFunction(MachineFunction *MF) {
+  if (!ShouldEmitDwarfDebug()) return;
 
-  // Start the dwarf frame section.
-  Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  EmitDifference("debug_frame_end", DebugFrameInfo.Number,
-                 "debug_frame_begin", DebugFrameInfo.Number, true);
-  Asm->EOL("Length of Frame Information Entry");
+  // Define end label for subprogram.
+  EmitLabel("func_end", SubprogramCount);
 
-  EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
+  // Get function line info.
+  if (!Lines.empty()) {
+    // Get section line info.
+    unsigned ID = SectionMap.insert(Asm->CurrentSection_);
+    if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
+    std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
+    // Append the function info to section info.
+    SectionLineInfos.insert(SectionLineInfos.end(),
+                            Lines.begin(), Lines.end());
+  }
 
-  EmitSectionOffset("debug_frame_common", "section_debug_frame",
-                    0, 0, true, false);
-  Asm->EOL("FDE CIE offset");
+  // Construct the DbgScope for abstract instances.
+  for (SmallVector<DbgScope *, 32>::iterator
+         I = AbstractInstanceRootList.begin(),
+         E = AbstractInstanceRootList.end(); I != E; ++I)
+    ConstructAbstractDbgScope(*I);
 
-  EmitReference("func_begin", DebugFrameInfo.Number);
-  Asm->EOL("FDE initial location");
-  EmitDifference("func_end", DebugFrameInfo.Number,
-                 "func_begin", DebugFrameInfo.Number);
-  Asm->EOL("FDE address range");
+  // Construct scopes for subprogram.
+  if (FunctionDbgScope)
+    ConstructFunctionDbgScope(FunctionDbgScope);
+  else
+    // FIXME: This is wrong. We are essentially getting past a problem with
+    // debug information not being able to handle unreachable blocks that have
+    // debug information in them. In particular, those unreachable blocks that
+    // have "region end" info in them. That situation results in the "root
+    // scope" not being created. If that's the case, then emit a "default"
+    // scope, i.e., one that encompasses the whole function. This isn't
+    // desirable. And a better way of handling this (and all of the debugging
+    // information) needs to be explored.
+    ConstructDefaultDbgScope(MF);
 
-  EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
-                 false);
+  DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
+                                               MMI->getFrameMoves()));
+
+  // Clear debug info
+  if (FunctionDbgScope) {
+    delete FunctionDbgScope;
+    DbgScopeMap.clear();
+    DbgAbstractScopeMap.clear();
+    DbgConcreteScopeMap.clear();
+    InlinedVariableScopes.clear();
+    FunctionDbgScope = NULL;
+    LexicalScopeStack.clear();
+    AbstractInstanceRootList.clear();
+  }
 
-  Asm->EmitAlignment(2, 0, 0, false);
-  EmitLabel("debug_frame_end", DebugFrameInfo.Number);
+  Lines.clear();
 
-  Asm->EOL();
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 }
 
-void DwarfDebug::EmitDebugPubNamesPerCU(CompileUnit *Unit) {
-  EmitDifference("pubnames_end", Unit->getID(),
-                 "pubnames_begin", Unit->getID(), true);
-  Asm->EOL("Length of Public Names Info");
-
-  EmitLabel("pubnames_begin", Unit->getID());
+/// RecordSourceLine - Records location information and associates it with a
+/// label. Returns a unique label ID used to generate a label and provide
+/// correspondence to the source line list.
+unsigned DwarfDebug::RecordSourceLine(Value *V, unsigned Line, unsigned Col) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
+  CompileUnit *Unit = CompileUnitMap[V];
+  assert(Unit && "Unable to find CompileUnit");
+  unsigned ID = MMI->NextLabelID();
+  Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID));
 
-  EmitSectionOffset("info_begin", "section_info",
-                    Unit->getID(), 0, true, false);
-  Asm->EOL("Offset of Compilation Unit Info");
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 
-  EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),
-                 true);
-  Asm->EOL("Compilation Unit Length");
+  return ID;
+}
 
-  StringMap<DIE*> &Globals = Unit->getGlobals();
-  for (StringMap<DIE*>::const_iterator
-         GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
-    const char *Name = GI->getKeyData();
-    DIE * Entity = GI->second;
+/// RecordSourceLine - Records location information and associates it with a
+/// label. Returns a unique label ID used to generate a label and provide
+/// correspondence to the source line list.
+unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col,
+                                      DICompileUnit CU) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-    Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
-    Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
-  }
+  std::string Dir, Fn;
+  unsigned Src = GetOrCreateSourceID(CU.getDirectory(Dir),
+                                     CU.getFilename(Fn));
+  unsigned ID = MMI->NextLabelID();
+  Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
 
-  Asm->EmitInt32(0); Asm->EOL("End Mark");
-  EmitLabel("pubnames_end", Unit->getID());
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 
-  Asm->EOL();
+  return ID;
 }
 
-/// EmitDebugPubNames - Emit visible names into a debug pubnames section.
-///
-void DwarfDebug::EmitDebugPubNames() {
-  // Start the dwarf pubnames section.
-  Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection());
+/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
+/// timed. 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(const std::string &DirName,
+                                         const std::string &FileName) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  if (MainCU) {
-    EmitDebugPubNamesPerCU(MainCU);
-    return;
-  }
+  unsigned SrcId = GetOrCreateSourceID(DirName, FileName);
 
-  for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i)
-    EmitDebugPubNamesPerCU(CompileUnits[i]);
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
+
+  return SrcId;
 }
 
-/// EmitDebugStr - Emit visible names into a debug str section.
-///
-void DwarfDebug::EmitDebugStr() {
-  // Check to see if it is worth the effort.
-  if (!StringPool.empty()) {
-    // Start the dwarf str section.
-    Asm->SwitchToDataSection(TAI->getDwarfStrSection());
+/// RecordRegionStart - Indicate the start of a region.
+unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-    // For each of strings in the string pool.
-    for (unsigned StringID = 1, N = StringPool.size();
-         StringID <= N; ++StringID) {
-      // Emit a label for reference from debug information entries.
-      EmitLabel("string", StringID);
+  DbgScope *Scope = getOrCreateScope(V);
+  unsigned ID = MMI->NextLabelID();
+  if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
+  LexicalScopeStack.push_back(Scope);
 
-      // Emit the string itself.
-      const std::string &String = StringPool[StringID];
-      Asm->EmitString(String); Asm->EOL();
-    }
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 
-    Asm->EOL();
-  }
+  return ID;
 }
 
-/// EmitDebugLoc - Emit visible names into a debug loc section.
-///
-void DwarfDebug::EmitDebugLoc() {
-  // Start the dwarf loc section.
-  Asm->SwitchToDataSection(TAI->getDwarfLocSection());
-  Asm->EOL();
-}
+/// RecordRegionEnd - Indicate the end of a region.
+unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-/// EmitDebugARanges - Emit visible names into a debug aranges section.
-///
-void DwarfDebug::EmitDebugARanges() {
-  // Start the dwarf aranges section.
-  Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
+  DbgScope *Scope = getOrCreateScope(V);
+  unsigned ID = MMI->NextLabelID();
+  Scope->setEndLabelID(ID);
+  if (LexicalScopeStack.size() != 0)
+    LexicalScopeStack.pop_back();
 
-  // FIXME - Mock up
-#if 0
-  CompileUnit *Unit = GetBaseCompileUnit();
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 
-  // Don't include size of length
-  Asm->EmitInt32(0x1c); Asm->EOL("Length of Address Ranges Info");
+  return ID;
+}
 
-  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
+/// RecordVariable - Indicate the declaration of a local variable.
+void DwarfDebug::RecordVariable(GlobalVariable *GV, unsigned FrameIndex,
+                                const MachineInstr *MI) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  EmitReference("info_begin", Unit->getID());
-  Asm->EOL("Offset of Compilation Unit Info");
+  DIDescriptor Desc(GV);
+  DbgScope *Scope = NULL;
+  bool InlinedFnVar = false;
 
-  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address");
+  if (Desc.getTag() == dwarf::DW_TAG_variable) {
+    // GV is a global variable.
+    DIGlobalVariable DG(GV);
+    Scope = getOrCreateScope(DG.getContext().getGV());
+  } else {
+    DenseMap<const MachineInstr *, DbgScope *>::iterator
+      SI = InlinedVariableScopes.find(MI);
 
-  Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor");
+    if (SI != InlinedVariableScopes.end()) {
+      // or GV is an inlined local variable.
+      Scope = SI->second;
+    } else {
+      DIVariable DV(GV);
+      GlobalVariable *V = DV.getContext().getGV();
 
-  Asm->EmitInt16(0);  Asm->EOL("Pad (1)");
-  Asm->EmitInt16(0);  Asm->EOL("Pad (2)");
+      // FIXME: The code that checks for the inlined local variable is a hack!
+      DenseMap<const GlobalVariable *, DbgScope *>::iterator
+        AI = AbstractInstanceRootMap.find(V);
 
-  // Range 1
-  EmitReference("text_begin", 0); Asm->EOL("Address");
-  EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length");
+      if (AI != AbstractInstanceRootMap.end()) {
+        // This method is called each time a DECLARE node is encountered. For an
+        // inlined function, this could be many, many times. We don't want to
+        // re-add variables to that DIE for each time. We just want to add them
+        // once. Check to make sure that we haven't added them already.
+        DenseMap<const GlobalVariable *,
+          SmallSet<const GlobalVariable *, 32> >::iterator
+          IP = InlinedParamMap.find(V);
 
-  Asm->EmitInt32(0); Asm->EOL("EOM (1)");
-  Asm->EmitInt32(0); Asm->EOL("EOM (2)");
-#endif
+        if (IP != InlinedParamMap.end() && IP->second.count(GV) > 0) {
+          if (TimePassesIsEnabled)
+            DebugTimer->stopTimer();
+          return;
+        }
 
-  Asm->EOL();
-}
+        // or GV is an inlined local variable.
+        Scope = AI->second;
+        InlinedParamMap[V].insert(GV);
+        InlinedFnVar = true;
+      } else {
+        // or GV is a local variable.
+        Scope = getOrCreateScope(V);
+      }
+    }
+  }
 
-/// EmitDebugRanges - Emit visible names into a debug ranges section.
-///
-void DwarfDebug::EmitDebugRanges() {
-  // Start the dwarf ranges section.
-  Asm->SwitchToDataSection(TAI->getDwarfRangesSection());
-  Asm->EOL();
-}
+  assert(Scope && "Unable to find the variable's scope");
+  DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex, InlinedFnVar);
+  Scope->AddVariable(DV);
 
-/// EmitDebugMacInfo - Emit visible names into a debug macinfo section.
-///
-void DwarfDebug::EmitDebugMacInfo() {
-  if (TAI->doesSupportMacInfoSection()) {
-    // Start the dwarf macinfo section.
-    Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());
-    Asm->EOL();
-  }
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 }
 
-/// EmitDebugInlineInfo - Emit inline info using following format.
-/// Section Header:
-/// 1. length of section
-/// 2. Dwarf version number
-/// 3. address size.
-///
-/// Entries (one "entry" for each function that was inlined):
-///
-/// 1. offset into __debug_str section for MIPS linkage name, if exists;
-///   otherwise offset into __debug_str for regular function name.
-/// 2. offset into __debug_str section for regular function name.
-/// 3. an unsigned LEB128 number indicating the number of distinct inlining
-/// instances for the function.
-///
-/// The rest of the entry consists of a {die_offset, low_pc} pair for each
-/// inlined instance; the die_offset points to the inlined_subroutine die in the
-/// __debug_info section, and the low_pc is the starting address for the
-/// inlining instance.
-void DwarfDebug::EmitDebugInlineInfo() {
-  if (!TAI->doesDwarfUsesInlineInfoSection())
-    return;
+//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
+unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
+                                          unsigned Line, unsigned Col) {
+  unsigned LabelID = MMI->NextLabelID();
 
-  if (!MainCU)
-    return;
+  if (!TAI->doesDwarfUsesInlineInfoSection())
+    return LabelID;
 
-  Asm->SwitchToDataSection(TAI->getDwarfDebugInlineSection());
-  Asm->EOL();
-  EmitDifference("debug_inlined_end", 1,
-                 "debug_inlined_begin", 1, true);
-  Asm->EOL("Length of Debug Inlined Information Entry");
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  EmitLabel("debug_inlined_begin", 1);
+  GlobalVariable *GV = SP.getGV();
+  DenseMap<const GlobalVariable *, DbgScope *>::iterator
+    II = AbstractInstanceRootMap.find(GV);
 
-  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
-  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
+  if (II == AbstractInstanceRootMap.end()) {
+    // Create an abstract instance entry for this inlined function if it doesn't
+    // already exist.
+    DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV));
 
-  for (DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
-         I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
-    GlobalVariable *GV = I->first;
-    SmallVector<unsigned, 4> &Labels = I->second;
-    DISubprogram SP(GV);
-    std::string Name;
-    std::string LName;
+    // Get the compile unit context.
+    CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
+    DIE *SPDie = Unit->getDieMapSlotFor(GV);
+    if (!SPDie)
+      SPDie = CreateSubprogramDIE(Unit, SP, false, true);
 
-    SP.getLinkageName(LName);
-    SP.getName(Name);
+    // Mark as being inlined. This makes this subprogram entry an abstract
+    // instance root.
+    // FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
+    // that it's defined. That probably won't change in the future. However,
+    // this could be more elegant.
+    AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
 
-    Asm->EmitString(LName.empty() ? Name : LName);
-    Asm->EOL("MIPS linkage name");
+    // Keep track of the abstract scope for this function.
+    DbgAbstractScopeMap[GV] = Scope;
 
-    Asm->EmitString(Name); Asm->EOL("Function name");
+    AbstractInstanceRootMap[GV] = Scope;
+    AbstractInstanceRootList.push_back(Scope);
+  }
 
-    Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
+  // Create a concrete inlined instance for this inlined function.
+  DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV));
+  DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
+  CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
+  ScopeDie->setAbstractCompileUnit(Unit);
 
-    for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(),
-           LE = Labels.end(); LI != LE; ++LI) {
-      DIE *SP = MainCU->getDieMapSlotFor(GV);
-      Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset");
+  DIE *Origin = Unit->getDieMapSlotFor(GV);
+  AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
+              dwarf::DW_FORM_ref4, Origin);
+  AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, Unit->getID());
+  AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
+  AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
 
-      if (TD->getPointerSize() == sizeof(int32_t))
-        O << TAI->getData32bitsDirective();
-      else
-        O << TAI->getData64bitsDirective();
+  ConcreteScope->setDie(ScopeDie);
+  ConcreteScope->setStartLabelID(LabelID);
+  MMI->RecordUsedDbgLabel(LabelID);
 
-      PrintLabelName("label", *LI); Asm->EOL("low_pc");
-    }
-  }
+  LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
 
-  EmitLabel("debug_inlined_end", 1);
-  Asm->EOL();
-}
+  // Keep track of the concrete scope that's inlined into this function.
+  DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
+    SI = DbgConcreteScopeMap.find(GV);
 
-/// GetOrCreateSourceID - 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(const std::string &DirName,
-                                         const std::string &FileName) {
-  unsigned DId;
-  StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName);
-  if (DI != DirectoryIdMap.end()) {
-    DId = DI->getValue();
-  } else {
-    DId = DirectoryNames.size() + 1;
-    DirectoryIdMap[DirName] = DId;
-    DirectoryNames.push_back(DirName);
-  }
+  if (SI == DbgConcreteScopeMap.end())
+    DbgConcreteScopeMap[GV].push_back(ConcreteScope);
+  else
+    SI->second.push_back(ConcreteScope);
 
-  unsigned FId;
-  StringMap<unsigned>::iterator FI = SourceFileIdMap.find(FileName);
-  if (FI != SourceFileIdMap.end()) {
-    FId = FI->getValue();
-  } else {
-    FId = SourceFileNames.size() + 1;
-    SourceFileIdMap[FileName] = FId;
-    SourceFileNames.push_back(FileName);
-  }
+  // Track the start label for this inlined function.
+  DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
+    I = InlineInfo.find(GV);
 
-  DenseMap<std::pair<unsigned, unsigned>, unsigned>::iterator SI =
-    SourceIdMap.find(std::make_pair(DId, FId));
-  if (SI != SourceIdMap.end())
-    return SI->second;
+  if (I == InlineInfo.end())
+    InlineInfo[GV].push_back(LabelID);
+  else
+    I->second.push_back(LabelID);
 
-  unsigned SrcId = SourceIds.size() + 1;  // DW_AT_decl_file cannot be 0.
-  SourceIdMap[std::make_pair(DId, FId)] = SrcId;
-  SourceIds.push_back(std::make_pair(DId, FId));
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 
-  return SrcId;
+  return LabelID;
 }
 
-void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) {
-  DICompileUnit DIUnit(GV);
-  std::string Dir, FN, Prod;
-  unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir),
-                                    DIUnit.getFilename(FN));
+/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
+unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
+  if (!TAI->doesDwarfUsesInlineInfoSection())
+    return 0;
 
-  DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
-  AddSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
-                   DWLabel("section_line", 0), DWLabel("section_line", 0),
-                   false);
-  AddString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
-            DIUnit.getProducer(Prod));
-  AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
-          DIUnit.getLanguage());
-  AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
 
-  if (!Dir.empty())
-    AddString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
-  if (DIUnit.isOptimized())
-    AddUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
+  GlobalVariable *GV = SP.getGV();
+  DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
+    I = DbgConcreteScopeMap.find(GV);
 
-  std::string Flags;
-  DIUnit.getFlags(Flags);
-  if (!Flags.empty())
-    AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
+  if (I == DbgConcreteScopeMap.end()) {
+    // FIXME: Can this situation actually happen? And if so, should it?
+    if (TimePassesIsEnabled)
+      DebugTimer->stopTimer();
 
-  unsigned RVer = DIUnit.getRunTimeVersion();
-  if (RVer)
-    AddUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
-            dwarf::DW_FORM_data1, RVer);
+    return 0;
+  }
 
-  CompileUnit *Unit = new CompileUnit(ID, Die);
-  if (DIUnit.isMain()) {
-    assert(!MainCU && "Multiple main compile units are found!");
-    MainCU = Unit;
-    }
+  SmallVector<DbgScope *, 8> &Scopes = I->second;
+  assert(!Scopes.empty() && "We should have at least one debug scope!");
+  DbgScope *Scope = Scopes.back(); Scopes.pop_back();
+  unsigned ID = MMI->NextLabelID();
+  MMI->RecordUsedDbgLabel(ID);
+  Scope->setEndLabelID(ID);
 
-  CompileUnitMap[DIUnit.getGV()] = Unit;
-  CompileUnits.push_back(Unit);
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
+
+  return ID;
 }
 
-/// ConstructCompileUnits - Create a compile unit DIEs.
-void DwarfDebug::ConstructCompileUnits() {
-  GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.compile_units");
-  if (!Root)
+/// RecordVariableScope - Record scope for the variable declared by
+/// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. Record scopes
+/// for only inlined subroutine variables. Other variables's scopes are
+/// determined during RecordVariable().
+void DwarfDebug::RecordVariableScope(DIVariable &DV,
+                                     const MachineInstr *DeclareMI) {
+  if (TimePassesIsEnabled)
+    DebugTimer->startTimer();
+
+  DISubprogram SP(DV.getContext().getGV());
+
+  if (SP.isNull()) {
+    if (TimePassesIsEnabled)
+      DebugTimer->stopTimer();
+
     return;
-  assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
-         "Malformed compile unit descriptor anchor type");
-  Constant *RootC = cast<Constant>(*Root->use_begin());
-  assert(RootC->hasNUsesOrMore(1) &&
-         "Malformed compile unit descriptor anchor type");
+  }
 
-  for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
-       UI != UE; ++UI)
-    for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
-         UUI != UUE; ++UUI) {
-      GlobalVariable *GV = cast<GlobalVariable>(*UUI);
-      ConstructCompileUnit(GV);
-    }
+  DenseMap<GlobalVariable *, DbgScope *>::iterator
+    I = DbgAbstractScopeMap.find(SP.getGV());
+  if (I != DbgAbstractScopeMap.end())
+    InlinedVariableScopes[DeclareMI] = I->second;
+
+  if (TimePassesIsEnabled)
+    DebugTimer->stopTimer();
 }
 
-bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) {
-  DIGlobalVariable DI_GV(GV);
-  CompileUnit *DW_Unit = MainCU;
-  if (!DW_Unit)
-    DW_Unit = &FindCompileUnit(DI_GV.getCompileUnit());
+/// SizeAndOffsetDie - Compute the size and offset of a DIE.
+///
+unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) {
+  // Get the children.
+  const std::vector<DIE *> &Children = Die->getChildren();
 
-  // Check for pre-existence.
-  DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV());
-  if (Slot)
-    return false;
+  // If not last sibling and has children then add sibling offset attribute.
+  if (!Last && !Children.empty()) Die->AddSiblingOffset();
+
+  // Record the abbreviation.
+  AssignAbbrevNumber(Die->getAbbrev());
+
+  // Get the abbreviation for this DIE.
+  unsigned AbbrevNumber = Die->getAbbrevNumber();
+  const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+
+  // Set DIE offset
+  Die->setOffset(Offset);
+
+  // Start the size with the size of abbreviation code.
+  Offset += TargetAsmInfo::getULEB128Size(AbbrevNumber);
+
+  const SmallVector<DIEValue*, 32> &Values = Die->getValues();
+  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
 
-  DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV);
+  // Size the DIE attribute values.
+  for (unsigned i = 0, N = Values.size(); i < N; ++i)
+    // Size attribute value.
+    Offset += Values[i]->SizeOf(TD, AbbrevData[i].getForm());
 
-  // Add address.
-  DIEBlock *Block = new DIEBlock();
-  AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
-  std::string GLN;
-  AddObjectLabel(Block, 0, dwarf::DW_FORM_udata,
-                 Asm->getGlobalLinkName(DI_GV.getGlobal(), GLN));
-  AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
+  // Size the DIE children if any.
+  if (!Children.empty()) {
+    assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
+           "Children flag not set");
 
-  // Add to map.
-  Slot = VariableDie;
+    for (unsigned j = 0, M = Children.size(); j < M; ++j)
+      Offset = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
 
-  // Add to context owner.
-  DW_Unit->getDie()->AddChild(VariableDie);
+    // End of children marker.
+    Offset += sizeof(int8_t);
+  }
 
-  // Expose as global. FIXME - need to check external flag.
-  std::string Name;
-  DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie);
-  return true;
+  Die->setSize(Offset - Die->getOffset());
+  return Offset;
 }
 
-/// ConstructGlobalVariableDIEs - Create DIEs for each of the externally visible
-/// global variables. Return true if at least one global DIE is created.
-bool DwarfDebug::ConstructGlobalVariableDIEs() {
-  GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables");
-  if (!Root)
-    return false;
+/// SizeAndOffsets - Compute the size and offset of all the DIEs.
+///
+void DwarfDebug::SizeAndOffsets() {
+  // Compute size of compile unit header.
+  static unsigned Offset =
+    sizeof(int32_t) + // Length of Compilation Unit Info
+    sizeof(int16_t) + // DWARF version number
+    sizeof(int32_t) + // Offset Into Abbrev. Section
+    sizeof(int8_t);   // Pointer Size (in bytes)
 
-  assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
-         "Malformed global variable descriptor anchor type");
-  Constant *RootC = cast<Constant>(*Root->use_begin());
-  assert(RootC->hasNUsesOrMore(1) &&
-         "Malformed global variable descriptor anchor type");
+  // Process base compile unit.
+  if (MainCU) {
+    SizeAndOffsetDie(MainCU->getDie(), Offset, true);
+    CompileUnitOffsets[MainCU] = 0;
+    return;
+  }
 
-  bool Result = false;
-  for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
-       UI != UE; ++UI)
-    for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
-         UUI != UUE; ++UUI)
-      Result |= ConstructGlobalVariableDIE(cast<GlobalVariable>(*UUI));
+  // Process all compile units.
+  unsigned PrevOffset = 0;
 
-  return Result;
+  for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) {
+    CompileUnit *Unit = CompileUnits[i];
+    CompileUnitOffsets[Unit] = PrevOffset;
+    PrevOffset += SizeAndOffsetDie(Unit->getDie(), Offset, true)
+      + sizeof(int32_t);  // FIXME - extra pad for gdb bug.
+  }
 }
 
-bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) {
-  DISubprogram SP(GV);
-  CompileUnit *Unit = MainCU;
-  if (!Unit)
-    Unit = &FindCompileUnit(SP.getCompileUnit());
-
-  // Check for pre-existence.
-  DIE *&Slot = Unit->getDieMapSlotFor(GV);
-  if (Slot)
-    return false;
+/// EmitInitial - Emit initial Dwarf declarations.  This is necessary for cc
+/// tools to recognize the object file contains Dwarf information.
+void DwarfDebug::EmitInitial() {
+  // Check to see if we already emitted intial headers.
+  if (didInitial) return;
+  didInitial = true;
 
-  if (!SP.isDefinition())
-    // This is a method declaration which will be handled while constructing
-    // class type.
-    return false;
+  // Dwarf sections base addresses.
+  if (TAI->doesDwarfRequireFrameSection()) {
+    Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
+    EmitLabel("section_debug_frame", 0);
+  }
 
-  DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP);
+  Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
+  EmitLabel("section_info", 0);
+  Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection());
+  EmitLabel("section_abbrev", 0);
+  Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
+  EmitLabel("section_aranges", 0);
 
-  // Add to map.
-  Slot = SubprogramDie;
+  if (TAI->doesSupportMacInfoSection()) {
+    Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());
+    EmitLabel("section_macinfo", 0);
+  }
 
-  // Add to context owner.
-  Unit->getDie()->AddChild(SubprogramDie);
+  Asm->SwitchToDataSection(TAI->getDwarfLineSection());
+  EmitLabel("section_line", 0);
+  Asm->SwitchToDataSection(TAI->getDwarfLocSection());
+  EmitLabel("section_loc", 0);
+  Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection());
+  EmitLabel("section_pubnames", 0);
+  Asm->SwitchToDataSection(TAI->getDwarfStrSection());
+  EmitLabel("section_str", 0);
+  Asm->SwitchToDataSection(TAI->getDwarfRangesSection());
+  EmitLabel("section_ranges", 0);
 
-  // Expose as global.
-  std::string Name;
-  Unit->AddGlobal(SP.getName(Name), SubprogramDie);
-  return true;
+  Asm->SwitchToSection(TAI->getTextSection());
+  EmitLabel("text_begin", 0);
+  Asm->SwitchToSection(TAI->getDataSection());
+  EmitLabel("data_begin", 0);
 }
 
-/// ConstructSubprograms - Create DIEs for each of the externally visible
-/// subprograms. Return true if at least one subprogram DIE is created.
-bool DwarfDebug::ConstructSubprograms() {
-  GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms");
-  if (!Root)
-    return false;
+/// EmitDIE - Recusively Emits a debug information entry.
+///
+void DwarfDebug::EmitDIE(DIE *Die) {
+  // Get the abbreviation for this DIE.
+  unsigned AbbrevNumber = Die->getAbbrevNumber();
+  const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
 
-  assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
-         "Malformed subprogram descriptor anchor type");
-  Constant *RootC = cast<Constant>(*Root->use_begin());
-  assert(RootC->hasNUsesOrMore(1) &&
-         "Malformed subprogram descriptor anchor type");
+  Asm->EOL();
 
-  bool Result = false;
-  for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
-       UI != UE; ++UI)
-    for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
-         UUI != UUE; ++UUI)
-      Result |= ConstructSubprogram(cast<GlobalVariable>(*UUI));
+  // Emit the code (index) for the abbreviation.
+  Asm->EmitULEB128Bytes(AbbrevNumber);
 
-  return Result;
-}
+  if (Asm->isVerbose())
+    Asm->EOL(std::string("Abbrev [" +
+                         utostr(AbbrevNumber) +
+                         "] 0x" + utohexstr(Die->getOffset()) +
+                         ":0x" + utohexstr(Die->getSize()) + " " +
+                         dwarf::TagString(Abbrev->getTag())));
+  else
+    Asm->EOL();
 
-/// SetDebugInfo - Create global DIEs and emit initial debug info sections.
-/// This is inovked by the target AsmPrinter.
-void DwarfDebug::SetDebugInfo(MachineModuleInfo *mmi) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  SmallVector<DIEValue*, 32> &Values = Die->getValues();
+  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
 
-  // Create all the compile unit DIEs.
-  ConstructCompileUnits();
+  // Emit the DIE attribute values.
+  for (unsigned i = 0, N = Values.size(); i < N; ++i) {
+    unsigned Attr = AbbrevData[i].getAttribute();
+    unsigned Form = AbbrevData[i].getForm();
+    assert(Form && "Too many attributes for DIE (check abbreviation)");
 
-  if (CompileUnits.empty()) {
-    if (TimePassesIsEnabled)
-      DebugTimer->stopTimer();
+    switch (Attr) {
+    case dwarf::DW_AT_sibling:
+      Asm->EmitInt32(Die->SiblingOffset());
+      break;
+    case dwarf::DW_AT_abstract_origin: {
+      DIEEntry *E = cast<DIEEntry>(Values[i]);
+      DIE *Origin = E->getEntry();
+      unsigned Addr =
+        CompileUnitOffsets[Die->getAbstractCompileUnit()] +
+        Origin->getOffset();
 
-    return;
-  }
+      Asm->EmitInt32(Addr);
+      break;
+    }
+    default:
+      // Emit an attribute using the defined form.
+      Values[i]->EmitValue(this, Form);
+      break;
+    }
 
-  // Create DIEs for each of the externally visible global variables.
-  bool globalDIEs = ConstructGlobalVariableDIEs();
+    Asm->EOL(dwarf::AttributeString(Attr));
+  }
 
-  // Create DIEs for each of the externally visible subprograms.
-  bool subprogramDIEs = ConstructSubprograms();
+  // Emit the DIE children if any.
+  if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
+    const std::vector<DIE *> &Children = Die->getChildren();
 
-  // If there is not any debug info available for any global variables and any
-  // subprograms then there is not any debug info to emit.
-  if (!globalDIEs && !subprogramDIEs) {
-    if (TimePassesIsEnabled)
-      DebugTimer->stopTimer();
+    for (unsigned j = 0, M = Children.size(); j < M; ++j)
+      EmitDIE(Children[j]);
 
-    return;
+    Asm->EmitInt8(0); Asm->EOL("End Of Children Mark");
   }
+}
 
-  MMI = mmi;
-  shouldEmit = true;
-  MMI->setDebugInfoAvailability(true);
+/// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section.
+///
+void DwarfDebug::EmitDebugInfoPerCU(CompileUnit *Unit) {
+  DIE *Die = Unit->getDie();
+
+  // Emit the compile units header.
+  EmitLabel("info_begin", Unit->getID());
+
+  // Emit size of content not including length itself
+  unsigned ContentSize = Die->getSize() +
+    sizeof(int16_t) + // DWARF version number
+    sizeof(int32_t) + // Offset Into Abbrev. Section
+    sizeof(int8_t) +  // Pointer Size (in bytes)
+    sizeof(int32_t);  // FIXME - extra pad for gdb bug.
+
+  Asm->EmitInt32(ContentSize);  Asm->EOL("Length of Compilation Unit Info");
+  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
+  EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false);
+  Asm->EOL("Offset Into Abbrev. Section");
+  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
+
+  EmitDIE(Die);
+  // FIXME - extra padding for gdb bug.
+  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
+  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
+  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
+  Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
+  EmitLabel("info_end", Unit->getID());
+
+  Asm->EOL();
+}
 
-  // Prime section data.
-  SectionMap.insert(TAI->getTextSection());
+void DwarfDebug::EmitDebugInfo() {
+  // Start debug info section.
+  Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
 
-  // Print out .file directives to specify files for .loc directives. These are
-  // printed out early so that they precede any .loc directives.
-  if (TAI->hasDotLocAndDotFile()) {
-    for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) {
-      // Remember source id starts at 1.
-      std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i);
-      sys::Path FullPath(getSourceDirectoryName(Id.first));
-      bool AppendOk =
-        FullPath.appendComponent(getSourceFileName(Id.second));
-      assert(AppendOk && "Could not append filename to directory!");
-      AppendOk = false;
-      Asm->EmitFile(i, FullPath.toString());
-      Asm->EOL();
-    }
+  if (MainCU) {
+    EmitDebugInfoPerCU(MainCU);
+    return;
   }
 
-  // Emit initial sections
-  EmitInitial();
-
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i)
+    EmitDebugInfoPerCU(CompileUnits[i]);
 }
 
-/// EndModule - Emit all Dwarf sections that should come after the content.
+/// EmitAbbreviations - Emit the abbreviation section.
 ///
-void DwarfDebug::EndModule() {
-  if (!ShouldEmitDwarfDebug())
-    return;
+void DwarfDebug::EmitAbbreviations() const {
+  // Check to see if it is worth the effort.
+  if (!Abbreviations.empty()) {
+    // Start the debug abbrev section.
+    Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection());
 
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+    EmitLabel("abbrev_begin", 0);
 
-  // Standard sections final addresses.
-  Asm->SwitchToSection(TAI->getTextSection());
-  EmitLabel("text_end", 0);
-  Asm->SwitchToSection(TAI->getDataSection());
-  EmitLabel("data_end", 0);
+    // For each abbrevation.
+    for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
+      // Get abbreviation data
+      const DIEAbbrev *Abbrev = Abbreviations[i];
 
-  // End text sections.
-  for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
-    Asm->SwitchToSection(SectionMap[i]);
-    EmitLabel("section_end", i);
-  }
+      // Emit the abbrevations code (base 1 index.)
+      Asm->EmitULEB128Bytes(Abbrev->getNumber());
+      Asm->EOL("Abbreviation Code");
 
-  // Emit common frame information.
-  EmitCommonDebugFrame();
+      // Emit the abbreviations data.
+      Abbrev->Emit(Asm);
 
-  // Emit function debug frame information
-  for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
-         E = DebugFrames.end(); I != E; ++I)
-    EmitFunctionDebugFrame(*I);
+      Asm->EOL();
+    }
 
-  // Compute DIE offsets and sizes.
-  SizeAndOffsets();
+    // Mark end of abbreviations.
+    Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
 
-  // Emit all the DIEs into a debug info section
-  EmitDebugInfo();
+    EmitLabel("abbrev_end", 0);
+    Asm->EOL();
+  }
+}
 
-  // Corresponding abbreviations into a abbrev section.
-  EmitAbbreviations();
+/// EmitEndOfLineMatrix - Emit the last address of the section and the end of
+/// the line matrix.
+///
+void DwarfDebug::EmitEndOfLineMatrix(unsigned SectionEnd) {
+  // Define last address of section.
+  Asm->EmitInt8(0); Asm->EOL("Extended Op");
+  Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
+  Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
+  EmitReference("section_end", SectionEnd); Asm->EOL("Section end label");
 
-  // Emit source line correspondence into a debug line section.
-  EmitDebugLines();
+  // Mark end of matrix.
+  Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence");
+  Asm->EmitULEB128Bytes(1); Asm->EOL();
+  Asm->EmitInt8(1); Asm->EOL();
+}
 
-  // Emit info into a debug pubnames section.
-  EmitDebugPubNames();
+/// EmitDebugLines - Emit source line information.
+///
+void DwarfDebug::EmitDebugLines() {
+  // If the target is using .loc/.file, the assembler will be emitting the
+  // .debug_line table automatically.
+  if (TAI->hasDotLocAndDotFile())
+    return;
 
-  // Emit info into a debug str section.
-  EmitDebugStr();
+  // Minimum line delta, thus ranging from -10..(255-10).
+  const int MinLineDelta = -(dwarf::DW_LNS_fixed_advance_pc + 1);
+  // Maximum line delta, thus ranging from -10..(255-10).
+  const int MaxLineDelta = 255 + MinLineDelta;
 
-  // Emit info into a debug loc section.
-  EmitDebugLoc();
+  // Start the dwarf line section.
+  Asm->SwitchToDataSection(TAI->getDwarfLineSection());
 
-  // Emit info into a debug aranges section.
-  EmitDebugARanges();
+  // Construct the section header.
+  EmitDifference("line_end", 0, "line_begin", 0, true);
+  Asm->EOL("Length of Source Line Info");
+  EmitLabel("line_begin", 0);
 
-  // Emit info into a debug ranges section.
-  EmitDebugRanges();
+  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
 
-  // Emit info into a debug macinfo section.
-  EmitDebugMacInfo();
+  EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true);
+  Asm->EOL("Prolog Length");
+  EmitLabel("line_prolog_begin", 0);
 
-  // Emit inline info.
-  EmitDebugInlineInfo();
+  Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length");
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
-}
+  Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag");
 
-/// BeginFunction - Gather pre-function debug information.  Assumes being
-/// emitted immediately after the function entry point.
-void DwarfDebug::BeginFunction(MachineFunction *MF) {
-  this->MF = MF;
+  Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)");
 
-  if (!ShouldEmitDwarfDebug()) return;
+  Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)");
 
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base");
 
-  // Begin accumulating function debug information.
-  MMI->BeginFunction(MF);
+  // Line number standard opcode encodings argument count
+  Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count");
+  Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count");
+  Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count");
+  Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count");
+  Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count");
+  Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count");
+  Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count");
+  Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count");
+  Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count");
 
-  // Assumes in correct section after the entry point.
-  EmitLabel("func_begin", ++SubprogramCount);
+  // Emit directories.
+  for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
+    Asm->EmitString(getSourceDirectoryName(DI));
+    Asm->EOL("Directory");
+  }
 
-  // Emit label for the implicitly defined dbg.stoppoint at the start of the
-  // function.
-  DebugLoc FDL = MF->getDefaultDebugLoc();
-  if (!FDL.isUnknown()) {
-    DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
-    unsigned LabelID = RecordSourceLine(DLT.Line, DLT.Col,
-                                        DICompileUnit(DLT.CompileUnit));
-    Asm->printLabel(LabelID);
+  Asm->EmitInt8(0); Asm->EOL("End of directories");
+
+  // Emit files.
+  for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
+    // Remember source id starts at 1.
+    std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI);
+    Asm->EmitString(getSourceFileName(Id.second));
+    Asm->EOL("Source");
+    Asm->EmitULEB128Bytes(Id.first);
+    Asm->EOL("Directory #");
+    Asm->EmitULEB128Bytes(0);
+    Asm->EOL("Mod date");
+    Asm->EmitULEB128Bytes(0);
+    Asm->EOL("File size");
   }
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
-}
+  Asm->EmitInt8(0); Asm->EOL("End of files");
 
-/// EndFunction - Gather and emit post-function debug information.
-///
-void DwarfDebug::EndFunction(MachineFunction *MF) {
-  if (!ShouldEmitDwarfDebug()) return;
+  EmitLabel("line_prolog_end", 0);
 
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  // A sequence for each text section.
+  unsigned SecSrcLinesSize = SectionSourceLines.size();
 
-  // Define end label for subprogram.
-  EmitLabel("func_end", SubprogramCount);
+  for (unsigned j = 0; j < SecSrcLinesSize; ++j) {
+    // Isolate current sections line info.
+    const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
 
-  // Get function line info.
-  if (!Lines.empty()) {
-    // Get section line info.
-    unsigned ID = SectionMap.insert(Asm->CurrentSection_);
-    if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
-    std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
-    // Append the function info to section info.
-    SectionLineInfos.insert(SectionLineInfos.end(),
-                            Lines.begin(), Lines.end());
-  }
+    if (Asm->isVerbose()) {
+      const Section* S = SectionMap[j + 1];
+      O << '\t' << TAI->getCommentString() << " Section"
+        << S->getName() << '\n';
+    } else {
+      Asm->EOL();
+    }
 
-  // Construct the DbgScope for abstract instances.
-  for (SmallVector<DbgScope *, 32>::iterator
-         I = AbstractInstanceRootList.begin(),
-         E = AbstractInstanceRootList.end(); I != E; ++I)
-    ConstructAbstractDbgScope(*I);
+    // Dwarf assumes we start with first line of first source file.
+    unsigned Source = 1;
+    unsigned Line = 1;
 
-  // Construct scopes for subprogram.
-  if (FunctionDbgScope)
-    ConstructFunctionDbgScope(FunctionDbgScope);
-  else
-    // FIXME: This is wrong. We are essentially getting past a problem with
-    // debug information not being able to handle unreachable blocks that have
-    // debug information in them. In particular, those unreachable blocks that
-    // have "region end" info in them. That situation results in the "root
-    // scope" not being created. If that's the case, then emit a "default"
-    // scope, i.e., one that encompasses the whole function. This isn't
-    // desirable. And a better way of handling this (and all of the debugging
-    // information) needs to be explored.
-    ConstructDefaultDbgScope(MF);
+    // Construct rows of the address, source, line, column matrix.
+    for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
+      const SrcLineInfo &LineInfo = LineInfos[i];
+      unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID());
+      if (!LabelID) continue;
+
+      if (!Asm->isVerbose())
+        Asm->EOL();
+      else {
+        std::pair<unsigned, unsigned> SourceID =
+          getSourceDirectoryAndFileIds(LineInfo.getSourceID());
+        O << '\t' << TAI->getCommentString() << ' '
+          << getSourceDirectoryName(SourceID.first) << ' '
+          << getSourceFileName(SourceID.second)
+          <<" :" << utostr_32(LineInfo.getLine()) << '\n';
+      }
 
-  DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
-                                               MMI->getFrameMoves()));
+      // Define the line address.
+      Asm->EmitInt8(0); Asm->EOL("Extended Op");
+      Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
+      Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
+      EmitReference("label",  LabelID); Asm->EOL("Location label");
 
-  // Clear debug info
-  if (FunctionDbgScope) {
-    delete FunctionDbgScope;
-    DbgScopeMap.clear();
-    DbgAbstractScopeMap.clear();
-    DbgConcreteScopeMap.clear();
-    InlinedVariableScopes.clear();
-    FunctionDbgScope = NULL;
-    LexicalScopeStack.clear();
-    AbstractInstanceRootList.clear();
-  }
+      // If change of source, then switch to the new source.
+      if (Source != LineInfo.getSourceID()) {
+        Source = LineInfo.getSourceID();
+        Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file");
+        Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source");
+      }
 
-  Lines.clear();
+      // If change of line.
+      if (Line != LineInfo.getLine()) {
+        // Determine offset.
+        int Offset = LineInfo.getLine() - Line;
+        int Delta = Offset - MinLineDelta;
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
-}
+        // Update line.
+        Line = LineInfo.getLine();
 
-/// RecordSourceLine - Records location information and associates it with a
-/// label. Returns a unique label ID used to generate a label and provide
-/// correspondence to the source line list.
-unsigned DwarfDebug::RecordSourceLine(Value *V, unsigned Line, unsigned Col) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+        // If delta is small enough and in range...
+        if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
+          // ... then use fast opcode.
+          Asm->EmitInt8(Delta - MinLineDelta); Asm->EOL("Line Delta");
+        } else {
+          // ... otherwise use long hand.
+          Asm->EmitInt8(dwarf::DW_LNS_advance_line);
+          Asm->EOL("DW_LNS_advance_line");
+          Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset");
+          Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
+        }
+      } else {
+        // Copy the previous row (different address or source)
+        Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
+      }
+    }
 
-  CompileUnit *Unit = CompileUnitMap[V];
-  assert(Unit && "Unable to find CompileUnit");
-  unsigned ID = MMI->NextLabelID();
-  Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID));
+    EmitEndOfLineMatrix(j + 1);
+  }
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  if (SecSrcLinesSize == 0)
+    // Because we're emitting a debug_line section, we still need a line
+    // table. The linker and friends expect it to exist. If there's nothing to
+    // put into it, emit an empty table.
+    EmitEndOfLineMatrix(1);
 
-  return ID;
+  EmitLabel("line_end", 0);
+  Asm->EOL();
 }
 
-/// RecordSourceLine - Records location information and associates it with a
-/// label. Returns a unique label ID used to generate a label and provide
-/// correspondence to the source line list.
-unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col,
-                                      DICompileUnit CU) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+/// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
+///
+void DwarfDebug::EmitCommonDebugFrame() {
+  if (!TAI->doesDwarfRequireFrameSection())
+    return;
 
-  std::string Dir, Fn;
-  unsigned Src = GetOrCreateSourceID(CU.getDirectory(Dir),
-                                     CU.getFilename(Fn));
-  unsigned ID = MMI->NextLabelID();
-  Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
+  int stackGrowth =
+    Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
+      TargetFrameInfo::StackGrowsUp ?
+    TD->getPointerSize() : -TD->getPointerSize();
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  // Start the dwarf frame section.
+  Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
 
-  return ID;
-}
+  EmitLabel("debug_frame_common", 0);
+  EmitDifference("debug_frame_common_end", 0,
+                 "debug_frame_common_begin", 0, true);
+  Asm->EOL("Length of Common Information Entry");
 
-/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
-/// timed. 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(const std::string &DirName,
-                                         const std::string &FileName) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  EmitLabel("debug_frame_common_begin", 0);
+  Asm->EmitInt32((int)dwarf::DW_CIE_ID);
+  Asm->EOL("CIE Identifier Tag");
+  Asm->EmitInt8(dwarf::DW_CIE_VERSION);
+  Asm->EOL("CIE Version");
+  Asm->EmitString("");
+  Asm->EOL("CIE Augmentation");
+  Asm->EmitULEB128Bytes(1);
+  Asm->EOL("CIE Code Alignment Factor");
+  Asm->EmitSLEB128Bytes(stackGrowth);
+  Asm->EOL("CIE Data Alignment Factor");
+  Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
+  Asm->EOL("CIE RA Column");
 
-  unsigned SrcId = GetOrCreateSourceID(DirName, FileName);
+  std::vector<MachineMove> Moves;
+  RI->getInitialFrameState(Moves);
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  EmitFrameMoves(NULL, 0, Moves, false);
 
-  return SrcId;
-}
+  Asm->EmitAlignment(2, 0, 0, false);
+  EmitLabel("debug_frame_common_end", 0);
 
-/// RecordRegionStart - Indicate the start of a region.
-unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  Asm->EOL();
+}
 
-  DbgScope *Scope = getOrCreateScope(V);
-  unsigned ID = MMI->NextLabelID();
-  if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
-  LexicalScopeStack.push_back(Scope);
+/// EmitFunctionDebugFrame - Emit per function frame info into a debug frame
+/// section.
+void
+DwarfDebug::EmitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
+  if (!TAI->doesDwarfRequireFrameSection())
+    return;
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  // Start the dwarf frame section.
+  Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
 
-  return ID;
-}
+  EmitDifference("debug_frame_end", DebugFrameInfo.Number,
+                 "debug_frame_begin", DebugFrameInfo.Number, true);
+  Asm->EOL("Length of Frame Information Entry");
 
-/// RecordRegionEnd - Indicate the end of a region.
-unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
 
-  DbgScope *Scope = getOrCreateScope(V);
-  unsigned ID = MMI->NextLabelID();
-  Scope->setEndLabelID(ID);
-  if (LexicalScopeStack.size() != 0)
-    LexicalScopeStack.pop_back();
+  EmitSectionOffset("debug_frame_common", "section_debug_frame",
+                    0, 0, true, false);
+  Asm->EOL("FDE CIE offset");
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  EmitReference("func_begin", DebugFrameInfo.Number);
+  Asm->EOL("FDE initial location");
+  EmitDifference("func_end", DebugFrameInfo.Number,
+                 "func_begin", DebugFrameInfo.Number);
+  Asm->EOL("FDE address range");
 
-  return ID;
-}
+  EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
+                 false);
 
-/// RecordVariable - Indicate the declaration of a local variable.
-void DwarfDebug::RecordVariable(GlobalVariable *GV, unsigned FrameIndex,
-                                const MachineInstr *MI) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  Asm->EmitAlignment(2, 0, 0, false);
+  EmitLabel("debug_frame_end", DebugFrameInfo.Number);
 
-  DIDescriptor Desc(GV);
-  DbgScope *Scope = NULL;
-  bool InlinedFnVar = false;
+  Asm->EOL();
+}
 
-  if (Desc.getTag() == dwarf::DW_TAG_variable) {
-    // GV is a global variable.
-    DIGlobalVariable DG(GV);
-    Scope = getOrCreateScope(DG.getContext().getGV());
-  } else {
-    DenseMap<const MachineInstr *, DbgScope *>::iterator
-      SI = InlinedVariableScopes.find(MI);
+void DwarfDebug::EmitDebugPubNamesPerCU(CompileUnit *Unit) {
+  EmitDifference("pubnames_end", Unit->getID(),
+                 "pubnames_begin", Unit->getID(), true);
+  Asm->EOL("Length of Public Names Info");
 
-    if (SI != InlinedVariableScopes.end()) {
-      // or GV is an inlined local variable.
-      Scope = SI->second;
-    } else {
-      DIVariable DV(GV);
-      GlobalVariable *V = DV.getContext().getGV();
+  EmitLabel("pubnames_begin", Unit->getID());
 
-      // FIXME: The code that checks for the inlined local variable is a hack!
-      DenseMap<const GlobalVariable *, DbgScope *>::iterator
-        AI = AbstractInstanceRootMap.find(V);
+  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
 
-      if (AI != AbstractInstanceRootMap.end()) {
-        // This method is called each time a DECLARE node is encountered. For an
-        // inlined function, this could be many, many times. We don't want to
-        // re-add variables to that DIE for each time. We just want to add them
-        // once. Check to make sure that we haven't added them already.
-        DenseMap<const GlobalVariable *,
-          SmallSet<const GlobalVariable *, 32> >::iterator
-          IP = InlinedParamMap.find(V);
+  EmitSectionOffset("info_begin", "section_info",
+                    Unit->getID(), 0, true, false);
+  Asm->EOL("Offset of Compilation Unit Info");
 
-        if (IP != InlinedParamMap.end() && IP->second.count(GV) > 0) {
-          if (TimePassesIsEnabled)
-            DebugTimer->stopTimer();
-          return;
-        }
+  EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),
+                 true);
+  Asm->EOL("Compilation Unit Length");
 
-        // or GV is an inlined local variable.
-        Scope = AI->second;
-        InlinedParamMap[V].insert(GV);
-        InlinedFnVar = true;
-      } else {
-        // or GV is a local variable.
-        Scope = getOrCreateScope(V);
-      }
-    }
+  StringMap<DIE*> &Globals = Unit->getGlobals();
+  for (StringMap<DIE*>::const_iterator
+         GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
+    const char *Name = GI->getKeyData();
+    DIE * Entity = GI->second;
+
+    Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
+    Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
   }
 
-  assert(Scope && "Unable to find the variable's scope");
-  DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex, InlinedFnVar);
-  Scope->AddVariable(DV);
+  Asm->EmitInt32(0); Asm->EOL("End Mark");
+  EmitLabel("pubnames_end", Unit->getID());
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  Asm->EOL();
 }
 
-//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
-                                          unsigned Line, unsigned Col) {
-  unsigned LabelID = MMI->NextLabelID();
+/// EmitDebugPubNames - Emit visible names into a debug pubnames section.
+///
+void DwarfDebug::EmitDebugPubNames() {
+  // Start the dwarf pubnames section.
+  Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection());
 
-  if (!TAI->doesDwarfUsesInlineInfoSection())
-    return LabelID;
+  if (MainCU) {
+    EmitDebugPubNamesPerCU(MainCU);
+    return;
+  }
 
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i)
+    EmitDebugPubNamesPerCU(CompileUnits[i]);
+}
 
-  GlobalVariable *GV = SP.getGV();
-  DenseMap<const GlobalVariable *, DbgScope *>::iterator
-    II = AbstractInstanceRootMap.find(GV);
+/// EmitDebugStr - Emit visible names into a debug str section.
+///
+void DwarfDebug::EmitDebugStr() {
+  // Check to see if it is worth the effort.
+  if (!StringPool.empty()) {
+    // Start the dwarf str section.
+    Asm->SwitchToDataSection(TAI->getDwarfStrSection());
 
-  if (II == AbstractInstanceRootMap.end()) {
-    // Create an abstract instance entry for this inlined function if it doesn't
-    // already exist.
-    DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV));
+    // For each of strings in the string pool.
+    for (unsigned StringID = 1, N = StringPool.size();
+         StringID <= N; ++StringID) {
+      // Emit a label for reference from debug information entries.
+      EmitLabel("string", StringID);
 
-    // Get the compile unit context.
-    CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
-    DIE *SPDie = Unit->getDieMapSlotFor(GV);
-    if (!SPDie)
-      SPDie = CreateSubprogramDIE(Unit, SP, false, true);
+      // Emit the string itself.
+      const std::string &String = StringPool[StringID];
+      Asm->EmitString(String); Asm->EOL();
+    }
 
-    // Mark as being inlined. This makes this subprogram entry an abstract
-    // instance root.
-    // FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
-    // that it's defined. That probably won't change in the future. However,
-    // this could be more elegant.
-    AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
+    Asm->EOL();
+  }
+}
 
-    // Keep track of the abstract scope for this function.
-    DbgAbstractScopeMap[GV] = Scope;
+/// EmitDebugLoc - Emit visible names into a debug loc section.
+///
+void DwarfDebug::EmitDebugLoc() {
+  // Start the dwarf loc section.
+  Asm->SwitchToDataSection(TAI->getDwarfLocSection());
+  Asm->EOL();
+}
 
-    AbstractInstanceRootMap[GV] = Scope;
-    AbstractInstanceRootList.push_back(Scope);
-  }
+/// EmitDebugARanges - Emit visible names into a debug aranges section.
+///
+void DwarfDebug::EmitDebugARanges() {
+  // Start the dwarf aranges section.
+  Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
 
-  // Create a concrete inlined instance for this inlined function.
-  DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV));
-  DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
-  CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
-  ScopeDie->setAbstractCompileUnit(Unit);
+  // FIXME - Mock up
+#if 0
+  CompileUnit *Unit = GetBaseCompileUnit();
 
-  DIE *Origin = Unit->getDieMapSlotFor(GV);
-  AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
-              dwarf::DW_FORM_ref4, Origin);
-  AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, Unit->getID());
-  AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
-  AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
+  // Don't include size of length
+  Asm->EmitInt32(0x1c); Asm->EOL("Length of Address Ranges Info");
 
-  ConcreteScope->setDie(ScopeDie);
-  ConcreteScope->setStartLabelID(LabelID);
-  MMI->RecordUsedDbgLabel(LabelID);
+  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
 
-  LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
+  EmitReference("info_begin", Unit->getID());
+  Asm->EOL("Offset of Compilation Unit Info");
 
-  // Keep track of the concrete scope that's inlined into this function.
-  DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
-    SI = DbgConcreteScopeMap.find(GV);
+  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address");
 
-  if (SI == DbgConcreteScopeMap.end())
-    DbgConcreteScopeMap[GV].push_back(ConcreteScope);
-  else
-    SI->second.push_back(ConcreteScope);
+  Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor");
 
-  // Track the start label for this inlined function.
-  DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
-    I = InlineInfo.find(GV);
+  Asm->EmitInt16(0);  Asm->EOL("Pad (1)");
+  Asm->EmitInt16(0);  Asm->EOL("Pad (2)");
 
-  if (I == InlineInfo.end())
-    InlineInfo[GV].push_back(LabelID);
-  else
-    I->second.push_back(LabelID);
+  // Range 1
+  EmitReference("text_begin", 0); Asm->EOL("Address");
+  EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length");
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  Asm->EmitInt32(0); Asm->EOL("EOM (1)");
+  Asm->EmitInt32(0); Asm->EOL("EOM (2)");
+#endif
 
-  return LabelID;
+  Asm->EOL();
 }
 
-/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
+/// EmitDebugRanges - Emit visible names into a debug ranges section.
+///
+void DwarfDebug::EmitDebugRanges() {
+  // Start the dwarf ranges section.
+  Asm->SwitchToDataSection(TAI->getDwarfRangesSection());
+  Asm->EOL();
+}
+
+/// EmitDebugMacInfo - Emit visible names into a debug macinfo section.
+///
+void DwarfDebug::EmitDebugMacInfo() {
+  if (TAI->doesSupportMacInfoSection()) {
+    // Start the dwarf macinfo section.
+    Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());
+    Asm->EOL();
+  }
+}
+
+/// EmitDebugInlineInfo - Emit inline info using following format.
+/// Section Header:
+/// 1. length of section
+/// 2. Dwarf version number
+/// 3. address size.
+///
+/// Entries (one "entry" for each function that was inlined):
+///
+/// 1. offset into __debug_str section for MIPS linkage name, if exists;
+///   otherwise offset into __debug_str for regular function name.
+/// 2. offset into __debug_str section for regular function name.
+/// 3. an unsigned LEB128 number indicating the number of distinct inlining
+/// instances for the function.
+///
+/// The rest of the entry consists of a {die_offset, low_pc} pair for each
+/// inlined instance; the die_offset points to the inlined_subroutine die in the
+/// __debug_info section, and the low_pc is the starting address for the
+/// inlining instance.
+void DwarfDebug::EmitDebugInlineInfo() {
   if (!TAI->doesDwarfUsesInlineInfoSection())
-    return 0;
+    return;
 
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+  if (!MainCU)
+    return;
 
-  GlobalVariable *GV = SP.getGV();
-  DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
-    I = DbgConcreteScopeMap.find(GV);
+  Asm->SwitchToDataSection(TAI->getDwarfDebugInlineSection());
+  Asm->EOL();
+  EmitDifference("debug_inlined_end", 1,
+                 "debug_inlined_begin", 1, true);
+  Asm->EOL("Length of Debug Inlined Information Entry");
 
-  if (I == DbgConcreteScopeMap.end()) {
-    // FIXME: Can this situation actually happen? And if so, should it?
-    if (TimePassesIsEnabled)
-      DebugTimer->stopTimer();
+  EmitLabel("debug_inlined_begin", 1);
 
-    return 0;
-  }
+  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
+  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
 
-  SmallVector<DbgScope *, 8> &Scopes = I->second;
-  assert(!Scopes.empty() && "We should have at least one debug scope!");
-  DbgScope *Scope = Scopes.back(); Scopes.pop_back();
-  unsigned ID = MMI->NextLabelID();
-  MMI->RecordUsedDbgLabel(ID);
-  Scope->setEndLabelID(ID);
+  for (DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
+         I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
+    GlobalVariable *GV = I->first;
+    SmallVector<unsigned, 4> &Labels = I->second;
+    DISubprogram SP(GV);
+    std::string Name;
+    std::string LName;
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+    SP.getLinkageName(LName);
+    SP.getName(Name);
 
-  return ID;
-}
+    Asm->EmitString(LName.empty() ? Name : LName);
+    Asm->EOL("MIPS linkage name");
 
-/// RecordVariableScope - Record scope for the variable declared by
-/// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. Record scopes
-/// for only inlined subroutine variables. Other variables's scopes are
-/// determined during RecordVariable().
-void DwarfDebug::RecordVariableScope(DIVariable &DV,
-                                     const MachineInstr *DeclareMI) {
-  if (TimePassesIsEnabled)
-    DebugTimer->startTimer();
+    Asm->EmitString(Name); Asm->EOL("Function name");
 
-  DISubprogram SP(DV.getContext().getGV());
+    Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
 
-  if (SP.isNull()) {
-    if (TimePassesIsEnabled)
-      DebugTimer->stopTimer();
+    for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(),
+           LE = Labels.end(); LI != LE; ++LI) {
+      DIE *SP = MainCU->getDieMapSlotFor(GV);
+      Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset");
 
-    return;
-  }
+      if (TD->getPointerSize() == sizeof(int32_t))
+        O << TAI->getData32bitsDirective();
+      else
+        O << TAI->getData64bitsDirective();
 
-  DenseMap<GlobalVariable *, DbgScope *>::iterator
-    I = DbgAbstractScopeMap.find(SP.getGV());
-  if (I != DbgAbstractScopeMap.end())
-    InlinedVariableScopes[DeclareMI] = I->second;
+      PrintLabelName("label", *LI); Asm->EOL("low_pc");
+    }
+  }
 
-  if (TimePassesIsEnabled)
-    DebugTimer->stopTimer();
+  EmitLabel("debug_inlined_end", 1);
+  Asm->EOL();
 }





More information about the llvm-commits mailing list