Skip to content
DwarfDebug.cpp 103 KiB
Newer Older
  DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
  DILocation DL(InlinedAt);
  createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
/// extractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool DwarfDebug::extractScopeInformation() {
  // If scope information was extracted using .dbg intrinsics then there is not
  // any need to extract these information by scanning each instruction.
  if (!DbgScopeMap.empty())
    return false;

  DenseMap<const MachineInstr *, unsigned> MIIndexMap;
  unsigned MIIndex = 0;
  // Scan each instruction and create scopes. First build working set of scopes.
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I) {
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      MIIndexMap[MInsn] = MIIndex++;
      if (DL.isUnknown()) continue;
      DILocation DLT = MF->getDILocation(DL);
      DIScope DLTScope = DLT.getScope();
      // There is no need to create another DIE for compile unit. For all
Jim Grosbach's avatar
Jim Grosbach committed
      // other scopes, create one DbgScope now. This will be translated
      if (DLTScope.isCompileUnit()) continue;
      createDbgScope(DLTScope.getNode(), DLT.getOrigLocation().getNode());
    }
  }


  // Build scope hierarchy using working set of scopes.
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
       I != E; ++I) {
    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
         II != IE; ++II) {
      const MachineInstr *MInsn = II;
      DebugLoc DL = MInsn->getDebugLoc();
      if (DL.isUnknown())  continue;
      DILocation DLT = MF->getDILocation(DL);
      DIScope DLTScope = DLT.getScope();
      // There is no need to create another DIE for compile unit. For all
Jim Grosbach's avatar
Jim Grosbach committed
      // other scopes, create one DbgScope now. This will be translated
      // into a scope DIE at the end.
      if (DLTScope.isCompileUnit()) continue;
      DbgScope *Scope = getUpdatedDbgScope(DLTScope.getNode(), MInsn, 
                                           DLT.getOrigLocation().getNode());
      Scope->setLastInsn(MInsn);
  if (!CurrentFnDbgScope)
    return false;

  CurrentFnDbgScope->fixInstructionMarkers(MIIndexMap);

  // Each scope has first instruction and last instruction to mark beginning
  // and end of a scope respectively. Create an inverse map that list scopes
  // starts (and ends) with an instruction. One instruction may start (or end)
  // multiple scopes. Ignore scopes that are not reachable.
  SmallVector<DbgScope *, 4> WorkList;
  WorkList.push_back(CurrentFnDbgScope);
  while (!WorkList.empty()) {
    DbgScope *S = WorkList.back(); WorkList.pop_back();

    SmallVector<DbgScope *, 4> &Children = S->getScopes();
      for (SmallVector<DbgScope *, 4>::iterator SI = Children.begin(),
             SE = Children.end(); SI != SE; ++SI)
        WorkList.push_back(*SI);

    if (S->isAbstractScope())
      continue;
    const MachineInstr *MI = S->getFirstInsn();
    assert (MI && "DbgScope does not have first instruction!");

    InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI);
    if (IDI != DbgScopeBeginMap.end())
      IDI->second.push_back(S);
    else
      DbgScopeBeginMap[MI].push_back(S);

    MI = S->getLastInsn();
    assert (MI && "DbgScope does not have last instruction!");
    IDI = DbgScopeEndMap.find(MI);
    if (IDI != DbgScopeEndMap.end())
      IDI->second.push_back(S);
    else
      DbgScopeEndMap[MI].push_back(S);
/// beginFunction - Gather pre-function debug information.  Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
  if (!ShouldEmitDwarfDebug()) return;
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  if (!extractScopeInformation())
  // Assumes in correct section after the entry point.
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount));

  // Emit label for the implicitly defined dbg.stoppoint at the start of the
  // function.
  DebugLoc FDL = MF->getDefaultDebugLoc();
  if (!FDL.isUnknown()) {
    DILocation DLT = MF->getDILocation(FDL);
    DISubprogram SP = getDISubprogram(DLT.getScope().getNode());
    if (SP.Verify())
      LabelID = recordSourceLine(SP.getLineNumber(), 0, 
                                 DLT.getScope().getNode());
      LabelID = recordSourceLine(DLT.getLineNumber(), 
                                 DLT.getColumnNumber(), 
                                 DLT.getScope().getNode());
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
  if (!ShouldEmitDwarfDebug()) return;
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  if (CurrentFnDbgScope) {
    // Define end label for subprogram.
Chris Lattner's avatar
Chris Lattner committed
    Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount));
    
    // Get function line info.
    if (!Lines.empty()) {
      // Get section line info.
      unsigned ID = SectionMap.insert(Asm->getCurrentSection());
      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());
    }
    
    // Construct abstract scopes.
    for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
           AE = AbstractScopesList.end(); AI != AE; ++AI)
      constructScopeDIE(*AI);
    
    constructScopeDIE(CurrentFnDbgScope);
    
    DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
                                                 MMI->getFrameMoves()));
  // Clear debug info
  CurrentFnDbgScope = NULL;
  DbgScopeBeginMap.clear();
  DbgScopeEndMap.clear();
  ConcreteScopes.clear();
  AbstractScopesList.clear();
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// 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.
Jim Grosbach's avatar
Jim Grosbach committed
unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col,
Devang Patel's avatar
Devang Patel committed
  if (!MMI)
    return 0;

  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  StringRef Dir;
  StringRef Fn;

  DIDescriptor Scope(S);
  if (Scope.isCompileUnit()) {
    DICompileUnit CU(S);
    Dir = CU.getDirectory();
    Fn = CU.getFilename();
  } else if (Scope.isSubprogram()) {
    DISubprogram SP(S);
    Dir = SP.getDirectory();
    Fn = SP.getFilename();
  } else if (Scope.isLexicalBlock()) {
    DILexicalBlock DB(S);
    Dir = DB.getDirectory();
    Fn = DB.getFilename();
  } else
    assert (0 && "Unexpected scope info");

  unsigned Src = GetOrCreateSourceID(Dir, Fn);
  unsigned ID = MMI->NextLabelID();
  Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// 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();
  unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();

  return SrcId;
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//

