Newer
Older
if (CTy.isAppleBlockExtension())
AddUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1);
unsigned RLang = CTy.getRunTimeLang();
if (RLang)
AddUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class,
dwarf::DW_FORM_data1, RLang);
break;
}
default:
break;
}
// Add name if not anonymous or intermediate type.
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
AddString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
if (Tag == dwarf::DW_TAG_enumeration_type ||
Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) {
// Add size if non-zero (derived types might be zero-sized.)
if (Size)
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)
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
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())
1117
1118
1119
1120
1121
1122
1123
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
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.
///
Devang Patel
committed
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
DbgScope *DwarfDebug::getDbgScope(MDNode *N, const MachineInstr *MI) {
DbgScope *&Slot = DbgScopeMap[N];
if (Slot) return Slot;
DbgScope *Parent = NULL;
DIDescriptor Scope(N);
if (Scope.isCompileUnit()) {
return NULL;
} else if (Scope.isSubprogram()) {
DISubprogram SP(N);
DIDescriptor ParentDesc = SP.getContext();
if (!ParentDesc.isNull() && !ParentDesc.isCompileUnit())
Parent = getDbgScope(ParentDesc.getNode(), MI);
} else if (Scope.isLexicalBlock()) {
DILexicalBlock DB(N);
DIDescriptor ParentDesc = DB.getContext();
if (!ParentDesc.isNull())
Parent = getDbgScope(ParentDesc.getNode(), MI);
} else
assert (0 && "Unexpected scope info");
Slot = new DbgScope(Parent, DIDescriptor(N));
Slot->setFirstInsn(MI);
if (Parent)
Parent->AddScope(Slot);
else
// First function is top level function.
// FIXME - Dpatel - What is FunctionDbgScope ?
if (!FunctionDbgScope)
FunctionDbgScope = Slot;
return Slot;
}
/// getOrCreateScope - Returns the scope associated with the given descriptor.
/// FIXME - Remove this method.
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);
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
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();
}
Devang Patel
committed
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
/// ExtractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
// If scope information was extracted using .dbg intrinsics then there is not
// any need to extract these information by scanning each instruction.
if (!DbgScopeMap.empty())
return false;
// Scan each instruction and create scopes.
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown())
continue;
DebugLocTuple DLT = MF->getDebugLocTuple(DL);
if (!DLT.CompileUnit)
continue;
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
// into a scope DIE at the end.
DIDescriptor D(DLT.CompileUnit);
if (!D.isCompileUnit()) {
DbgScope *Scope = getDbgScope(DLT.CompileUnit, MInsn);
Scope->setLastInsn(MInsn);
}
}
}
// If a scope's last instruction is not set then use its child scope's
// last instruction as this scope's last instrunction.
for (DenseMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
DE = DbgScopeMap.end(); DI != DE; ++DI) {
assert (DI->second->getFirstInsn() && "Invalid first instruction!");
DI->second->FixInstructionMarkers();
assert (DI->second->getLastInsn() && "Invalid last instruction!");
}
// Each scope has first instruction and last instruction to mark beginning
// and end of a scope respectively. Create an inverse map that list scopes
// starts (and ends) with an instruction. One instruction may start (or end)
// multiple scopes.
for (DenseMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
DE = DbgScopeMap.end(); DI != DE; ++DI) {
DbgScope *S = DI->second;
assert (S && "DbgScope is missing!");
const MachineInstr *MI = S->getFirstInsn();
assert (MI && "DbgScope does not have first instruction!");
InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI);
if (IDI != DbgScopeBeginMap.end())
IDI->second.push_back(S);
else
DbgScopeBeginMap.insert(std::make_pair(MI,
SmallVector<DbgScope *, 2>(2, S)));
MI = S->getLastInsn();
assert (MI && "DbgScope does not have last instruction!");
IDI = DbgScopeEndMap.find(MI);
if (IDI != DbgScopeEndMap.end())
IDI->second.push_back(S);
else
DbgScopeEndMap.insert(std::make_pair(MI,
SmallVector<DbgScope *, 2>(2, S)));
}
return !DbgScopeMap.empty();
}
/// 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();
Devang Patel
committed
DbgScopeBeginMap.clear();
DbgScopeEndMap.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.