Revert r72192. It was causing a build failure.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72193 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index ad7184d..086a8a5 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -275,9 +275,9 @@
}
}
-/// CreateDIEEntry - Creates a new DIEEntry to be a proxy for a debug
-/// information entry.
-DIEEntry *DwarfDebug::CreateDIEEntry(DIE *Entry) {
+/// NewDIEEntry - Creates a new DIEEntry to be a proxy for a debug information
+/// entry.
+DIEEntry *DwarfDebug::NewDIEEntry(DIE *Entry) {
DIEEntry *Value;
if (Entry) {
@@ -545,7 +545,7 @@
}
// Set up proxy.
- Slot = CreateDIEEntry();
+ Slot = NewDIEEntry();
// Construct type.
DIE Buffer(dwarf::DW_TAG_base_type);
@@ -925,9 +925,9 @@
return *I->second;
}
-/// CreateDbgScopeVariable - Create a new scope variable.
+/// NewDbgScopeVariable - Create a new scope variable.
///
-DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
+DIE *DwarfDebug::NewDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
// Get the descriptor.
const DIVariable &VD = DV->getVariable();
@@ -1012,7 +1012,7 @@
// Add variables to scope.
SmallVector<DbgVariable *, 8> &Variables = ParentScope->getVariables();
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
- DIE *VariableDie = CreateDbgScopeVariable(Variables[i], Unit);
+ DIE *VariableDie = NewDbgScopeVariable(Variables[i], Unit);
if (VariableDie) ParentDie->AddChild(VariableDie);
}
@@ -1092,8 +1092,7 @@
/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
///
-void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope,
- bool AbstractScope) {
+void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope) {
// Exit if there is no root scope.
if (!RootScope) return;
DIDescriptor Desc = RootScope->getDesc();
@@ -1112,19 +1111,43 @@
DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV());
assert(SPDie && "Missing subprogram descriptor");
- if (!AbstractScope) {
- // Add the function bounds.
- AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
- AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
- MachineLocation Location(RI->getFrameRegister(*MF));
- AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
- }
+ // Add the function bounds.
+ AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ DWLabel("func_begin", SubprogramCount));
+ AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ DWLabel("func_end", SubprogramCount));
+ MachineLocation Location(RI->getFrameRegister(*MF));
+ AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
ConstructDbgScope(RootScope, 0, 0, SPDie, Unit);
}
+/// ConstructFunctionDbgScope - Construct the scope for the abstract debug
+/// scope.
+///
+void DwarfDebug::ConstructAbstractDbgScope(DbgScope *AbsScope) {
+ // Exit if there is no root scope.
+ if (!AbsScope) return;
+
+ DIDescriptor Desc = AbsScope->getDesc();
+ if (Desc.isNull())
+ return;
+
+ // Get the subprogram debug information entry.
+ DISubprogram SPD(Desc.getGV());
+
+ // Get the compile unit context.
+ CompileUnit *Unit = MainCU;
+ if (!Unit)
+ Unit = &FindCompileUnit(SPD.getCompileUnit());
+
+ // Get the subprogram die.
+ DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV());
+ assert(SPDie && "Missing subprogram descriptor");
+
+ ConstructDbgScope(AbsScope, 0, 0, SPDie, Unit);
+}
+
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
///
void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) {
@@ -1173,809 +1196,6 @@
#endif
}
-/// GetOrCreateSourceID - Look up the source id with the given directory and
-/// source file names. If none currently exists, create a new id and insert it
-/// in the SourceIds map. This can update DirectoryNames and SourceFileNames
-/// maps as well.
-unsigned DwarfDebug::GetOrCreateSourceID(const std::string &DirName,
- const std::string &FileName) {
- unsigned DId;
- StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName);
- if (DI != DirectoryIdMap.end()) {
- DId = DI->getValue();
- } else {
- DId = DirectoryNames.size() + 1;
- DirectoryIdMap[DirName] = DId;
- DirectoryNames.push_back(DirName);
- }
-
- unsigned FId;
- StringMap<unsigned>::iterator FI = SourceFileIdMap.find(FileName);
- if (FI != SourceFileIdMap.end()) {
- FId = FI->getValue();
- } else {
- FId = SourceFileNames.size() + 1;
- SourceFileIdMap[FileName] = FId;
- SourceFileNames.push_back(FileName);
- }
-
- DenseMap<std::pair<unsigned, unsigned>, unsigned>::iterator SI =
- SourceIdMap.find(std::make_pair(DId, FId));
- if (SI != SourceIdMap.end())
- return SI->second;
-
- unsigned SrcId = SourceIds.size() + 1; // DW_AT_decl_file cannot be 0.
- SourceIdMap[std::make_pair(DId, FId)] = SrcId;
- SourceIds.push_back(std::make_pair(DId, FId));
-
- return SrcId;
-}
-
-void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) {
- DICompileUnit DIUnit(GV);
- std::string Dir, FN, Prod;
- unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir),
- DIUnit.getFilename(FN));
-
- DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
- AddSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
- DWLabel("section_line", 0), DWLabel("section_line", 0),
- false);
- AddString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
- DIUnit.getProducer(Prod));
- AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
- DIUnit.getLanguage());
- AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
-
- if (!Dir.empty())
- AddString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
- if (DIUnit.isOptimized())
- AddUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
-
- std::string Flags;
- DIUnit.getFlags(Flags);
- if (!Flags.empty())
- AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
-
- unsigned RVer = DIUnit.getRunTimeVersion();
- if (RVer)
- AddUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
- dwarf::DW_FORM_data1, RVer);
-
- CompileUnit *Unit = new CompileUnit(ID, Die);
- if (DIUnit.isMain()) {
- assert(!MainCU && "Multiple main compile units are found!");
- MainCU = Unit;
- }
-
- CompileUnitMap[DIUnit.getGV()] = Unit;
- CompileUnits.push_back(Unit);
-}
-
-/// ConstructCompileUnits - Create a compile unit DIEs.
-void DwarfDebug::ConstructCompileUnits() {
- GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.compile_units");
- if (!Root)
- return;
- assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
- "Malformed compile unit descriptor anchor type");
- Constant *RootC = cast<Constant>(*Root->use_begin());
- assert(RootC->hasNUsesOrMore(1) &&
- "Malformed compile unit descriptor anchor type");
-
- for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
- UI != UE; ++UI)
- for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
- UUI != UUE; ++UUI) {
- GlobalVariable *GV = cast<GlobalVariable>(*UUI);
- ConstructCompileUnit(GV);
- }
-}
-
-bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) {
- DIGlobalVariable DI_GV(GV);
- CompileUnit *DW_Unit = MainCU;
- if (!DW_Unit)
- DW_Unit = &FindCompileUnit(DI_GV.getCompileUnit());
-
- // Check for pre-existence.
- DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV());
- if (Slot)
- return false;
-
- DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV);
-
- // Add address.
- DIEBlock *Block = new DIEBlock();
- AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
- std::string GLN;
- AddObjectLabel(Block, 0, dwarf::DW_FORM_udata,
- Asm->getGlobalLinkName(DI_GV.getGlobal(), GLN));
- AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
-
- // Add to map.
- Slot = VariableDie;
-
- // Add to context owner.
- DW_Unit->getDie()->AddChild(VariableDie);
-
- // Expose as global. FIXME - need to check external flag.
- std::string Name;
- DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie);
- return true;
-}
-
-/// ConstructGlobalVariableDIEs - Create DIEs for each of the externally visible
-/// global variables. Return true if at least one global DIE is created.
-bool DwarfDebug::ConstructGlobalVariableDIEs() {
- GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables");
- if (!Root)
- return false;
-
- assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
- "Malformed global variable descriptor anchor type");
- Constant *RootC = cast<Constant>(*Root->use_begin());
- assert(RootC->hasNUsesOrMore(1) &&
- "Malformed global variable descriptor anchor type");
-
- bool Result = false;
- for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
- UI != UE; ++UI)
- for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
- UUI != UUE; ++UUI)
- Result |= ConstructGlobalVariableDIE(cast<GlobalVariable>(*UUI));
-
- return Result;
-}
-
-bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) {
- DISubprogram SP(GV);
- CompileUnit *Unit = MainCU;
- if (!Unit)
- Unit = &FindCompileUnit(SP.getCompileUnit());
-
- // Check for pre-existence.
- DIE *&Slot = Unit->getDieMapSlotFor(GV);
- if (Slot)
- return false;
-
- if (!SP.isDefinition())
- // This is a method declaration which will be handled while constructing
- // class type.
- return false;
-
- DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP);
-
- // Add to map.
- Slot = SubprogramDie;
-
- // Add to context owner.
- Unit->getDie()->AddChild(SubprogramDie);
-
- // Expose as global.
- std::string Name;
- Unit->AddGlobal(SP.getName(Name), SubprogramDie);
- return true;
-}
-
-/// ConstructSubprograms - Create DIEs for each of the externally visible
-/// subprograms. Return true if at least one subprogram DIE is created.
-bool DwarfDebug::ConstructSubprograms() {
- GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms");
- if (!Root)
- return false;
-
- assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
- "Malformed subprogram descriptor anchor type");
- Constant *RootC = cast<Constant>(*Root->use_begin());
- assert(RootC->hasNUsesOrMore(1) &&
- "Malformed subprogram descriptor anchor type");
-
- bool Result = false;
- for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
- UI != UE; ++UI)
- for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
- UUI != UUE; ++UUI)
- Result |= ConstructSubprogram(cast<GlobalVariable>(*UUI));
-
- return Result;
-}
-
-/// SetDebugInfo - Create global DIEs and emit initial debug info sections.
-/// This is inovked by the target AsmPrinter.
-void DwarfDebug::SetDebugInfo(MachineModuleInfo *mmi) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- // Create all the compile unit DIEs.
- ConstructCompileUnits();
-
- if (CompileUnits.empty()) {
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return;
- }
-
- // Create DIEs for each of the externally visible global variables.
- bool globalDIEs = ConstructGlobalVariableDIEs();
-
- // Create DIEs for each of the externally visible subprograms.
- bool subprogramDIEs = ConstructSubprograms();
-
- // If there is not any debug info available for any global variables and any
- // subprograms then there is not any debug info to emit.
- if (!globalDIEs && !subprogramDIEs) {
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return;
- }
-
- MMI = mmi;
- shouldEmit = true;
- MMI->setDebugInfoAvailability(true);
-
- // Prime section data.
- SectionMap.insert(TAI->getTextSection());
-
- // Print out .file directives to specify files for .loc directives. These are
- // printed out early so that they precede any .loc directives.
- if (TAI->hasDotLocAndDotFile()) {
- for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) {
- // Remember source id starts at 1.
- std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i);
- sys::Path FullPath(getSourceDirectoryName(Id.first));
- bool AppendOk =
- FullPath.appendComponent(getSourceFileName(Id.second));
- assert(AppendOk && "Could not append filename to directory!");
- AppendOk = false;
- Asm->EmitFile(i, FullPath.toString());
- Asm->EOL();
- }
- }
-
- // Emit initial sections
- EmitInitial();
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-}
-
-/// EndModule - Emit all Dwarf sections that should come after the content.
-///
-void DwarfDebug::EndModule() {
- if (!ShouldEmitDwarfDebug())
- return;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- // Standard sections final addresses.
- Asm->SwitchToSection(TAI->getTextSection());
- EmitLabel("text_end", 0);
- Asm->SwitchToSection(TAI->getDataSection());
- EmitLabel("data_end", 0);
-
- // End text sections.
- for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
- Asm->SwitchToSection(SectionMap[i]);
- EmitLabel("section_end", i);
- }
-
- // Emit common frame information.
- EmitCommonDebugFrame();
-
- // Emit function debug frame information
- for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
- E = DebugFrames.end(); I != E; ++I)
- EmitFunctionDebugFrame(*I);
-
- // Compute DIE offsets and sizes.
- SizeAndOffsets();
-
- // Emit all the DIEs into a debug info section
- EmitDebugInfo();
-
- // Corresponding abbreviations into a abbrev section.
- EmitAbbreviations();
-
- // Emit source line correspondence into a debug line section.
- EmitDebugLines();
-
- // Emit info into a debug pubnames section.
- EmitDebugPubNames();
-
- // Emit info into a debug str section.
- EmitDebugStr();
-
- // Emit info into a debug loc section.
- EmitDebugLoc();
-
- // Emit info into a debug aranges section.
- EmitDebugARanges();
-
- // Emit info into a debug ranges section.
- EmitDebugRanges();
-
- // Emit info into a debug macinfo section.
- EmitDebugMacInfo();
-
- // Emit inline info.
- EmitDebugInlineInfo();
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-}
-
-/// BeginFunction - Gather pre-function debug information. Assumes being
-/// emitted immediately after the function entry point.
-void DwarfDebug::BeginFunction(MachineFunction *MF) {
- this->MF = MF;
-
- if (!ShouldEmitDwarfDebug()) return;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- // 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 = RecordSourceLine(DLT.Line, DLT.Col,
- DICompileUnit(DLT.CompileUnit));
- Asm->printLabel(LabelID);
- }
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-}
-
-/// EndFunction - Gather and emit post-function debug information.
-///
-void DwarfDebug::EndFunction(MachineFunction *MF) {
- if (!ShouldEmitDwarfDebug()) return;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- // 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->CurrentSection_);
- if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
- std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
- // Append the function info to section info.
- SectionLineInfos.insert(SectionLineInfos.end(),
- Lines.begin(), Lines.end());
- }
-
- // Construct the DbgScope for abstract instances.
- for (SmallVector<DbgScope *, 32>::iterator
- I = AbstractInstanceRootList.begin(),
- E = AbstractInstanceRootList.end(); I != E; ++I)
- ConstructFunctionDbgScope(*I, true);
-
- // Construct scopes for subprogram.
- if (FunctionDbgScope)
- ConstructFunctionDbgScope(FunctionDbgScope);
- else
- // FIXME: This is wrong. We are essentially getting past a problem with
- // debug information not being able to handle unreachable blocks that have
- // debug information in them. In particular, those unreachable blocks that
- // have "region end" info in them. That situation results in the "root
- // scope" not being created. If that's the case, then emit a "default"
- // scope, i.e., one that encompasses the whole function. This isn't
- // desirable. And a better way of handling this (and all of the debugging
- // information) needs to be explored.
- ConstructDefaultDbgScope(MF);
-
- DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
- MMI->getFrameMoves()));
-
- // Clear debug info
- if (FunctionDbgScope) {
- delete FunctionDbgScope;
- DbgScopeMap.clear();
- DbgAbstractScopeMap.clear();
- DbgConcreteScopeMap.clear();
- InlinedVariableScopes.clear();
- FunctionDbgScope = NULL;
- LexicalScopeStack.clear();
- AbstractInstanceRootList.clear();
- }
-
- Lines.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.
-unsigned DwarfDebug::RecordSourceLine(Value *V, unsigned Line, unsigned Col) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- CompileUnit *Unit = CompileUnitMap[V];
- assert(Unit && "Unable to find CompileUnit");
- unsigned ID = MMI->NextLabelID();
- Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID));
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// RecordSourceLine - Records location information and associates it with a
-/// label. Returns a unique label ID used to generate a label and provide
-/// correspondence to the source line list.
-unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col,
- DICompileUnit CU) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- std::string Dir, Fn;
- unsigned Src = GetOrCreateSourceID(CU.getDirectory(Dir),
- CU.getFilename(Fn));
- unsigned ID = MMI->NextLabelID();
- Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// 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, FileName);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return SrcId;
-}
-
-/// RecordRegionStart - Indicate the start of a region.
-unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DbgScope *Scope = getOrCreateScope(V);
- unsigned ID = MMI->NextLabelID();
- if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
- LexicalScopeStack.push_back(Scope);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// RecordRegionEnd - Indicate the end of a region.
-unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DbgScope *Scope = getOrCreateScope(V);
- unsigned ID = MMI->NextLabelID();
- Scope->setEndLabelID(ID);
- if (LexicalScopeStack.size() != 0)
- LexicalScopeStack.pop_back();
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// RecordVariable - Indicate the declaration of a local variable.
-void DwarfDebug::RecordVariable(GlobalVariable *GV, unsigned FrameIndex,
- const MachineInstr *MI) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DIDescriptor Desc(GV);
- DbgScope *Scope = NULL;
- bool InlinedFnVar = false;
-
- if (Desc.getTag() == dwarf::DW_TAG_variable) {
- // GV is a global variable.
- DIGlobalVariable DG(GV);
- Scope = getOrCreateScope(DG.getContext().getGV());
- } else {
- DenseMap<const MachineInstr *, DbgScope *>::iterator
- SI = InlinedVariableScopes.find(MI);
-
- if (SI != InlinedVariableScopes.end()) {
- // or GV is an inlined local variable.
- Scope = SI->second;
- } else {
- DIVariable DV(GV);
- GlobalVariable *V = DV.getContext().getGV();
-
- // FIXME: The code that checks for the inlined local variable is a hack!
- DenseMap<const GlobalVariable *, DbgScope *>::iterator
- AI = AbstractInstanceRootMap.find(V);
-
- if (AI != AbstractInstanceRootMap.end()) {
- // This method is called each time a DECLARE node is encountered. For an
- // inlined function, this could be many, many times. We don't want to
- // re-add variables to that DIE for each time. We just want to add them
- // once. Check to make sure that we haven't added them already.
- DenseMap<const GlobalVariable *,
- SmallSet<const GlobalVariable *, 32> >::iterator
- IP = InlinedParamMap.find(V);
-
- if (IP != InlinedParamMap.end() && IP->second.count(GV) > 0) {
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
- return;
- }
-
- // or GV is an inlined local variable.
- Scope = AI->second;
- InlinedParamMap[V].insert(GV);
- InlinedFnVar = true;
- } else {
- // or GV is a local variable.
- Scope = getOrCreateScope(V);
- }
- }
- }
-
- assert(Scope && "Unable to find the variable's scope");
- DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex, InlinedFnVar);
- Scope->AddVariable(DV);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-}
-
-/// RecordInlinedFnStart - Indicate the start of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
- unsigned Line, unsigned Col) {
- unsigned LabelID = MMI->NextLabelID();
-
- if (!TAI->doesDwarfUsesInlineInfoSection())
- return LabelID;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- GlobalVariable *GV = SP.getGV();
- DenseMap<const GlobalVariable *, DbgScope *>::iterator
- II = AbstractInstanceRootMap.find(GV);
-
- if (II == AbstractInstanceRootMap.end()) {
- // Create an abstract instance entry for this inlined function if it doesn't
- // already exist.
- DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV));
-
- // Get the compile unit context.
- CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
- DIE *SPDie = Unit->getDieMapSlotFor(GV);
- if (!SPDie)
- SPDie = CreateSubprogramDIE(Unit, SP, false, true);
-
- // Mark as being inlined. This makes this subprogram entry an abstract
- // instance root.
- // FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
- // that it's defined. That probably won't change in the future. However,
- // this could be more elegant.
- AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
-
- // Keep track of the abstract scope for this function.
- DbgAbstractScopeMap[GV] = Scope;
-
- AbstractInstanceRootMap[GV] = Scope;
- AbstractInstanceRootList.push_back(Scope);
- }
-
- // Create a concrete inlined instance for this inlined function.
- DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV));
- DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
- CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
- ScopeDie->setAbstractCompileUnit(Unit);
-
- DIE *Origin = Unit->getDieMapSlotFor(GV);
- AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
- dwarf::DW_FORM_ref4, Origin);
- AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, Unit->getID());
- AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
- AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
-
- ConcreteScope->setDie(ScopeDie);
- ConcreteScope->setStartLabelID(LabelID);
- MMI->RecordUsedDbgLabel(LabelID);
-
- LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
- LexicalScopeStack.push_back(ConcreteScope);
-
- // Keep track of the concrete scope that's inlined into this function.
- DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
- SI = DbgConcreteScopeMap.find(GV);
-
- if (SI == DbgConcreteScopeMap.end())
- DbgConcreteScopeMap[GV].push_back(ConcreteScope);
- else
- SI->second.push_back(ConcreteScope);
-
- // Track the start label for this inlined function.
- DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
- I = InlineInfo.find(GV);
-
- if (I == InlineInfo.end())
- InlineInfo[GV].push_back(LabelID);
- else
- I->second.push_back(LabelID);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return LabelID;
-}
-
-/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
- if (!TAI->doesDwarfUsesInlineInfoSection())
- return 0;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- GlobalVariable *GV = SP.getGV();
- DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
- I = DbgConcreteScopeMap.find(GV);
-
- if (I == DbgConcreteScopeMap.end()) {
- // FIXME: Can this situation actually happen? And if so, should it?
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return 0;
- }
-
- SmallVector<DbgScope *, 8> &Scopes = I->second;
- assert(!Scopes.empty() && "We should have at least one debug scope!");
- DbgScope *Scope = Scopes.back(); Scopes.pop_back();
- unsigned ID = MMI->NextLabelID();
- MMI->RecordUsedDbgLabel(ID);
- Scope->setEndLabelID(ID);
- LexicalScopeStack.pop_back();
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// RecordVariableScope - Record scope for the variable declared by
-/// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. Record scopes
-/// for only inlined subroutine variables. Other variables's scopes are
-/// determined during RecordVariable().
-void DwarfDebug::RecordVariableScope(DIVariable &DV,
- const MachineInstr *DeclareMI) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DISubprogram SP(DV.getContext().getGV());
-
- if (SP.isNull()) {
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return;
- }
-
- DenseMap<GlobalVariable *, DbgScope *>::iterator
- I = DbgAbstractScopeMap.find(SP.getGV());
- if (I != DbgAbstractScopeMap.end())
- InlinedVariableScopes[DeclareMI] = I->second;
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-}
-
-//===----------------------------------------------------------------------===//
-// Emit Methods
-//===----------------------------------------------------------------------===//
-
-/// SizeAndOffsetDie - Compute the size and offset of a DIE.
-///
-unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) {
- // Get the children.
- const std::vector<DIE *> &Children = Die->getChildren();
-
- // If not last sibling and has children then add sibling offset attribute.
- if (!Last && !Children.empty()) Die->AddSiblingOffset();
-
- // Record the abbreviation.
- AssignAbbrevNumber(Die->getAbbrev());
-
- // Get the abbreviation for this DIE.
- unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
-
- // Set DIE offset
- Die->setOffset(Offset);
-
- // Start the size with the size of abbreviation code.
- Offset += TargetAsmInfo::getULEB128Size(AbbrevNumber);
-
- const SmallVector<DIEValue*, 32> &Values = Die->getValues();
- const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
-
- // 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 = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
-
- // End of children marker.
- Offset += sizeof(int8_t);
- }
-
- Die->setSize(Offset - Die->getOffset());
- return Offset;
-}
-
-/// SizeAndOffsets - Compute the size and offset of all the DIEs.
-///
-void DwarfDebug::SizeAndOffsets() {
- // Compute size of compile unit header.
- static unsigned Offset =
- sizeof(int32_t) + // Length of Compilation Unit Info
- sizeof(int16_t) + // DWARF version number
- sizeof(int32_t) + // Offset Into Abbrev. Section
- sizeof(int8_t); // Pointer Size (in bytes)
-
- // Process base compile unit.
- if (MainCU) {
- SizeAndOffsetDie(MainCU->getDie(), Offset, true);
- CompileUnitOffsets[MainCU] = 0;
- return;
- }
-
- // Process all compile units.
- unsigned PrevOffset = 0;
-
- for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) {
- CompileUnit *Unit = CompileUnits[i];
- CompileUnitOffsets[Unit] = PrevOffset;
- PrevOffset += SizeAndOffsetDie(Unit->getDie(), Offset, true)
- + sizeof(int32_t); // FIXME - extra pad for gdb bug.
- }
-}
-
/// EmitInitial - Emit initial Dwarf declarations. This is necessary for cc
/// tools to recognize the object file contains Dwarf information.
void DwarfDebug::EmitInitial() {
@@ -2082,6 +1302,80 @@
}
}
+/// SizeAndOffsetDie - Compute the size and offset of a DIE.
+///
+unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) {
+ // Get the children.
+ const std::vector<DIE *> &Children = Die->getChildren();
+
+ // If not last sibling and has children then add sibling offset attribute.
+ if (!Last && !Children.empty()) Die->AddSiblingOffset();
+
+ // Record the abbreviation.
+ AssignAbbrevNumber(Die->getAbbrev());
+
+ // Get the abbreviation for this DIE.
+ unsigned AbbrevNumber = Die->getAbbrevNumber();
+ const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+
+ // Set DIE offset
+ Die->setOffset(Offset);
+
+ // Start the size with the size of abbreviation code.
+ Offset += TargetAsmInfo::getULEB128Size(AbbrevNumber);
+
+ const SmallVector<DIEValue*, 32> &Values = Die->getValues();
+ const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
+
+ // 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 = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
+
+ // End of children marker.
+ Offset += sizeof(int8_t);
+ }
+
+ Die->setSize(Offset - Die->getOffset());
+ return Offset;
+}
+
+/// SizeAndOffsets - Compute the size and offset of all the DIEs.
+///
+void DwarfDebug::SizeAndOffsets() {
+ // Compute size of compile unit header.
+ static unsigned Offset =
+ sizeof(int32_t) + // Length of Compilation Unit Info
+ sizeof(int16_t) + // DWARF version number
+ sizeof(int32_t) + // Offset Into Abbrev. Section
+ sizeof(int8_t); // Pointer Size (in bytes)
+
+ // Process base compile unit.
+ if (MainCU) {
+ SizeAndOffsetDie(MainCU->getDie(), Offset, true);
+ CompileUnitOffsets[MainCU] = 0;
+ return;
+ }
+
+ // Process all compile units.
+ unsigned PrevOffset = 0;
+
+ for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) {
+ CompileUnit *Unit = CompileUnits[i];
+ CompileUnitOffsets[Unit] = PrevOffset;
+ PrevOffset += SizeAndOffsetDie(Unit->getDie(), Offset, true)
+ + sizeof(int32_t); // FIXME - extra pad for gdb bug.
+ }
+}
+
/// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section.
///
void DwarfDebug::EmitDebugInfoPerCU(CompileUnit *Unit) {
@@ -2621,3 +1915,726 @@
EmitLabel("debug_inlined_end", 1);
Asm->EOL();
}
+
+/// GetOrCreateSourceID - Look up the source id with the given directory and
+/// source file names. If none currently exists, create a new id and insert it
+/// in the SourceIds map. This can update DirectoryNames and SourceFileNames
+/// maps as well.
+unsigned DwarfDebug::GetOrCreateSourceID(const std::string &DirName,
+ const std::string &FileName) {
+ unsigned DId;
+ StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName);
+ if (DI != DirectoryIdMap.end()) {
+ DId = DI->getValue();
+ } else {
+ DId = DirectoryNames.size() + 1;
+ DirectoryIdMap[DirName] = DId;
+ DirectoryNames.push_back(DirName);
+ }
+
+ unsigned FId;
+ StringMap<unsigned>::iterator FI = SourceFileIdMap.find(FileName);
+ if (FI != SourceFileIdMap.end()) {
+ FId = FI->getValue();
+ } else {
+ FId = SourceFileNames.size() + 1;
+ SourceFileIdMap[FileName] = FId;
+ SourceFileNames.push_back(FileName);
+ }
+
+ DenseMap<std::pair<unsigned, unsigned>, unsigned>::iterator SI =
+ SourceIdMap.find(std::make_pair(DId, FId));
+ if (SI != SourceIdMap.end())
+ return SI->second;
+
+ unsigned SrcId = SourceIds.size() + 1; // DW_AT_decl_file cannot be 0.
+ SourceIdMap[std::make_pair(DId, FId)] = SrcId;
+ SourceIds.push_back(std::make_pair(DId, FId));
+
+ return SrcId;
+}
+
+void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) {
+ DICompileUnit DIUnit(GV);
+ std::string Dir, FN, Prod;
+ unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir),
+ DIUnit.getFilename(FN));
+
+ DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+ AddSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+ DWLabel("section_line", 0), DWLabel("section_line", 0),
+ false);
+ AddString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
+ DIUnit.getProducer(Prod));
+ AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
+ DIUnit.getLanguage());
+ AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
+
+ if (!Dir.empty())
+ AddString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
+ if (DIUnit.isOptimized())
+ AddUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
+
+ std::string Flags;
+ DIUnit.getFlags(Flags);
+ if (!Flags.empty())
+ AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
+
+ unsigned RVer = DIUnit.getRunTimeVersion();
+ if (RVer)
+ AddUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
+ dwarf::DW_FORM_data1, RVer);
+
+ CompileUnit *Unit = new CompileUnit(ID, Die);
+ if (DIUnit.isMain()) {
+ assert(!MainCU && "Multiple main compile units are found!");
+ MainCU = Unit;
+ }
+
+ CompileUnitMap[DIUnit.getGV()] = Unit;
+ CompileUnits.push_back(Unit);
+}
+
+/// ConstructCompileUnits - Create a compile unit DIEs.
+void DwarfDebug::ConstructCompileUnits() {
+ GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.compile_units");
+ if (!Root)
+ return;
+ assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
+ "Malformed compile unit descriptor anchor type");
+ Constant *RootC = cast<Constant>(*Root->use_begin());
+ assert(RootC->hasNUsesOrMore(1) &&
+ "Malformed compile unit descriptor anchor type");
+
+ for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
+ UI != UE; ++UI)
+ for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
+ UUI != UUE; ++UUI) {
+ GlobalVariable *GV = cast<GlobalVariable>(*UUI);
+ ConstructCompileUnit(GV);
+ }
+}
+
+bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) {
+ DIGlobalVariable DI_GV(GV);
+ CompileUnit *DW_Unit = MainCU;
+ if (!DW_Unit)
+ DW_Unit = &FindCompileUnit(DI_GV.getCompileUnit());
+
+ // Check for pre-existence.
+ DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV());
+ if (Slot)
+ return false;
+
+ DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV);
+
+ // Add address.
+ DIEBlock *Block = new DIEBlock();
+ AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
+ std::string GLN;
+ AddObjectLabel(Block, 0, dwarf::DW_FORM_udata,
+ Asm->getGlobalLinkName(DI_GV.getGlobal(), GLN));
+ AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
+
+ // Add to map.
+ Slot = VariableDie;
+
+ // Add to context owner.
+ DW_Unit->getDie()->AddChild(VariableDie);
+
+ // Expose as global. FIXME - need to check external flag.
+ std::string Name;
+ DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie);
+ return true;
+}
+
+/// ConstructGlobalVariableDIEs - Create DIEs for each of the externally visible
+/// global variables. Return true if at least one global DIE is created.
+bool DwarfDebug::ConstructGlobalVariableDIEs() {
+ GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables");
+ if (!Root)
+ return false;
+
+ assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
+ "Malformed global variable descriptor anchor type");
+ Constant *RootC = cast<Constant>(*Root->use_begin());
+ assert(RootC->hasNUsesOrMore(1) &&
+ "Malformed global variable descriptor anchor type");
+
+ bool Result = false;
+ for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
+ UI != UE; ++UI)
+ for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
+ UUI != UUE; ++UUI)
+ Result |= ConstructGlobalVariableDIE(cast<GlobalVariable>(*UUI));
+
+ return Result;
+}
+
+bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) {
+ DISubprogram SP(GV);
+ CompileUnit *Unit = MainCU;
+ if (!Unit)
+ Unit = &FindCompileUnit(SP.getCompileUnit());
+
+ // Check for pre-existence.
+ DIE *&Slot = Unit->getDieMapSlotFor(GV);
+ if (Slot)
+ return false;
+
+ if (!SP.isDefinition())
+ // This is a method declaration which will be handled while constructing
+ // class type.
+ return false;
+
+ DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP);
+
+ // Add to map.
+ Slot = SubprogramDie;
+
+ // Add to context owner.
+ Unit->getDie()->AddChild(SubprogramDie);
+
+ // Expose as global.
+ std::string Name;
+ Unit->AddGlobal(SP.getName(Name), SubprogramDie);
+ return true;
+}
+
+/// ConstructSubprograms - Create DIEs for each of the externally visible
+/// subprograms. Return true if at least one subprogram DIE is created.
+bool DwarfDebug::ConstructSubprograms() {
+ GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms");
+ if (!Root)
+ return false;
+
+ assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() &&
+ "Malformed subprogram descriptor anchor type");
+ Constant *RootC = cast<Constant>(*Root->use_begin());
+ assert(RootC->hasNUsesOrMore(1) &&
+ "Malformed subprogram descriptor anchor type");
+
+ bool Result = false;
+ for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
+ UI != UE; ++UI)
+ for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
+ UUI != UUE; ++UUI)
+ Result |= ConstructSubprogram(cast<GlobalVariable>(*UUI));
+
+ return Result;
+}
+
+/// SetDebugInfo - Create global DIEs and emit initial debug info sections.
+/// This is inovked by the target AsmPrinter.
+void DwarfDebug::SetDebugInfo(MachineModuleInfo *mmi) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ // Create all the compile unit DIEs.
+ ConstructCompileUnits();
+
+ if (CompileUnits.empty()) {
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return;
+ }
+
+ // Create DIEs for each of the externally visible global variables.
+ bool globalDIEs = ConstructGlobalVariableDIEs();
+
+ // Create DIEs for each of the externally visible subprograms.
+ bool subprogramDIEs = ConstructSubprograms();
+
+ // If there is not any debug info available for any global variables and any
+ // subprograms then there is not any debug info to emit.
+ if (!globalDIEs && !subprogramDIEs) {
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return;
+ }
+
+ MMI = mmi;
+ shouldEmit = true;
+ MMI->setDebugInfoAvailability(true);
+
+ // Prime section data.
+ SectionMap.insert(TAI->getTextSection());
+
+ // Print out .file directives to specify files for .loc directives. These are
+ // printed out early so that they precede any .loc directives.
+ if (TAI->hasDotLocAndDotFile()) {
+ for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) {
+ // Remember source id starts at 1.
+ std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i);
+ sys::Path FullPath(getSourceDirectoryName(Id.first));
+ bool AppendOk =
+ FullPath.appendComponent(getSourceFileName(Id.second));
+ assert(AppendOk && "Could not append filename to directory!");
+ AppendOk = false;
+ Asm->EmitFile(i, FullPath.toString());
+ Asm->EOL();
+ }
+ }
+
+ // Emit initial sections
+ EmitInitial();
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+}
+
+/// EndModule - Emit all Dwarf sections that should come after the content.
+///
+void DwarfDebug::EndModule() {
+ if (!ShouldEmitDwarfDebug())
+ return;
+
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ // Standard sections final addresses.
+ Asm->SwitchToSection(TAI->getTextSection());
+ EmitLabel("text_end", 0);
+ Asm->SwitchToSection(TAI->getDataSection());
+ EmitLabel("data_end", 0);
+
+ // End text sections.
+ for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
+ Asm->SwitchToSection(SectionMap[i]);
+ EmitLabel("section_end", i);
+ }
+
+ // Emit common frame information.
+ EmitCommonDebugFrame();
+
+ // Emit function debug frame information
+ for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
+ E = DebugFrames.end(); I != E; ++I)
+ EmitFunctionDebugFrame(*I);
+
+ // Compute DIE offsets and sizes.
+ SizeAndOffsets();
+
+ // Emit all the DIEs into a debug info section
+ EmitDebugInfo();
+
+ // Corresponding abbreviations into a abbrev section.
+ EmitAbbreviations();
+
+ // Emit source line correspondence into a debug line section.
+ EmitDebugLines();
+
+ // Emit info into a debug pubnames section.
+ EmitDebugPubNames();
+
+ // Emit info into a debug str section.
+ EmitDebugStr();
+
+ // Emit info into a debug loc section.
+ EmitDebugLoc();
+
+ // Emit info into a debug aranges section.
+ EmitDebugARanges();
+
+ // Emit info into a debug ranges section.
+ EmitDebugRanges();
+
+ // Emit info into a debug macinfo section.
+ EmitDebugMacInfo();
+
+ // Emit inline info.
+ EmitDebugInlineInfo();
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+}
+
+/// BeginFunction - Gather pre-function debug information. Assumes being
+/// emitted immediately after the function entry point.
+void DwarfDebug::BeginFunction(MachineFunction *MF) {
+ this->MF = MF;
+
+ if (!ShouldEmitDwarfDebug()) return;
+
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ // 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 = RecordSourceLine(DLT.Line, DLT.Col,
+ DICompileUnit(DLT.CompileUnit));
+ Asm->printLabel(LabelID);
+ }
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+}
+
+/// EndFunction - Gather and emit post-function debug information.
+///
+void DwarfDebug::EndFunction(MachineFunction *MF) {
+ if (!ShouldEmitDwarfDebug()) return;
+
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ // 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->CurrentSection_);
+ if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
+ std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
+ // Append the function info to section info.
+ SectionLineInfos.insert(SectionLineInfos.end(),
+ Lines.begin(), Lines.end());
+ }
+
+ // Construct the DbgScope for abstract instances.
+ for (SmallVector<DbgScope *, 32>::iterator
+ I = AbstractInstanceRootList.begin(),
+ E = AbstractInstanceRootList.end(); I != E; ++I)
+ ConstructAbstractDbgScope(*I);
+
+ // Construct scopes for subprogram.
+ if (FunctionDbgScope)
+ ConstructFunctionDbgScope(FunctionDbgScope);
+ else
+ // FIXME: This is wrong. We are essentially getting past a problem with
+ // debug information not being able to handle unreachable blocks that have
+ // debug information in them. In particular, those unreachable blocks that
+ // have "region end" info in them. That situation results in the "root
+ // scope" not being created. If that's the case, then emit a "default"
+ // scope, i.e., one that encompasses the whole function. This isn't
+ // desirable. And a better way of handling this (and all of the debugging
+ // information) needs to be explored.
+ ConstructDefaultDbgScope(MF);
+
+ DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
+ MMI->getFrameMoves()));
+
+ // Clear debug info
+ if (FunctionDbgScope) {
+ delete FunctionDbgScope;
+ DbgScopeMap.clear();
+ DbgAbstractScopeMap.clear();
+ DbgConcreteScopeMap.clear();
+ InlinedVariableScopes.clear();
+ FunctionDbgScope = NULL;
+ LexicalScopeStack.clear();
+ AbstractInstanceRootList.clear();
+ }
+
+ Lines.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.
+unsigned DwarfDebug::RecordSourceLine(Value *V, unsigned Line, unsigned Col) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ CompileUnit *Unit = CompileUnitMap[V];
+ assert(Unit && "Unable to find CompileUnit");
+ unsigned ID = MMI->NextLabelID();
+ Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID));
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return ID;
+}
+
+/// RecordSourceLine - Records location information and associates it with a
+/// label. Returns a unique label ID used to generate a label and provide
+/// correspondence to the source line list.
+unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col,
+ DICompileUnit CU) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ std::string Dir, Fn;
+ unsigned Src = GetOrCreateSourceID(CU.getDirectory(Dir),
+ CU.getFilename(Fn));
+ unsigned ID = MMI->NextLabelID();
+ Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return ID;
+}
+
+/// 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, FileName);
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return SrcId;
+}
+
+/// RecordRegionStart - Indicate the start of a region.
+unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ DbgScope *Scope = getOrCreateScope(V);
+ unsigned ID = MMI->NextLabelID();
+ if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
+ LexicalScopeStack.push_back(Scope);
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return ID;
+}
+
+/// RecordRegionEnd - Indicate the end of a region.
+unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ DbgScope *Scope = getOrCreateScope(V);
+ unsigned ID = MMI->NextLabelID();
+ Scope->setEndLabelID(ID);
+ if (LexicalScopeStack.size() != 0)
+ LexicalScopeStack.pop_back();
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return ID;
+}
+
+/// RecordVariable - Indicate the declaration of a local variable.
+void DwarfDebug::RecordVariable(GlobalVariable *GV, unsigned FrameIndex,
+ const MachineInstr *MI) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ DIDescriptor Desc(GV);
+ DbgScope *Scope = NULL;
+ bool InlinedFnVar = false;
+
+ if (Desc.getTag() == dwarf::DW_TAG_variable) {
+ // GV is a global variable.
+ DIGlobalVariable DG(GV);
+ Scope = getOrCreateScope(DG.getContext().getGV());
+ } else {
+ DenseMap<const MachineInstr *, DbgScope *>::iterator
+ SI = InlinedVariableScopes.find(MI);
+
+ if (SI != InlinedVariableScopes.end()) {
+ // or GV is an inlined local variable.
+ Scope = SI->second;
+ } else {
+ DIVariable DV(GV);
+ GlobalVariable *V = DV.getContext().getGV();
+
+ // FIXME: The code that checks for the inlined local variable is a hack!
+ DenseMap<const GlobalVariable *, DbgScope *>::iterator
+ AI = AbstractInstanceRootMap.find(V);
+
+ if (AI != AbstractInstanceRootMap.end()) {
+ // This method is called each time a DECLARE node is encountered. For an
+ // inlined function, this could be many, many times. We don't want to
+ // re-add variables to that DIE for each time. We just want to add them
+ // once. Check to make sure that we haven't added them already.
+ DenseMap<const GlobalVariable *,
+ SmallSet<const GlobalVariable *, 32> >::iterator
+ IP = InlinedParamMap.find(V);
+
+ if (IP != InlinedParamMap.end() && IP->second.count(GV) > 0) {
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+ return;
+ }
+
+ // or GV is an inlined local variable.
+ Scope = AI->second;
+ InlinedParamMap[V].insert(GV);
+ InlinedFnVar = true;
+ } else {
+ // or GV is a local variable.
+ Scope = getOrCreateScope(V);
+ }
+ }
+ }
+
+ assert(Scope && "Unable to find the variable's scope");
+ DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex, InlinedFnVar);
+ Scope->AddVariable(DV);
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+}
+
+//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
+unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
+ unsigned Line, unsigned Col) {
+ unsigned LabelID = MMI->NextLabelID();
+
+ if (!TAI->doesDwarfUsesInlineInfoSection())
+ return LabelID;
+
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ GlobalVariable *GV = SP.getGV();
+ DenseMap<const GlobalVariable *, DbgScope *>::iterator
+ II = AbstractInstanceRootMap.find(GV);
+
+ if (II == AbstractInstanceRootMap.end()) {
+ // Create an abstract instance entry for this inlined function if it doesn't
+ // already exist.
+ DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV));
+
+ // Get the compile unit context.
+ CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
+ DIE *SPDie = Unit->getDieMapSlotFor(GV);
+ if (!SPDie)
+ SPDie = CreateSubprogramDIE(Unit, SP, false, true);
+
+ // Mark as being inlined. This makes this subprogram entry an abstract
+ // instance root.
+ // FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
+ // that it's defined. That probably won't change in the future. However,
+ // this could be more elegant.
+ AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
+
+ // Keep track of the abstract scope for this function.
+ DbgAbstractScopeMap[GV] = Scope;
+
+ AbstractInstanceRootMap[GV] = Scope;
+ AbstractInstanceRootList.push_back(Scope);
+ }
+
+ // Create a concrete inlined instance for this inlined function.
+ DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV));
+ DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
+ CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
+ ScopeDie->setAbstractCompileUnit(Unit);
+
+ DIE *Origin = Unit->getDieMapSlotFor(GV);
+ AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
+ dwarf::DW_FORM_ref4, Origin);
+ AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, Unit->getID());
+ AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
+ AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
+
+ ConcreteScope->setDie(ScopeDie);
+ ConcreteScope->setStartLabelID(LabelID);
+ MMI->RecordUsedDbgLabel(LabelID);
+
+ LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
+
+ // Keep track of the concrete scope that's inlined into this function.
+ DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
+ SI = DbgConcreteScopeMap.find(GV);
+
+ if (SI == DbgConcreteScopeMap.end())
+ DbgConcreteScopeMap[GV].push_back(ConcreteScope);
+ else
+ SI->second.push_back(ConcreteScope);
+
+ // Track the start label for this inlined function.
+ DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
+ I = InlineInfo.find(GV);
+
+ if (I == InlineInfo.end())
+ InlineInfo[GV].push_back(LabelID);
+ else
+ I->second.push_back(LabelID);
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return LabelID;
+}
+
+/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
+unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
+ if (!TAI->doesDwarfUsesInlineInfoSection())
+ return 0;
+
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ GlobalVariable *GV = SP.getGV();
+ DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
+ I = DbgConcreteScopeMap.find(GV);
+
+ if (I == DbgConcreteScopeMap.end()) {
+ // FIXME: Can this situation actually happen? And if so, should it?
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return 0;
+ }
+
+ SmallVector<DbgScope *, 8> &Scopes = I->second;
+ assert(!Scopes.empty() && "We should have at least one debug scope!");
+ DbgScope *Scope = Scopes.back(); Scopes.pop_back();
+ unsigned ID = MMI->NextLabelID();
+ MMI->RecordUsedDbgLabel(ID);
+ Scope->setEndLabelID(ID);
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return ID;
+}
+
+/// RecordVariableScope - Record scope for the variable declared by
+/// DeclareMI. DeclareMI must describe TargetInstrInfo::DECLARE. Record scopes
+/// for only inlined subroutine variables. Other variables's scopes are
+/// determined during RecordVariable().
+void DwarfDebug::RecordVariableScope(DIVariable &DV,
+ const MachineInstr *DeclareMI) {
+ if (TimePassesIsEnabled)
+ DebugTimer->startTimer();
+
+ DISubprogram SP(DV.getContext().getGV());
+
+ if (SP.isNull()) {
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+
+ return;
+ }
+
+ DenseMap<GlobalVariable *, DbgScope *>::iterator
+ I = DbgAbstractScopeMap.find(SP.getGV());
+ if (I != DbgAbstractScopeMap.end())
+ InlinedVariableScopes[DeclareMI] = I->second;
+
+ if (TimePassesIsEnabled)
+ DebugTimer->stopTimer();
+}