/// computeSizeAndOffset - Compute the size and offset of a DIE.
Jim Grosbach's avatar
Jim Grosbach committed
unsigned
DwarfDebug::computeSizeAndOffset(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];

  // Set DIE offset
  Die->setOffset(Offset);

  // Start the size with the size of abbreviation code.
  Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);

  const SmallVector<DIEValue*, 32> &Values = Die->getValues();
  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
  // 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());
  // Size the DIE children if any.
  if (!Children.empty()) {
    assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
           "Children flag not set");
    for (unsigned j = 0, M = Children.size(); j < M; ++j)
      Offset = computeSizeAndOffset(Children[j], Offset, (j + 1) == M);
    // End of children marker.
    Offset += sizeof(int8_t);
  }
  Die->setSize(Offset - Die->getOffset());
  return Offset;
/// computeSizeAndOffsets - Compute the size and offset of all the DIEs.
void DwarfDebug::computeSizeAndOffsets() {
  // 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)
  computeSizeAndOffset(ModuleCU->getCUDie(), Offset, true);
Devang Patel's avatar
Devang Patel committed
  CompileUnitOffsets[ModuleCU] = 0;
/// 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;
  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  // Dwarf sections base addresses.
  if (MAI->doesDwarfRequireFrameSection()) {
    Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection());
Chris Lattner's avatar
Chris Lattner committed
    Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_info"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges"));
  if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
    Asm->OutStreamer.SwitchSection(LineInfoDirective);
Chris Lattner's avatar
Chris Lattner committed
    Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_line"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_loc"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames"));
