Skip to content
DwarfDebug.cpp 109 KiB
Newer Older
    DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.first, VP.second);
    DbgVariable *RegVar = new DbgVariable(DV, VP.first, AbsDbgVariable);
    Scope->addVariable(RegVar);

  // Collect variable information from DBG_VALUE machine instructions;
  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;
      if (!MInsn->isDebugValue())
      // FIXME : Lift this restriction.
      if (MInsn->getNumOperands() != 3)
        continue;
      DIVariable DV((MDNode*)(MInsn->getOperand(MInsn->getNumOperands()
                                                - 1).getMetadata()));
      if (DV.getTag() == dwarf::DW_TAG_arg_variable)  {
        // FIXME Handle inlined subroutine arguments.
        DbgVariable *ArgVar = new DbgVariable(DV, MInsn, NULL);
        CurrentFnDbgScope->addVariable(ArgVar);
        continue;
      }

      DebugLoc DL = MInsn->getDebugLoc();
      if (DL.isUnknown()) continue;
      DbgScope *Scope = 0;
      if (MDNode *IA = DL.getInlinedAt(Ctx))
        Scope = ConcreteScopes.lookup(IA);
      if (Scope == 0)
        Scope = DbgScopeMap.lookup(DL.getScope(Ctx));
      
      // If variable scope is not found then skip this variable.
      DbgVariable *AbsDbgVariable = findAbstractVariable(DV, MInsn, DL);
      DbgVariable *RegVar = new DbgVariable(DV, MInsn, AbsDbgVariable);
