Skip to content
DwarfDebug.cpp 98.1 KiB
Newer Older
      if (!DLT.Scope) continue;
      // 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 (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
      createDbgScope(DLT.Scope, DLT.InlinedAtLoc);
    }
  }


  // 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;
      DebugLocTuple DLT = MF->getDebugLocTuple(DL);
      if (!DLT.Scope)  continue;
      // 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 (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
      DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
      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.
  for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
	 DE = DbgScopeMap.end(); DI != DE; ++DI) {
    DbgScope *S = DI->second;
    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(MachineFunction *MF) {
  if (!ShouldEmitDwarfDebug()) return;
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  if (!extractScopeInformation(MF))
  // Begin accumulating function debug information.
  MMI->BeginFunction(MF);
  // 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 = 0;
    DISubprogram SP = getDISubprogram(DLT.Scope);
      LabelID = recordSourceLine(SP.getLineNumber(), 0, DLT.Scope);
      LabelID = recordSourceLine(DLT.Line, DLT.Col, DLT.Scope);
  if (TimePassesIsEnabled)
    DebugTimer->stopTimer();
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(MachineFunction *MF) {
  if (!ShouldEmitDwarfDebug()) return;
  if (TimePassesIsEnabled)
    DebugTimer->startTimer();
  if (CurrentFnDbgScope) {
    // Define end label for subprogram.
    EmitLabel("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;
  DbgScopeMap.clear();
  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());
    EmitLabel("section_debug_frame", 0);
  }
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
  EmitLabel("section_info", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
  EmitLabel("section_abbrev", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
  EmitLabel("section_aranges", 0);
  if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
    Asm->OutStreamer.SwitchSection(LineInfoDirective);
    EmitLabel("section_macinfo", 0);
  }
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
  EmitLabel("section_line", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
  EmitLabel("section_loc", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
  EmitLabel("section_pubnames", 0);
Devang Patel's avatar
Devang Patel committed
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection());
  EmitLabel("section_pubtypes", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
  EmitLabel("section_str", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
  EmitLabel("section_ranges", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
  EmitLabel("text_begin", 0);
  Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
  EmitLabel("data_begin", 0);
/// 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.
  Asm->EmitULEB128Bytes(AbbrevNumber);
  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();
  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)");
    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);
      break;
    }
    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)
    Asm->EmitInt8(0); Asm->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.
  EmitLabel("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);  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)");

  // 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", 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());
    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);
    // Mark end of abbreviations.
    Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
    EmitLabel("abbrev_end", 0);
    Asm->EOL();
  }
}
/// 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");
  // Mark end of matrix.
  Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence");
  Asm->EmitULEB128Bytes(1); Asm->EOL();
  Asm->EmitInt8(1); Asm->EOL();
}
/// 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.
  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);
  Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length");
  Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag");
  Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)");
  Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)");
  Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base");
  // 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");
  // Emit directories.
  for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
    Asm->EmitString(getSourceDirectoryName(DI));
    Asm->EOL("Directory");
  }
  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");
  Asm->EmitInt8(0); Asm->EOL("End of files");
  EmitLabel("line_prolog_end", 0);
  // 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())
        Asm->EOL();
      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); 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");
      // 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");
      }
      // 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); 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");
      }
    }
    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.
  EmitLabel("line_end", 0);
  Asm->EOL();
/// 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());
  EmitLabel("debug_frame_common", 0);
  EmitDifference("debug_frame_common_end", 0,
                 "debug_frame_common_begin", 0, true);
  Asm->EOL("Length of Common Information Entry");
  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");
  std::vector<MachineMove> Moves;
  RI->getInitialFrameState(Moves);
  EmitFrameMoves(NULL, 0, Moves, false);
  Asm->EmitAlignment(2, 0, 0, false);
  EmitLabel("debug_frame_common_end", 0);