Devang Patel's avatar
Devang Patel committed
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_str"));
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges"));
  Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("text_begin"));
  Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("data_begin"));
/// 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];
  // Emit the code (index) for the abbreviation.
  if (Asm->VerboseAsm)
    Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
                                Twine::utohexstr(Die->getOffset()) + ":0x" +
                                Twine::utohexstr(Die->getSize()) + " " +
                                dwarf::TagString(Abbrev->getTag()));
  EmitULEB128(AbbrevNumber);
  SmallVector<DIEValue*, 32> &Values = Die->getValues();
  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
  // 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 (Asm->VerboseAsm)
      Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
    
    switch (Attr) {
    case dwarf::DW_AT_sibling:
      Asm->EmitInt32(Die->getSiblingOffset());
      break;
    case dwarf::DW_AT_abstract_origin: {
      DIEEntry *E = cast<DIEEntry>(Values[i]);
      DIE *Origin = E->getEntry();
      unsigned Addr = Origin->getOffset();
      Asm->EmitInt32(Addr);
      break;
    }
    default:
      // Emit an attribute using the defined form.
      Values[i]->EmitValue(this, Form);
      O << "\n"; // REMOVE This once all EmitValue impls emit their own newline.
  // 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)
    Asm->EmitInt8(0); EOL("End Of Children Mark");
/// emitDebugInfo - Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
  // Start debug info section.
  Asm->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfInfoSection());
  DIE *Die = ModuleCU->getCUDie();

  // Emit the compile units header.
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->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);  EOL("Length of Compilation Unit Info");
  Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
  EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"),
                    true, false);
  EOL("Offset Into Abbrev. Section");
  Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
  // FIXME - extra padding for gdb bug.
  Asm->EmitInt8(0); EOL("Extra Pad For GDB");
  Asm->EmitInt8(0); EOL("Extra Pad For GDB");
  Asm->EmitInt8(0); EOL("Extra Pad For GDB");
  Asm->EmitInt8(0); EOL("Extra Pad For GDB");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->getID()));
/// 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->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfAbbrevSection());
Chris Lattner's avatar
Chris Lattner committed
    Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_begin"));
    // 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.)
      EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
      // Emit the abbreviations data.
    // Mark end of abbreviations.
Chris Lattner's avatar
Chris Lattner committed
    Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_end"));
/// 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); EOL("Extended Op");
  Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size");
  Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address");
  EmitReference(getDWLabel("section_end", SectionEnd));
  EOL("Section end label");
  // Mark end of matrix.
  Asm->EmitInt8(0); EOL("DW_LNE_end_sequence");
/// 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.
  // 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->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfLineSection());
  // Construct the section header.
Chris Lattner's avatar
Chris Lattner committed
  EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true);
  EOL("Length of Source Line Info");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("line_begin"));
  Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