/// beginScope - Process beginning of a scope.
void DwarfDebug::beginScope(const MachineInstr *MI) {
  // Check location.
  DebugLoc DL = MI->getDebugLoc();
  if (DL.isUnknown())
    return;

  // Check and update last known location info.
  if (DL == PrevInstLoc)
    return;
  
  MDNode *Scope = DL.getScope(MF->getFunction()->getContext());
  
  // FIXME: Should only verify each scope once!
  if (!DIScope(Scope).Verify())
  // DBG_VALUE instruction establishes new value.
  if (MI->isDebugValue()) {
    DenseMap<const MachineInstr *, DbgVariable *>::iterator DI
      = DbgValueStartMap.find(MI);
    if (DI != DbgValueStartMap.end()) {
      MCSymbol *Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
      PrevInstLoc = DL;
  // Emit a label to indicate location change. This is used for line 
  // table even if this instruction does start a new scope.
  MCSymbol *Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
  PrevInstLoc = DL;

  // update DbgScope if this instruction starts a new scope.
  InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
  if (I == DbgScopeBeginMap.end())
    return;
Dan Gohman's avatar
Dan Gohman committed
  ScopeVector &SD = I->second;
  for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
Jim Grosbach's avatar
Jim Grosbach committed
       SDI != SDE; ++SDI)
Chris Lattner's avatar
Chris Lattner committed
    (*SDI)->setStartLabel(Label);
/// endScope - Process end of a scope.
void DwarfDebug::endScope(const MachineInstr *MI) {
  if (MI->isDebugValue())
    return;

  // Check location.
  DebugLoc DL = MI->getDebugLoc();
  if (DL.isUnknown())
    return;
  // Emit a label and update DbgScope if this instruction ends a scope.
  InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
Devang Patel's avatar
Devang Patel committed
  if (I == DbgScopeEndMap.end())
  MCSymbol *Label = MMI->getContext().CreateTempSymbol();
  Asm->OutStreamer.EmitLabel(Label);
  SmallVector<DbgScope*, 2> &SD = I->second;
  for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
Jim Grosbach's avatar
Jim Grosbach committed
       SDI != SDE; ++SDI)
  return;
}

/// createDbgScope - Create DbgScope for the scope.
void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {
  if (!InlinedAt) {
    DbgScope *WScope = DbgScopeMap.lookup(Scope);
    if (WScope)
      return;
    WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
    DbgScopeMap.insert(std::make_pair(Scope, WScope));
Jim Grosbach's avatar
Jim Grosbach committed
    if (DIDescriptor(Scope).isLexicalBlock())
      createDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL);
    return;
  }

  DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
  if (WScope)
    return;

  WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
  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 at least 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;
  LLVMContext &Ctx = MF->getFunction()->getContext();
  
  // 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;
      if (MInsn->isDebugValue()) continue;
      MIIndexMap[MInsn] = MIIndex++;
      if (DL.isUnknown()) 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 (DIScope(Scope).isCompileUnit()) continue;
      createDbgScope(Scope, DL.getInlinedAt(Ctx));
Devang Patel's avatar
Devang Patel committed

  // 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;
      if (MInsn->isDebugValue()) continue;
      DebugLoc DL = MInsn->getDebugLoc();
      if (DL.isUnknown()) continue;

      MDNode *Scope = DL.getScope(Ctx);
      if (Scope == 0) 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 (DIScope(Scope).isCompileUnit()) continue;
      DbgScope *DScope = getUpdatedDbgScope(Scope, MInsn, DL.getInlinedAt(Ctx));
      DScope->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.pop_back_val();
    const SmallVector<DbgScope *, 4> &Children = S->getScopes();
      for (SmallVector<DbgScope *, 4>::const_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);
    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 (!extractScopeInformation())
  // Assumes in correct section after the entry point.
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_begin",
                                                ++SubprogramCount));

  // Emit label for the implicitly defined dbg.stoppoint at the start of the
  // function.
  DebugLoc FDL = MF->getDefaultDebugLoc();
  if (FDL.isUnknown()) return;
  
  MDNode *Scope = FDL.getScope(MF->getFunction()->getContext());
  
  DISubprogram SP = getDISubprogram(Scope);
  unsigned Line, Col;
  if (SP.Verify()) {
    Line = SP.getLineNumber();
    Col = 0;
  } else {
    Line = FDL.getLine();
    Col = FDL.getCol();
  
  recordSourceLine(Line, Col, Scope);
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
  if (!ShouldEmitDwarfDebug()) return;
  if (DbgScopeMap.empty()) return;
  
  TimeRegion Timer(DebugTimer);
  if (CurrentFnDbgScope) {
    // Define end label for subprogram.
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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();
Chris Lattner's avatar
Chris Lattner committed
/// recordSourceLine - Register a source line with debug info. Returns the
/// unique label that was emitted and which provides correspondence to
/// the source line list.
MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) {
Devang Patel's avatar
Devang Patel committed
  if (!MMI)
    return 0;

  TimeRegion Timer(DebugTimer);
  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
Chris Lattner's avatar
Chris Lattner committed
    assert(0 && "Unexpected scope info");

  unsigned Src = GetOrCreateSourceID(Dir, Fn);
  MCSymbol *Label = MMI->getContext().CreateTempSymbol();
  Lines.push_back(SrcLineInfo(Line, Col, Src, Label));
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(Label);
  return Label;
/// 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) {
  TimeRegion Timer(DebugTimer);
  return GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
//===----------------------------------------------------------------------===//
// 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.
    Die->addSiblingOffset(DIEValueAllocator);

  // 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;
/// EmitSectionSym - Switch to the specified MCSection and emit an assembler
/// temporary label to it if SymbolStem is specified.
static MCSymbol *EmitSectionSym(AsmPrinter *Asm, const MCSection *Section,
                                const char *SymbolStem = 0) {
  Asm->OutStreamer.SwitchSection(Section);
  if (!SymbolStem) return 0;
  
  MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem);
  Asm->OutStreamer.EmitLabel(TmpSym);
  return TmpSym;
}

/// EmitSectionLabels - Emit initial Dwarf sections with a label at
/// the start of each one.
void DwarfDebug::EmitSectionLabels() {
  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  // Dwarf sections base addresses.
  if (MAI->doesDwarfRequireFrameSection()) {
    DwarfFrameSectionSym =
      EmitSectionSym(Asm, TLOF.getDwarfFrameSection(), "section_debug_frame");
   }

  DwarfInfoSectionSym = 
    EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
  DwarfAbbrevSectionSym = 
    EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
  EmitSectionSym(Asm, TLOF.getDwarfARangesSection());
  
  if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
    EmitSectionSym(Asm, MacroInfo);
  EmitSectionSym(Asm, TLOF.getDwarfLineSection());
  EmitSectionSym(Asm, TLOF.getDwarfLocSection());
  EmitSectionSym(Asm, TLOF.getDwarfPubNamesSection());
  EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
  DwarfStrSectionSym = 
    EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str");
  EmitSectionSym(Asm, TLOF.getDwarfRangesSection());
  TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin");
  EmitSectionSym(Asm, TLOF.getDataSection());
/// 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->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
                                Twine::utohexstr(Die->getOffset()) + ":0x" +
                                Twine::utohexstr(Die->getSize()) + " " +
                                dwarf::TagString(Abbrev->getTag()));
  Asm->EmitULEB128(AbbrevNumber);
  const 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)");
      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);
      break;
    }
  }
  // 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->OutStreamer.AddComment("End Of Children Mark");
    Asm->EmitInt8(0);
