"llvm/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "5f08ec854fc03a3b3780c4d704837d22be9f2ace"
Newer
Older
FunctionDbgScope = Slot;
return Slot;
}
/// ConstructDbgScope - Construct the components of a scope.
///
void DwarfDebug::ConstructDbgScope(DbgScope *ParentScope,
unsigned ParentStartID,
unsigned ParentEndID,
DIE *ParentDie, CompileUnit *Unit) {
// Add variables to scope.
SmallVector<DbgVariable *, 8> &Variables = ParentScope->getVariables();
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
Bill Wendling
committed
DIE *VariableDie = CreateDbgScopeVariable(Variables[i], Unit);
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
if (VariableDie) ParentDie->AddChild(VariableDie);
}
// Add concrete instances to scope.
SmallVector<DbgConcreteScope *, 8> &ConcreteInsts =
ParentScope->getConcreteInsts();
for (unsigned i = 0, N = ConcreteInsts.size(); i < N; ++i) {
DbgConcreteScope *ConcreteInst = ConcreteInsts[i];
DIE *Die = ConcreteInst->getDie();
unsigned StartID = ConcreteInst->getStartLabelID();
unsigned EndID = ConcreteInst->getEndLabelID();
// Add the scope bounds.
if (StartID)
AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("label", StartID));
else
AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("func_begin", SubprogramCount));
if (EndID)
AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("label", EndID));
else
AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("func_end", SubprogramCount));
ParentDie->AddChild(Die);
}
// Add nested scopes.
SmallVector<DbgScope *, 4> &Scopes = ParentScope->getScopes();
for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
// Define the Scope debug information entry.
DbgScope *Scope = Scopes[j];
unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
// Ignore empty scopes.
if (StartID == EndID && StartID != 0) continue;
// Do not ignore inlined scopes even if they don't have any variables or
// scopes.
if (Scope->getScopes().empty() && Scope->getVariables().empty() &&
Scope->getConcreteInsts().empty())
continue;
if (StartID == ParentStartID && EndID == ParentEndID) {
// Just add stuff to the parent scope.
ConstructDbgScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit);
} else {
DIE *ScopeDie = new DIE(dwarf::DW_TAG_lexical_block);
// Add the scope bounds.
if (StartID)
AddLabel(ScopeDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("label", StartID));
else
AddLabel(ScopeDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("func_begin", SubprogramCount));
if (EndID)
AddLabel(ScopeDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("label", EndID));
else
AddLabel(ScopeDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("func_end", SubprogramCount));
// Add the scope's contents.
ConstructDbgScope(Scope, StartID, EndID, ScopeDie, Unit);
ParentDie->AddChild(ScopeDie);
}
}
}
/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
///
Bill Wendling
committed
void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope,
bool AbstractScope) {
// Exit if there is no root scope.
if (!RootScope) return;
DIDescriptor Desc = RootScope->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");
Bill Wendling
committed
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);
}
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
ConstructDbgScope(RootScope, 0, 0, SPDie, Unit);
}
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
///
void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) {
const char *FnName = MF->getFunction()->getNameStart();
if (MainCU) {
StringMap<DIE*> &Globals = MainCU->getGlobals();
StringMap<DIE*>::iterator GI = Globals.find(FnName);
if (GI != Globals.end()) {
DIE *SPDie = GI->second;
// 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);
return;
}
} else {
for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) {
CompileUnit *Unit = CompileUnits[i];
StringMap<DIE*> &Globals = Unit->getGlobals();
StringMap<DIE*>::iterator GI = Globals.find(FnName);
if (GI != Globals.end()) {
DIE *SPDie = GI->second;
// 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);
return;
}
}
}
#if 0
// FIXME: This is causing an abort because C++ mangled names are compared with
// their unmangled counterparts. See PR2885. Don't do this assert.
assert(0 && "Couldn't find DIE for machine function!");
#endif
}
Bill Wendling
committed
/// 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);
Bill Wendling
committed
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);
Bill Wendling
committed
DenseMap<std::pair<unsigned, unsigned>, unsigned>::iterator SI =
SourceIdMap.find(std::make_pair(DId, FId));
if (SI != SourceIdMap.end())
return SI->second;
Bill Wendling
committed
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));
Bill Wendling
committed
return SrcId;
}
Bill Wendling
committed
void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) {
DICompileUnit DIUnit(GV);
std::string Dir, FN, Prod;
unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir),
DIUnit.getFilename(FN));
Bill Wendling
committed
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);
Bill Wendling
committed
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);
Bill Wendling
committed
std::string Flags;
DIUnit.getFlags(Flags);
if (!Flags.empty())
AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
Bill Wendling
committed
unsigned RVer = DIUnit.getRunTimeVersion();
if (RVer)
AddUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
Bill Wendling
committed
CompileUnit *Unit = new CompileUnit(ID, Die);
if (DIUnit.isMain()) {
assert(!MainCU && "Multiple main compile units are found!");
MainCU = Unit;
Bill Wendling
committed
CompileUnitMap[DIUnit.getGV()] = Unit;
CompileUnits.push_back(Unit);
}
Bill Wendling
committed
/// 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");
Bill Wendling
committed
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);
}
Bill Wendling
committed
bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) {
DIGlobalVariable DI_GV(GV);
CompileUnit *DW_Unit = MainCU;
if (!DW_Unit)
DW_Unit = &FindCompileUnit(DI_GV.getCompileUnit());
Bill Wendling
committed
// Check for pre-existence.
DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV());
if (Slot)
return false;
Bill Wendling
committed
DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV);
Bill Wendling
committed
// 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);
Bill Wendling
committed
// Add to map.
Slot = VariableDie;
Bill Wendling
committed
// Add to context owner.
DW_Unit->getDie()->AddChild(VariableDie);
Bill Wendling
committed
// Expose as global. FIXME - need to check external flag.
std::string Name;
DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie);
return true;
}
Bill Wendling
committed
/// 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;
Bill Wendling
committed
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");
Bill Wendling
committed
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));
Bill Wendling
committed
return Result;
Bill Wendling
committed
bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) {
DISubprogram SP(GV);
CompileUnit *Unit = MainCU;
if (!Unit)
Unit = &FindCompileUnit(SP.getCompileUnit());
Bill Wendling
committed
// Check for pre-existence.
DIE *&Slot = Unit->getDieMapSlotFor(GV);
if (Slot)
return false;
Bill Wendling
committed
if (!SP.isDefinition())
// This is a method declaration which will be handled while constructing
// class type.
return false;
Bill Wendling
committed
DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP);
Bill Wendling
committed
// Add to map.
Slot = SubprogramDie;
Bill Wendling
committed
// Add to context owner.
Unit->getDie()->AddChild(SubprogramDie);
Bill Wendling
committed
// Expose as global.
std::string Name;
Unit->AddGlobal(SP.getName(Name), SubprogramDie);
return true;
}
Bill Wendling
committed
/// 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;
Bill Wendling
committed
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");
Bill Wendling
committed
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;
Bill Wendling
committed
/// 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;
}
Bill Wendling
committed
// Create DIEs for each of the externally visible global variables.
bool globalDIEs = ConstructGlobalVariableDIEs();
Bill Wendling
committed
// Create DIEs for each of the externally visible subprograms.
bool subprogramDIEs = ConstructSubprograms();
Bill Wendling
committed
// 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();
Bill Wendling
committed
return;
}
Bill Wendling
committed
MMI = mmi;
shouldEmit = true;
MMI->setDebugInfoAvailability(true);
Bill Wendling
committed
// Prime section data.
SectionMap.insert(TAI->getTextSection());
Bill Wendling
committed
// 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();
}
}
Bill Wendling
committed
// Emit initial sections
EmitInitial();
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
/// EndModule - Emit all Dwarf sections that should come after the content.
Bill Wendling
committed
void DwarfDebug::EndModule() {
if (!ShouldEmitDwarfDebug())
return;
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
// Standard sections final addresses.
Asm->SwitchToSection(TAI->getTextSection());
EmitLabel("text_end", 0);
Asm->SwitchToSection(TAI->getDataSection());
EmitLabel("data_end", 0);
Bill Wendling
committed
// End text sections.
for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
Asm->SwitchToSection(SectionMap[i]);
EmitLabel("section_end", i);
}
Bill Wendling
committed
// Emit common frame information.
EmitCommonDebugFrame();
Bill Wendling
committed
// Emit function debug frame information
for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
E = DebugFrames.end(); I != E; ++I)
EmitFunctionDebugFrame(*I);
Bill Wendling
committed
// Compute DIE offsets and sizes.
SizeAndOffsets();
Bill Wendling
committed
// Emit all the DIEs into a debug info section
EmitDebugInfo();
Bill Wendling
committed
// Corresponding abbreviations into a abbrev section.
EmitAbbreviations();
Bill Wendling
committed
// Emit source line correspondence into a debug line section.
EmitDebugLines();
Bill Wendling
committed
// Emit info into a debug pubnames section.
EmitDebugPubNames();
Bill Wendling
committed
// Emit info into a debug str section.
EmitDebugStr();
Bill Wendling
committed
// Emit info into a debug loc section.
EmitDebugLoc();
Bill Wendling
committed
// Emit info into a debug aranges section.
EmitDebugARanges();
Bill Wendling
committed
// Emit info into a debug ranges section.
EmitDebugRanges();
Bill Wendling
committed
// Emit info into a debug macinfo section.
EmitDebugMacInfo();
Bill Wendling
committed
// Emit inline info.
EmitDebugInlineInfo();
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
Bill Wendling
committed
/// BeginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::BeginFunction(MachineFunction *MF) {
this->MF = MF;
Bill Wendling
committed
if (!ShouldEmitDwarfDebug()) return;
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
// Begin accumulating function debug information.
MMI->BeginFunction(MF);
Bill Wendling
committed
// Assumes in correct section after the entry point.
EmitLabel("func_begin", ++SubprogramCount);
Bill Wendling
committed
// 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);
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
/// EndFunction - Gather and emit post-function debug information.
Bill Wendling
committed
void DwarfDebug::EndFunction(MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
// Define end label for subprogram.
EmitLabel("func_end", SubprogramCount);
Bill Wendling
committed
// 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());
}
Bill Wendling
committed
// Construct the DbgScope for abstract instances.
for (SmallVector<DbgScope *, 32>::iterator
I = AbstractInstanceRootList.begin(),
E = AbstractInstanceRootList.end(); I != E; ++I)
ConstructFunctionDbgScope(*I, true);
Bill Wendling
committed
// 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);
Bill Wendling
committed
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
Bill Wendling
committed
// Clear debug info
if (FunctionDbgScope) {
delete FunctionDbgScope;
DbgScopeMap.clear();
DbgAbstractScopeMap.clear();
DbgConcreteScopeMap.clear();
InlinedVariableScopes.clear();
FunctionDbgScope = NULL;
LexicalScopeStack.clear();
AbstractInstanceRootList.clear();
}
Bill Wendling
committed
Lines.clear();
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
/// 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();
Bill Wendling
committed
CompileUnit *Unit = CompileUnitMap[V];
assert(Unit && "Unable to find CompileUnit");
unsigned ID = MMI->NextLabelID();
Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID));
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
return ID;
}
Bill Wendling
committed
/// 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();
Bill Wendling
committed
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));
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
return ID;
Bill Wendling
committed
/// 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();
Bill Wendling
committed
unsigned SrcId = GetOrCreateSourceID(DirName, FileName);
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return SrcId;
Bill Wendling
committed
/// RecordRegionStart - Indicate the start of a region.
unsigned DwarfDebug::RecordRegionStart(GlobalVariable *V) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
DbgScope *Scope = getOrCreateScope(V);
unsigned ID = MMI->NextLabelID();
if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
LexicalScopeStack.push_back(Scope);
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
return ID;
Bill Wendling
committed
/// RecordRegionEnd - Indicate the end of a region.
unsigned DwarfDebug::RecordRegionEnd(GlobalVariable *V) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
DbgScope *Scope = getOrCreateScope(V);
unsigned ID = MMI->NextLabelID();
Scope->setEndLabelID(ID);
if (LexicalScopeStack.size() != 0)
LexicalScopeStack.pop_back();
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
return ID;
}
Bill Wendling
committed
/// RecordVariable - Indicate the declaration of a local variable.
void DwarfDebug::RecordVariable(GlobalVariable *GV, unsigned FrameIndex,
const MachineInstr *MI) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
DIDescriptor Desc(GV);
DbgScope *Scope = NULL;
bool InlinedFnVar = false;
Bill Wendling
committed
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);
Bill Wendling
committed
if (SI != InlinedVariableScopes.end()) {
// or GV is an inlined local variable.
Scope = SI->second;
} else {
DIVariable DV(GV);
GlobalVariable *V = DV.getContext().getGV();
Bill Wendling
committed
// FIXME: The code that checks for the inlined local variable is a hack!
DenseMap<const GlobalVariable *, DbgScope *>::iterator
AI = AbstractInstanceRootMap.find(V);
Bill Wendling
committed
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);
Bill Wendling
committed
if (IP != InlinedParamMap.end() && IP->second.count(GV) > 0) {
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return;
}
Bill Wendling
committed
// 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);
}
}
}
Bill Wendling
committed
assert(Scope && "Unable to find the variable's scope");
DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex, InlinedFnVar);
Scope->AddVariable(DV);
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
/// RecordInlinedFnStart - Indicate the start of inlined subroutine.
unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
unsigned Line, unsigned Col) {
unsigned LabelID = MMI->NextLabelID();
Bill Wendling
committed
if (!TAI->doesDwarfUsesInlineInfoSection())
return LabelID;
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
GlobalVariable *GV = SP.getGV();
DenseMap<const GlobalVariable *, DbgScope *>::iterator
II = AbstractInstanceRootMap.find(GV);
Bill Wendling
committed
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));
Bill Wendling
committed
// Get the compile unit context.
CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
DIE *SPDie = Unit->getDieMapSlotFor(GV);
if (!SPDie)
SPDie = CreateSubprogramDIE(Unit, SP, false, true);
Bill Wendling
committed
// 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);
Bill Wendling
committed
// Keep track of the abstract scope for this function.
DbgAbstractScopeMap[GV] = Scope;
Bill Wendling
committed
AbstractInstanceRootMap[GV] = Scope;
AbstractInstanceRootList.push_back(Scope);
}
Bill Wendling
committed
// 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);
Bill Wendling
committed
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);
Bill Wendling
committed
ConcreteScope->setDie(ScopeDie);
ConcreteScope->setStartLabelID(LabelID);
MMI->RecordUsedDbgLabel(LabelID);
Bill Wendling
committed
LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
LexicalScopeStack.push_back(ConcreteScope);
Bill Wendling
committed
// Keep track of the concrete scope that's inlined into this function.
DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
SI = DbgConcreteScopeMap.find(GV);
Bill Wendling
committed
if (SI == DbgConcreteScopeMap.end())
DbgConcreteScopeMap[GV].push_back(ConcreteScope);
else
SI->second.push_back(ConcreteScope);
Bill Wendling
committed
// Track the start label for this inlined function.
DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator
I = InlineInfo.find(GV);
Bill Wendling
committed
if (I == InlineInfo.end())
InlineInfo[GV].push_back(LabelID);
else
I->second.push_back(LabelID);
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
return LabelID;
Bill Wendling
committed
/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
if (!TAI->doesDwarfUsesInlineInfoSection())
return 0;
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Bill Wendling
committed
GlobalVariable *GV = SP.getGV();
DenseMap<GlobalVariable *, SmallVector<DbgScope *, 8> >::iterator
I = DbgConcreteScopeMap.find(GV);
Bill Wendling
committed
if (I == DbgConcreteScopeMap.end()) {
// FIXME: Can this situation actually happen? And if so, should it?
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
return 0;
}
Bill Wendling
committed
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();
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return ID;
Bill Wendling
committed
/// 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();
Bill Wendling
committed
}
Bill Wendling
committed
DenseMap<GlobalVariable *, DbgScope *>::iterator
I = DbgAbstractScopeMap.find(SP.getGV());
if (I != DbgAbstractScopeMap.end())
InlinedVariableScopes[DeclareMI] = I->second;
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
Bill Wendling
committed
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
/// 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);
Bill Wendling
committed
const SmallVector<DIEValue*, 32> &Values = Die->getValues();
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
Bill Wendling
committed
// 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());
Bill Wendling
committed
// Size the DIE children if any.
if (!Children.empty()) {
assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
"Children flag not set");
Bill Wendling
committed
for (unsigned j = 0, M = Children.size(); j < M; ++j)
Offset = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
Bill Wendling
committed
// End of children marker.
Offset += sizeof(int8_t);
}
Die->setSize(Offset - Die->getOffset());
return Offset;
Bill Wendling
committed
/// 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)
Bill Wendling
committed
// Process base compile unit.
if (MainCU) {
SizeAndOffsetDie(MainCU->getDie(), Offset, true);
CompileUnitOffsets[MainCU] = 0;
return;
}
Bill Wendling
committed
// Process all compile units.
unsigned PrevOffset = 0;
Bill Wendling
committed
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.
}
Bill Wendling
committed
/// 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;
Bill Wendling
committed
// Dwarf sections base addresses.
if (TAI->doesDwarfRequireFrameSection()) {
Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
EmitLabel("section_debug_frame", 0);
}
Bill Wendling
committed
Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
EmitLabel("section_info", 0);
Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection());
EmitLabel("section_abbrev", 0);
Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
EmitLabel("section_aranges", 0);
Bill Wendling
committed
if (TAI->doesSupportMacInfoSection()) {
Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());