Chris Lattner's avatar
Chris Lattner committed
  EmitDifference(getTempLabel("line_prolog_end"),
                 getTempLabel("line_prolog_begin"), true);
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin"));
  Asm->EmitInt8(1); EOL("Minimum Instruction Length");
  Asm->EmitInt8(1); EOL("Default is_stmt_start flag");
  Asm->EmitInt8(MinLineDelta); EOL("Line Base Value (Special Opcodes)");
  Asm->EmitInt8(MaxLineDelta); EOL("Line Range Value (Special Opcodes)");
  Asm->EmitInt8(-MinLineDelta); EOL("Special Opcode Base");
  // Line number standard opcode encodings argument count
  Asm->EmitInt8(0); EOL("DW_LNS_copy arg count");
  Asm->EmitInt8(1); EOL("DW_LNS_advance_pc arg count");
  Asm->EmitInt8(1); EOL("DW_LNS_advance_line arg count");
  Asm->EmitInt8(1); EOL("DW_LNS_set_file arg count");
  Asm->EmitInt8(1); EOL("DW_LNS_set_column arg count");
  Asm->EmitInt8(0); EOL("DW_LNS_negate_stmt arg count");
  Asm->EmitInt8(0); EOL("DW_LNS_set_basic_block arg count");
  Asm->EmitInt8(0); EOL("DW_LNS_const_add_pc arg count");
  Asm->EmitInt8(1); EOL("DW_LNS_fixed_advance_pc arg count");
  // Emit directories.
  for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
    const std::string &Dir = getSourceDirectoryName(DI);
    if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory");
    Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0);
  Asm->EmitInt8(0); 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);
    const std::string &FN = getSourceFileName(Id.second);
    if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source");
    Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0);
    
    EmitULEB128(Id.first, "Directory #");
    EmitULEB128(0, "Mod date");
    EmitULEB128(0, "File size");
  Asm->EmitInt8(0); EOL("End of files");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end"));
  // A sequence for each text section.
  unsigned SecSrcLinesSize = SectionSourceLines.size();
  for (unsigned j = 0; j < SecSrcLinesSize; ++j) {
    // Isolate current sections line info.
    const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
      const MCSection *S = SectionMap[j + 1];
      O << '\t' << MAI->getCommentString() << " Section"
        << S->getName() << '\n';
    // Dwarf assumes we start with first line of first source file.
    unsigned Source = 1;
    unsigned Line = 1;
    // 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 (LineInfo.getLine() == 0) continue;

      if (!Asm->isVerbose())
      else {
        std::pair<unsigned, unsigned> SourceID =
          getSourceDirectoryAndFileIds(LineInfo.getSourceID());
        O << '\t' << MAI->getCommentString() << ' '
          << getSourceDirectoryName(SourceID.first) << '/'
          << getSourceFileName(SourceID.second)
          << ':' << utostr_32(LineInfo.getLine()) << '\n';
      // Define the line address.
      Asm->EmitInt8(0); EOL("Extended Op");
      Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size");
      Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address");
      EmitReference(getDWLabel("label", LabelID)); EOL("Location label");
      // If change of source, then switch to the new source.
      if (Source != LineInfo.getSourceID()) {
        Source = LineInfo.getSourceID();
        Asm->EmitInt8(dwarf::DW_LNS_set_file); EOL("DW_LNS_set_file");
        EmitULEB128(Source, "New Source");
      // If change of line.
      if (Line != LineInfo.getLine()) {
        // Determine offset.
        int Offset = LineInfo.getLine() - Line;
        int Delta = Offset - MinLineDelta;
        // Update line.
        Line = LineInfo.getLine();
        // If delta is small enough and in range...
        if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
          // ... then use fast opcode.
          Asm->EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
        } else {
          // ... otherwise use long hand.
          Asm->EmitInt8(dwarf::DW_LNS_advance_line);
          EmitSLEB128(Offset, "Line Offset");
          Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
        }
      } else {
        // Copy the previous row (different address or source)
        Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
    emitEndOfLineMatrix(j + 1);
  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.
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("line_end"));
/// emitCommonDebugFrame - Emit common frame info into a debug frame section.
void DwarfDebug::emitCommonDebugFrame() {
  if (!MAI->doesDwarfRequireFrameSection())
  int stackGrowth =
    Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
      TargetFrameInfo::StackGrowsUp ?
    TD->getPointerSize() : -TD->getPointerSize();
  // Start the dwarf frame section.
  Asm->OutStreamer.SwitchSection(
                              Asm->getObjFileLowering().getDwarfFrameSection());
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common"));
  EmitDifference(getTempLabel("debug_frame_common_end"),
                 getTempLabel("debug_frame_common_begin"), true);
  EOL("Length of Common Information Entry");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin"));
  Asm->EmitInt32((int)dwarf::DW_CIE_ID);
  Asm->EmitInt8(dwarf::DW_CIE_VERSION);
  Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator.
  EmitULEB128(1, "CIE Code Alignment Factor");
  EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
  Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
  std::vector<MachineMove> Moves;
  RI->getInitialFrameState(Moves);
  EmitFrameMoves(NULL, 0, Moves, false);
  Asm->EmitAlignment(2, 0, 0, false);
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end"));
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
  if (!MAI->doesDwarfRequireFrameSection())
  // Start the dwarf frame section.
  Asm->OutStreamer.SwitchSection(
                              Asm->getObjFileLowering().getDwarfFrameSection());
  EmitDifference(getDWLabel("debug_frame_end", DebugFrameInfo.Number),
                 getDWLabel("debug_frame_begin", DebugFrameInfo.Number), true);
  EOL("Length of Frame Information Entry");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_begin",
                                        DebugFrameInfo.Number));
  EmitSectionOffset(getTempLabel("debug_frame_common"),
                    getTempLabel("section_debug_frame"), true, false);
  EmitReference(getDWLabel("func_begin", DebugFrameInfo.Number));
  EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number),
                 getDWLabel("func_begin", DebugFrameInfo.Number));
  EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
                 false);
  Asm->EmitAlignment(2, 0, 0, false);
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_end",
                                        DebugFrameInfo.Number));
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::emitDebugPubNames() {
  // Start the dwarf pubnames section.
  Asm->OutStreamer.SwitchSection(
                          Asm->getObjFileLowering().getDwarfPubNamesSection());

  EmitDifference(getDWLabel("pubnames_end", ModuleCU->getID()),
                 getDWLabel("pubnames_begin", ModuleCU->getID()), true);
  EOL("Length of Public Names Info");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID()));
  Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version");
  EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()), 
                    getTempLabel("section_info"),
                    true, false);
  EOL("Offset of Compilation Unit Info");
  EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
                 getDWLabel("info_begin", ModuleCU->getID()),
  EOL("Compilation Unit Length");
  const StringMap<DIE*> &Globals = ModuleCU->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()); EOL("DIE offset");
    
    if (Asm->VerboseAsm)
      Asm->OutStreamer.AddComment("External Name");
    Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
  Asm->EmitInt32(0); EOL("End Mark");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID()));