/// 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.
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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->OutStreamer.AddComment("Length of Compilation Unit Info");
  Asm->EmitInt32(ContentSize);
  Asm->OutStreamer.AddComment("DWARF version number");
  Asm->EmitInt16(dwarf::DWARF_VERSION);
  Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
  Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"),
                         DwarfAbbrevSectionSym);
  Asm->OutStreamer.AddComment("Address Size (in bytes)");
  Asm->EmitInt8(TD->getPointerSize());
  // FIXME - extra padding for gdb bug.
  Asm->OutStreamer.AddComment("4 extra padding bytes for GDB");
  Asm->EmitInt8(0);
  Asm->EmitInt8(0);
  Asm->EmitInt8(0);
  Asm->EmitInt8(0);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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());
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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.)
      Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
      // Emit the abbreviations data.
    // Mark end of abbreviations.
    Asm->EmitULEB128(0, "EOM(3)");
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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->OutStreamer.AddComment("Extended Op");
  Asm->EmitInt8(0);
  
  Asm->OutStreamer.AddComment("Op size");
  Asm->EmitInt8(TD->getPointerSize() + 1);
  Asm->OutStreamer.AddComment("DW_LNE_set_address");
  Asm->EmitInt8(dwarf::DW_LNE_set_address);

  Asm->OutStreamer.AddComment("Section end label");
  Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd),
                                   TD->getPointerSize(), 0/*AddrSpace*/);
  // Mark end of matrix.
  Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
  Asm->EmitInt8(0);
