Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
AddUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size);
else {
// Add zero size if it is not a forward declaration.
if (CTy.isForwardDecl())
AddUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
else
AddUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0);
}
// Add source line info if available.
if (!CTy.isForwardDecl())
AddSourceLine(&Buffer, &CTy);
}
}
/// ConstructSubrangeDIE - Construct subrange DIE from DISubrange.
void DwarfDebug::ConstructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){
int64_t L = SR.getLo();
int64_t H = SR.getHi();
DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type);
AddDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy);
if (L)
AddSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L);
if (H)
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
Buffer.AddChild(DW_Subrange);
}
/// ConstructArrayTypeDIE - Construct array type DIE from DICompositeType.
void DwarfDebug::ConstructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
DICompositeType *CTy) {
Buffer.setTag(dwarf::DW_TAG_array_type);
if (CTy->getTag() == dwarf::DW_TAG_vector_type)
AddUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1);
// Emit derived type.
AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom());
DIArray Elements = CTy->getTypeArray();
// Construct an anonymous type for index type.
DIE IdxBuffer(dwarf::DW_TAG_base_type);
AddUInt(&IdxBuffer, dwarf::DW_AT_byte_size, 0, sizeof(int32_t));
AddUInt(&IdxBuffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
dwarf::DW_ATE_signed);
DIE *IndexTy = DW_Unit->AddDie(IdxBuffer);
// Add subranges to array type.
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
if (Element.getTag() == dwarf::DW_TAG_subrange_type)
ConstructSubrangeDIE(Buffer, DISubrange(Element.getNode()), IndexTy);
}
}
/// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
DIE *DwarfDebug::ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) {
DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator);
const char *Name = ETy->getName();
AddString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
int64_t Value = ETy->getEnumValue();
AddSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value);
return Enumerator;
}
/// CreateGlobalVariableDIE - Create new DIE using GV.
DIE *DwarfDebug::CreateGlobalVariableDIE(CompileUnit *DW_Unit,
const DIGlobalVariable &GV) {
DIE *GVDie = new DIE(dwarf::DW_TAG_variable);
AddString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
const char *LinkageName = GV.getLinkageName();
if (LinkageName) {
// Skip special LLVM prefix that is used to inform the asm printer to not
// emit usual symbol prefix before the symbol name. This happens for
// Objective-C symbol names and symbol whose name is replaced using GCC's
// __asm__ attribute.
if (LinkageName[0] == 1)
LinkageName = &LinkageName[1];
AddString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
if (!GV.isLocalToUnit())
AddUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
AddSourceLine(GVDie, &GV);
return GVDie;
}
/// CreateMemberDIE - Create new member DIE.
DIE *DwarfDebug::CreateMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){
DIE *MemberDie = new DIE(DT.getTag());
if (const char *Name = DT.getName())
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
AddString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom());
AddSourceLine(MemberDie, &DT);
uint64_t Size = DT.getSizeInBits();
uint64_t FieldSize = DT.getOriginalTypeSize();
if (Size != FieldSize) {
// Handle bitfield.
AddUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3);
AddUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits());
uint64_t Offset = DT.getOffsetInBits();
uint64_t FieldOffset = Offset;
uint64_t AlignMask = ~(DT.getAlignInBits() - 1);
uint64_t HiMark = (Offset + FieldSize) & AlignMask;
FieldOffset = (HiMark - FieldSize);
Offset -= FieldOffset;
// Maybe we need to work from the other end.
if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
AddUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset);
}
DIEBlock *Block = new DIEBlock();
AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
AddUInt(Block, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3);
AddBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, Block);
if (DT.isProtected())
AddUInt(MemberDie, dwarf::DW_AT_accessibility, 0,
dwarf::DW_ACCESS_protected);
else if (DT.isPrivate())
AddUInt(MemberDie, dwarf::DW_AT_accessibility, 0,
dwarf::DW_ACCESS_private);
return MemberDie;
}
/// CreateSubprogramDIE - Create new DIE using SP.
DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP,
Bill Wendling
committed
bool IsConstructor,
bool IsInlined) {
DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram);
const char * Name = SP.getName();
AddString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
const char *LinkageName = SP.getLinkageName();
if (LinkageName) {
// Skip special LLVM prefix that is used to inform the asm printer to not emit
// usual symbol prefix before the symbol name. This happens for Objective-C
// symbol names and symbol whose name is replaced using GCC's __asm__ attribute.
if (LinkageName[0] == 1)
LinkageName = &LinkageName[1];
AddString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
AddSourceLine(SPDie, &SP);
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
// Add prototyped tag, if C or ObjC.
unsigned Lang = SP.getCompileUnit().getLanguage();
if (Lang == dwarf::DW_LANG_C99 || Lang == dwarf::DW_LANG_C89 ||
Lang == dwarf::DW_LANG_ObjC)
AddUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
// Add Return Type.
unsigned SPTag = SPTy.getTag();
if (!IsConstructor) {
if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
AddType(DW_Unit, SPDie, SPTy);
else
AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode()));
}
if (!SP.isDefinition()) {
AddUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
// Add arguments. Do not add arguments for subprogram definition. They will
// be handled through RecordVariable.
if (SPTag == dwarf::DW_TAG_subroutine_type)
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
AddType(DW_Unit, Arg, DIType(Args.getElement(i).getNode()));
AddUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ??
SPDie->AddChild(Arg);
}
}
Bill Wendling
committed
if (!SP.isLocalToUnit() && !IsInlined)
AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
// DW_TAG_inlined_subroutine may refer to this DIE.
Slot = SPDie;
return SPDie;
}
/// FindCompileUnit - Get the compile unit for the given descriptor.
///
CompileUnit &DwarfDebug::FindCompileUnit(DICompileUnit Unit) const {
DenseMap<Value *, CompileUnit *>::const_iterator I =
assert(I != CompileUnitMap.end() && "Missing compile unit.");
return *I->second;
}
Bill Wendling
committed
/// CreateDbgScopeVariable - Create a new scope variable.
Bill Wendling
committed
DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
// Get the descriptor.
const DIVariable &VD = DV->getVariable();
// Translate tag to proper Dwarf tag. The result variable is dropped for
// now.
unsigned Tag;
switch (VD.getTag()) {
case dwarf::DW_TAG_return_variable:
return NULL;
case dwarf::DW_TAG_arg_variable:
Tag = dwarf::DW_TAG_formal_parameter;
break;
case dwarf::DW_TAG_auto_variable: // fall thru
default:
Tag = dwarf::DW_TAG_variable;
break;
}
// Define variable debug information entry.
DIE *VariableDie = new DIE(Tag);
const char *Name = VD.getName();
AddString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
// Add source line info if available.
AddSourceLine(VariableDie, &VD);
// Add variable type.
// FIXME: isBlockByrefVariable should be reformulated in terms of complex addresses instead.
Caroline Tice
committed
if (VD.isBlockByrefVariable())
AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
else
AddType(Unit, VariableDie, VD.getType());
// Add variable address.
if (!DV->isInlinedFnVar()) {
// Variables for abstract instances of inlined functions don't get a
// location.
MachineLocation Location;
Location.set(RI->getFrameRegister(*MF),
RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
Caroline Tice
committed
if (VD.hasComplexAddress())
AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
else if (VD.isBlockByrefVariable())
AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
Caroline Tice
committed
else
AddAddress(VariableDie, dwarf::DW_AT_location, Location);
}
return VariableDie;
}
/// getOrCreateScope - Returns the scope associated with the given descriptor.
///
DbgScope *DwarfDebug::getOrCreateScope(MDNode *N) {
DbgScope *&Slot = DbgScopeMap[N];
if (Slot) return Slot;
DbgScope *Parent = NULL;
// Don't create a new scope if we already created one for an inlined function.
DenseMap<const MDNode *, DbgScope *>::iterator
II = AbstractInstanceRootMap.find(N);
if (II != AbstractInstanceRootMap.end())
return LexicalScopeStack.back();
if (!Block.isNull()) {
DIDescriptor ParentDesc = Block.getContext();
Parent =
ParentDesc.isNull() ? NULL : getOrCreateScope(ParentDesc.getNode());
if (Parent)
Parent->AddScope(Slot);
else
// First function is top level function.
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);
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
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.
///
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.
// Get the subprogram die.
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);
}
ConstructDbgScope(RootScope, 0, 0, SPDie, ModuleCU);
}
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
///
void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) {
StringMap<DIE*>::iterator GI = Globals.find(MF->getFunction()->getName());
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);
}
}
/// 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 char *DirName,
const char *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));
void DwarfDebug::ConstructCompileUnit(MDNode *N) {
DICompileUnit DIUnit(N);
const char *FN = DIUnit.getFilename();
const char *Dir = DIUnit.getDirectory();
unsigned ID = GetOrCreateSourceID(Dir, 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());
AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
DIUnit.getLanguage());
AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
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);
if (const char *Flags = DIUnit.getFlags())
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);
// Use first compile unit marked as isMain as the compile unit
// for this module.
CompileUnits.push_back(Unit);
void DwarfDebug::ConstructGlobalVariableDIE(MDNode *N) {
DIGlobalVariable DI_GV(N);
// If debug information is malformed then ignore it.
if (DI_GV.Verify() == false)
return;
// Check for pre-existence.
DIE *&Slot = ModuleCU->getDieMapSlotFor(DI_GV.getNode());
DIE *VariableDie = CreateGlobalVariableDIE(ModuleCU, DI_GV);
// Add address.
DIEBlock *Block = new DIEBlock();
AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
AddObjectLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getMangledName(DI_GV.getGlobal()));
AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
// Add to map.
Slot = VariableDie;
// Expose as global. FIXME - need to check external flag.
ModuleCU->AddGlobal(DI_GV.getName(), VariableDie);
void DwarfDebug::ConstructSubprogram(MDNode *N) {
DISubprogram SP(N);
Bill Wendling
committed
// Check for pre-existence.
if (!SP.isDefinition())
// This is a method declaration which will be handled while constructing
// class type.
Bill Wendling
committed
DIE *SubprogramDie = CreateSubprogramDIE(ModuleCU, SP);
Bill Wendling
committed
// Add to map.
Slot = SubprogramDie;
ModuleCU->AddGlobal(SP.getName(), SubprogramDie);
/// BeginModule - Emit all Dwarf sections that should come prior to the
/// content. Create global DIEs and emit initial debug info sections.
/// This is inovked by the target AsmPrinter.
void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) {
this->M = M;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
// Create all the compile unit DIEs.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I)
if (CompileUnits.empty()) {
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
// If main compile unit for this module is not seen than randomly
// select first compile unit.
// 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 (DbgFinder.global_variable_count() == 0
&& DbgFinder.subprogram_count() == 0) {
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return;
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
E = DbgFinder.global_variable_end(); I != E; ++I)
ConstructGlobalVariableDIE(*I);
// Create DIEs for each of the externally visible subprograms.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
MMI = mmi;
shouldEmit = true;
MMI->setDebugInfoAvailability(true);
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
// Print out .file directives to specify files for .loc directives. These are
// printed out early so that they precede any .loc directives.
if (MAI->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.str());
// 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->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
// End text sections.
for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
Asm->OutStreamer.SwitchSection(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);
Bill Wendling
committed
// 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, DLT.CompileUnit);
O << '\n';
}
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.
Chris Lattner
committed
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 the DbgScope for abstract instances.
for (SmallVector<DbgScope *, 32>::iterator
I = AbstractInstanceRootList.begin(),
E = AbstractInstanceRootList.end(); I != E; ++I)
ConstructFunctionDbgScope(*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();
FunctionDbgScope = NULL;
LexicalScopeStack.clear();
AbstractInstanceRootList.clear();
AbstractInstanceRootMap.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();
/// 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,
MDNode *Scope) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
DICompileUnit CU(Scope);
unsigned Src = GetOrCreateSourceID(CU.getDirectory(),
CU.getFilename());
unsigned ID = MMI->NextLabelID();
Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
/// timed. Look up the source id with the given directory and source file
/// names. If none currently exists, create a new id and insert it in the
/// SourceIds map. This can update DirectoryNames and SourceFileNames maps as
/// well.
unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName,
const std::string &FileName) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return SrcId;
/// RecordRegionStart - Indicate the start of a region.
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned ID = MMI->NextLabelID();
if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
LexicalScopeStack.push_back(Scope);
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// RecordRegionEnd - Indicate the end of a region.
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned ID = MMI->NextLabelID();
Scope->setEndLabelID(ID);
Devang Patel
committed
// FIXME : region.end() may not be in the last basic block.
// For now, do not pop last lexical scope because next basic
// block may start new inlined function's body.
unsigned LSSize = LexicalScopeStack.size();
if (LSSize != 0 && LSSize != 1)
LexicalScopeStack.pop_back();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// RecordVariable - Indicate the declaration of a local variable.
void DwarfDebug::RecordVariable(MDNode *N, unsigned FrameIndex) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
DbgScope *Scope = NULL;
bool InlinedFnVar = false;
if (Desc.getTag() == dwarf::DW_TAG_variable)
Scope = getOrCreateScope(DIGlobalVariable(N).getContext().getNode());
else {
bool InlinedVar = false;
MDNode *Context = DIVariable(N).getContext().getNode();
DISubprogram SP(Context);
if (!SP.isNull()) {
// SP is inserted into DbgAbstractScopeMap when inlined function
// start was recorded by RecordInlineFnStart.
DenseMap<MDNode *, DbgScope *>::iterator
I = DbgAbstractScopeMap.find(SP.getNode());
if (I != DbgAbstractScopeMap.end()) {
InlinedVar = true;
Scope = I->second;
}
}
assert(Scope && "Unable to find the variable's scope");
DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex, InlinedFnVar);
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 (!MAI->doesDwarfUsesInlineInfoSection())
if (TimePassesIsEnabled)
DebugTimer->startTimer();
MDNode *Node = SP.getNode();
DenseMap<const MDNode *, DbgScope *>::iterator
II = AbstractInstanceRootMap.find(Node);
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(Node));
Bill Wendling
committed
// Get the compile unit context.
SPDie = CreateSubprogramDIE(ModuleCU, 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);
Bill Wendling
committed
// Keep track of the abstract scope for this function.
Bill Wendling
committed
AbstractInstanceRootList.push_back(Scope);
}
Bill Wendling
committed
// Create a concrete inlined instance for this inlined function.
DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(Node));
DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, Origin);
AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, ModuleCU->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);
LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
// Keep track of the concrete scope that's inlined into this function.
DenseMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
SI = DbgConcreteScopeMap.find(Node);
Bill Wendling
committed
if (SI == DbgConcreteScopeMap.end())