Devang Patel's avatar
Devang Patel committed
void DwarfDebug::emitDebugPubTypes() {
  // Start the dwarf pubnames section.
  Asm->OutStreamer.SwitchSection(
                          Asm->getObjFileLowering().getDwarfPubTypesSection());
  EmitDifference(getDWLabel("pubtypes_end", ModuleCU->getID()),
                 getDWLabel("pubtypes_begin", ModuleCU->getID()), true);
  EOL("Length of Public Types Info");
Devang Patel's avatar
Devang Patel committed

Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID()));
Devang Patel's avatar
Devang Patel committed

  if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version");
  Asm->EmitInt16(dwarf::DWARF_VERSION);
Devang Patel's avatar
Devang Patel committed

  EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
                    getTempLabel("section_info"), true, false);
  EOL("Offset of Compilation ModuleCU Info");
Devang Patel's avatar
Devang Patel committed

  EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
                 getDWLabel("info_begin", ModuleCU->getID()),
Devang Patel's avatar
Devang Patel committed
                 true);
  EOL("Compilation ModuleCU Length");
Devang Patel's avatar
Devang Patel committed

  const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes();
  for (StringMap<DIE*>::const_iterator
         GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
    const char *Name = GI->getKeyData();
    DIE * Entity = GI->second;

    if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset");
    Asm->EmitInt32(Entity->getOffset());
    
    if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name");
    Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
Devang Patel's avatar
Devang Patel committed
  }

  Asm->EmitInt32(0); EOL("End Mark");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->getID()));
Devang Patel's avatar
Devang Patel committed
}

/// 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->OutStreamer.SwitchSection(
                                Asm->getObjFileLowering().getDwarfStrSection());
    // 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.
Chris Lattner's avatar
Chris Lattner committed
      Asm->OutStreamer.EmitLabel(getDWLabel("string", StringID));
      // Emit the string itself.
      const std::string &String = StringPool[StringID];
      Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0);