/// 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("debug_frame_end", DebugFrameInfo.Number,
                 "debug_frame_begin", DebugFrameInfo.Number, true);
  Asm->EOL("Length of Frame Information Entry");
  EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
  EmitSectionOffset("debug_frame_common", "section_debug_frame",
                    0, 0, true, false);
  Asm->EOL("FDE CIE offset");
  EmitReference("func_begin", DebugFrameInfo.Number);
  Asm->EOL("FDE initial location");
  EmitDifference("func_end", DebugFrameInfo.Number,
                 "func_begin", DebugFrameInfo.Number);
  Asm->EOL("FDE address range");
  EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
                 false);
  Asm->EmitAlignment(2, 0, 0, false);
  EmitLabel("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("pubnames_end", ModuleCU->getID(),
                 "pubnames_begin", ModuleCU->getID(), true);
  Asm->EOL("Length of Public Names Info");
  EmitLabel("pubnames_begin", ModuleCU->getID());
  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
  EmitSectionOffset("info_begin", "section_info",
                    ModuleCU->getID(), 0, true, false);
  Asm->EOL("Offset of Compilation Unit Info");
  EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
                 true);
  Asm->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()); Asm->EOL("DIE offset");
    Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
  Asm->EmitInt32(0); Asm->EOL("End Mark");
  EmitLabel("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());
Devang Patel's avatar
Devang Patel committed
  EmitDifference("pubtypes_end", ModuleCU->getID(),
                 "pubtypes_begin", ModuleCU->getID(), true);
  Asm->EOL("Length of Public Types Info");

  EmitLabel("pubtypes_begin", ModuleCU->getID());

  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");

  EmitSectionOffset("info_begin", "section_info",
                    ModuleCU->getID(), 0, true, false);
  Asm->EOL("Offset of Compilation ModuleCU Info");

  EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
                 true);
  Asm->EOL("Compilation ModuleCU Length");

  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;

    Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
    Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
  }

  Asm->EmitInt32(0); Asm->EOL("End Mark");
  EmitLabel("pubtypes_end", ModuleCU->getID());

  Asm->EOL();
}

/// 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.
      EmitLabel("string", StringID);
      // Emit the string itself.
      const std::string &String = StringPool[StringID];
      Asm->EmitString(String); Asm->EOL();
    }
/// 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); Asm->EOL("Length of Address Ranges Info");
  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
  EmitReference("info_begin", Unit->getID());
  Asm->EOL("Offset of Compilation Unit Info");
  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address");
  Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor");
  Asm->EmitInt16(0);  Asm->EOL("Pad (1)");
  Asm->EmitInt16(0);  Asm->EOL("Pad (2)");
  // Range 1
  EmitReference("text_begin", 0); Asm->EOL("Address");
  EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length");
  Asm->EmitInt32(0); Asm->EOL("EOM (1)");
  Asm->EmitInt32(0); Asm->EOL("EOM (2)");
#endif
/// 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());
  Asm->EOL();
  EmitDifference("debug_inlined_end", 1,
                 "debug_inlined_begin", 1, true);
  Asm->EOL("Length of Debug Inlined Information Entry");
  EmitLabel("debug_inlined_begin", 1);
  Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
  Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
  for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
         E = InlinedSPNodes.end(); I != E; ++I) {
    MDNode *Node = *I;
Jim Grosbach's avatar
Jim Grosbach committed
    ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
      = 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())
      EmitSectionOffset("string", "section_str",
                        StringPool.idFor(getRealLinkageName(LName)), false, true);
    Asm->EOL("MIPS linkage name");
    EmitSectionOffset("string", "section_str",
                      StringPool.idFor(Name), false, true);
    Asm->EOL("Function name");
    Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
    for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
           LE = Labels.end(); LI != LE; ++LI) {
      DIE *SP = LI->second;
      Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset");
      if (TD->getPointerSize() == sizeof(int32_t))
        O << MAI->getData32bitsDirective();
        O << MAI->getData64bitsDirective();
      PrintLabelName("label", LI->first); Asm->EOL("low_pc");
  EmitLabel("debug_inlined_end", 1);
  Asm->EOL();