/// 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.
  Asm->OutStreamer.AddComment("Length of Source Line Info");
  Asm->EmitLabelDifference(Asm->GetTempSymbol("line_end"),
                           Asm->GetTempSymbol("line_begin"), 4);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_begin"));
  Asm->OutStreamer.AddComment("DWARF version number");
  Asm->EmitInt16(dwarf::DWARF_VERSION); 
  Asm->OutStreamer.AddComment("Prolog Length");
  Asm->EmitLabelDifference(Asm->GetTempSymbol("line_prolog_end"),
                           Asm->GetTempSymbol("line_prolog_begin"), 4);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("line_prolog_begin"));
  Asm->OutStreamer.AddComment("Minimum Instruction Length");
  Asm->EmitInt8(1);
  Asm->OutStreamer.AddComment("Default is_stmt_start flag");
  Asm->EmitInt8(1);
  Asm->OutStreamer.AddComment("Line Base Value (Special Opcodes)");
  Asm->EmitInt8(MinLineDelta);
  Asm->OutStreamer.AddComment("Line Range Value (Special Opcodes)");
  Asm->EmitInt8(MaxLineDelta);
  Asm->OutStreamer.AddComment("Special Opcode Base");
  Asm->EmitInt8(-MinLineDelta);
  // Line number standard opcode encodings argument count
  Asm->OutStreamer.AddComment("DW_LNS_copy arg count");
  Asm->EmitInt8(0);
  Asm->OutStreamer.AddComment("DW_LNS_advance_pc arg count");
  Asm->EmitInt8(1);
  Asm->OutStreamer.AddComment("DW_LNS_advance_line arg count");
  Asm->EmitInt8(1);
  Asm->OutStreamer.AddComment("DW_LNS_set_file arg count");
  Asm->EmitInt8(1);
  Asm->OutStreamer.AddComment("DW_LNS_set_column arg count");
  Asm->EmitInt8(1);
  Asm->OutStreamer.AddComment("DW_LNS_negate_stmt arg count");
  Asm->EmitInt8(0);
  Asm->OutStreamer.AddComment("DW_LNS_set_basic_block arg count");
  Asm->EmitInt8(0);
  Asm->OutStreamer.AddComment("DW_LNS_const_add_pc arg count");
  Asm->EmitInt8(0);
  Asm->OutStreamer.AddComment("DW_LNS_fixed_advance_pc arg count");
  Asm->EmitInt8(1);
  // Emit directories.
  for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
    const std::string &Dir = getSourceDirectoryName(DI);
    if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Directory");
    Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0);
  Asm->OutStreamer.AddComment("End of directories");
  Asm->EmitInt8(0);

  // 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->isVerbose()) Asm->OutStreamer.AddComment("Source");
    Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0);
    
    Asm->EmitULEB128(Id.first, "Directory #");
    Asm->EmitULEB128(0, "Mod date");
    Asm->EmitULEB128(0, "File size");
  Asm->OutStreamer.AddComment("End of files");
  Asm->EmitInt8(0);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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];
    // 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];
      MCSymbol *Label = LineInfo.getLabel();
      if (!Label->isDefined()) continue; // Not emitted, in dead code.
      if (LineInfo.getLine() == 0) continue;

        std::pair<unsigned, unsigned> SrcID =
          getSourceDirectoryAndFileIds(LineInfo.getSourceID());
        Asm->OutStreamer.AddComment(Twine(getSourceDirectoryName(SrcID.first)) +
Chris Lattner's avatar
Chris Lattner committed
                                    "/" +
                                    Twine(getSourceFileName(SrcID.second)) +
                                    ":" + Twine(LineInfo.getLine()));
      // Define the line address.
      Asm->OutStreamer.AddComment("Extended Op");
      Asm->EmitInt8(0);
      Asm->OutStreamer.AddComment("Op size");
      Asm->EmitInt8(TD->getPointerSize() + 1);

      Asm->OutStreamer.AddComment("DW_LNE_set_address");
      Asm->EmitInt8(dwarf::DW_LNE_set_address); 

      Asm->OutStreamer.AddComment("Location label");
      Asm->OutStreamer.EmitSymbolValue(Label, TD->getPointerSize(),
                                       0/*AddrSpace*/);
      // If change of source, then switch to the new source.
      if (Source != LineInfo.getSourceID()) {
        Source = LineInfo.getSourceID();
        Asm->OutStreamer.AddComment("DW_LNS_set_file");
        Asm->EmitInt8(dwarf::DW_LNS_set_file); 
        Asm->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->OutStreamer.AddComment("Line Delta");
          Asm->EmitInt8(Delta - MinLineDelta);
        } else {
          // ... otherwise use long hand.
          Asm->OutStreamer.AddComment("DW_LNS_advance_line");
          Asm->EmitInt8(dwarf::DW_LNS_advance_line);
          Asm->EmitSLEB128(Offset, "Line Offset");
          Asm->OutStreamer.AddComment("DW_LNS_copy");
          Asm->EmitInt8(dwarf::DW_LNS_copy);
        }
      } else {
        // Copy the previous row (different address or source)
        Asm->OutStreamer.AddComment("DW_LNS_copy");
        Asm->EmitInt8(dwarf::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.
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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());
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common"));
  Asm->OutStreamer.AddComment("Length of Common Information Entry");
  Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_frame_common_end"),
                           Asm->GetTempSymbol("debug_frame_common_begin"), 4);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_begin"));
  Asm->OutStreamer.AddComment("CIE Identifier Tag");
  Asm->EmitInt32((int)dwarf::DW_CIE_ID);
  Asm->OutStreamer.AddComment("CIE Version");
  Asm->EmitInt8(dwarf::DW_CIE_VERSION);
  Asm->OutStreamer.AddComment("CIE Augmentation");
  Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator.
  Asm->EmitULEB128(1, "CIE Code Alignment Factor");
  Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
  Asm->OutStreamer.AddComment("CIE RA Column");
  Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
  std::vector<MachineMove> Moves;
  RI->getInitialFrameState(Moves);
  EmitFrameMoves(0, Moves, false);
  Asm->EmitAlignment(2, 0, 0, false);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_end"));
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
Chris Lattner's avatar
Chris Lattner committed
void DwarfDebug::
emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) {
  if (!MAI->doesDwarfRequireFrameSection())
  // Start the dwarf frame section.
  Asm->OutStreamer.SwitchSection(
                              Asm->getObjFileLowering().getDwarfFrameSection());
  Asm->OutStreamer.AddComment("Length of Frame Information Entry");
Chris Lattner's avatar
Chris Lattner committed
  MCSymbol *DebugFrameBegin =
    Asm->GetTempSymbol("debug_frame_begin", DebugFrameInfo.Number);
Chris Lattner's avatar
Chris Lattner committed
  MCSymbol *DebugFrameEnd =
    Asm->GetTempSymbol("debug_frame_end", DebugFrameInfo.Number);
  Asm->EmitLabelDifference(DebugFrameEnd, DebugFrameBegin, 4);
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(DebugFrameBegin);
  Asm->OutStreamer.AddComment("FDE CIE offset");
  Asm->EmitSectionOffset(Asm->GetTempSymbol("debug_frame_common"), 
                         DwarfFrameSectionSym);
  Asm->OutStreamer.AddComment("FDE initial location");
  MCSymbol *FuncBeginSym =
    Asm->GetTempSymbol("func_begin", DebugFrameInfo.Number);
  Asm->OutStreamer.EmitSymbolValue(FuncBeginSym,
                                   TD->getPointerSize(), 0/*AddrSpace*/);
  
  
  Asm->OutStreamer.AddComment("FDE address range");
  Asm->EmitLabelDifference(Asm->GetTempSymbol("func_end",DebugFrameInfo.Number),
                           FuncBeginSym, TD->getPointerSize());
  EmitFrameMoves(FuncBeginSym, DebugFrameInfo.Moves, false);
  Asm->EmitAlignment(2, 0, 0, false);
Chris Lattner's avatar
Chris Lattner committed
  Asm->OutStreamer.EmitLabel(DebugFrameEnd);
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::emitDebugPubNames() {
  // Start the dwarf pubnames section.
  Asm->OutStreamer.SwitchSection(
                          Asm->getObjFileLowering().getDwarfPubNamesSection());

  Asm->OutStreamer.AddComment("Length of Public Names Info");
  Asm->EmitLabelDifference(
                 Asm->GetTempSymbol("pubnames_end", ModuleCU->getID()),
                 Asm->GetTempSymbol("pubnames_begin", ModuleCU->getID()), 4);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin",
                                                ModuleCU->getID()));
  Asm->OutStreamer.AddComment("DWARF Version");
  Asm->EmitInt16(dwarf::DWARF_VERSION); 
  Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
  Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", ModuleCU->getID()), 
                         DwarfInfoSectionSym);
  Asm->OutStreamer.AddComment("Compilation Unit Length");
  Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", ModuleCU->getID()),
                           Asm->GetTempSymbol("info_begin", ModuleCU->getID()),
                           4);
  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();
    Asm->OutStreamer.AddComment("DIE offset");
    Asm->EmitInt32(Entity->getOffset());
      Asm->OutStreamer.AddComment("External Name");
    Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
  Asm->OutStreamer.AddComment("End Mark");
  Asm->EmitInt32(0);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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());
  Asm->OutStreamer.AddComment("Length of Public Types Info");
  Asm->EmitLabelDifference(
                    Asm->GetTempSymbol("pubtypes_end", ModuleCU->getID()),
                    Asm->GetTempSymbol("pubtypes_begin", ModuleCU->getID()), 4);
Devang Patel's avatar
Devang Patel committed

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

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

  Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info");
  Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", ModuleCU->getID()),
                         DwarfInfoSectionSym);
Devang Patel's avatar
Devang Patel committed

  Asm->OutStreamer.AddComment("Compilation ModuleCU Length");
  Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", ModuleCU->getID()),
                           Asm->GetTempSymbol("info_begin", ModuleCU->getID()),
                           4);
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->isVerbose()) Asm->OutStreamer.AddComment("DIE offset");
    Asm->EmitInt32(Entity->getOffset());
    if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name");
    Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
Devang Patel's avatar
Devang Patel committed
  }

  Asm->OutStreamer.AddComment("End Mark");
  Asm->EmitInt32(0); 
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("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()) return;
  
  // Start the dwarf str section.
  Asm->OutStreamer.SwitchSection(
                                Asm->getObjFileLowering().getDwarfStrSection());