/// emitDebugLoc - Emit visible names into a debug loc section.
void DwarfDebug::emitDebugLoc() {
  // Start the dwarf loc section.
  Asm->OutStreamer.SwitchSection(
                              Asm->getObjFileLowering().getDwarfLocSection());
/// EmitDebugARanges - Emit visible names into a debug aranges section.
///
void DwarfDebug::EmitDebugARanges() {
  // Start the dwarf aranges section.
  Asm->OutStreamer.SwitchSection(
                          Asm->getObjFileLowering().getDwarfARangesSection());
  // FIXME - Mock up
#if 0
  CompileUnit *Unit = GetBaseCompileUnit();
  // Don't include size of length
  Asm->EmitInt32(0x1c); EOL("Length of Address Ranges Info");
  Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
  EmitReference("info_begin", Unit->getID());
  EOL("Offset of Compilation Unit Info");
  Asm->EmitInt8(TD->getPointerSize()); EOL("Size of Address");
  Asm->EmitInt8(0); EOL("Size of Segment Descriptor");
  Asm->EmitInt16(0);  EOL("Pad (1)");
  Asm->EmitInt16(0);  EOL("Pad (2)");
  EmitReference("text_begin", 0); EOL("Address");
  EmitDifference(getTempLabel("text_end"), getTempLabel("text_begin"),
                 true); EOL("Length");
  Asm->EmitInt32(0); EOL("EOM (1)");
  Asm->EmitInt32(0); EOL("EOM (2)");
/// emitDebugRanges - Emit visible names into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
  // Start the dwarf ranges section.
  Asm->OutStreamer.SwitchSection(
                            Asm->getObjFileLowering().getDwarfRangesSection());
/// emitDebugMacInfo - Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
  if (const MCSection *LineInfo =
      Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
    // Start the dwarf macinfo section.
    Asm->OutStreamer.SwitchSection(LineInfo);
/// 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 (!MAI->doesDwarfUsesInlineInfoSection())
Devang Patel's avatar
Devang Patel committed
  if (!ModuleCU)
  Asm->OutStreamer.SwitchSection(
                        Asm->getObjFileLowering().getDwarfDebugInlineSection());
  EmitDifference(getDWLabel("debug_inlined_end", 1),
                 getDWLabel("debug_inlined_begin", 1), true);
  EOL("Length of Debug Inlined Information Entry");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_begin", 1));
  Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
  Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
  for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
         E = InlinedSPNodes.end(); I != E; ++I) {
    MDNode *Node = *I;
    DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
Jim Grosbach's avatar
Jim Grosbach committed
      = InlineInfo.find(Node);
    SmallVector<InlineInfoLabels, 4> &Labels = II->second;
Devang Patel's avatar
Devang Patel committed
    DISubprogram SP(Node);
    StringRef LName = SP.getLinkageName();
    StringRef Name = SP.getName();
    if (LName.empty()) {
      Asm->OutStreamer.EmitBytes(Name, 0);
      Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator.
    } else 
      EmitSectionOffset(getDWLabel("string",
                                   StringPool.idFor(getRealLinkageName(LName))),
                        getTempLabel("section_str"), true);
    EmitSectionOffset(getDWLabel("string", StringPool.idFor(Name)),
                      getTempLabel("section_str"), false, true);
    EmitULEB128(Labels.size(), "Inline count");
    for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
           LE = Labels.end(); LI != LE; ++LI) {
      DIE *SP = LI->second;
      Asm->EmitInt32(SP->getOffset()); EOL("DIE offset");
      if (TD->getPointerSize() == sizeof(int32_t))
        O << MAI->getData32bitsDirective();
        O << MAI->getData64bitsDirective();
      PrintLabelName(getDWLabel("label", LI->first)); EOL("low_pc");
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_end", 1));