Newer
Older
DIE *GVDie = new DIE(dwarf::DW_TAG_variable);
addString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
StringRef LinkageName = GV.getLinkageName();
if (!LinkageName.empty()) {
// 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.substr(1);
addString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
addType(DW_Unit, GVDie, GV.getType());
if (!GV.isLocalToUnit())
addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
addSourceLine(GVDie, &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(GV.getGlobal()));
addBlock(GVDie, dwarf::DW_AT_location, 0, Block);
return GVDie;
}
/// createMemberDIE - Create new member DIE.
DIE *DwarfDebug::createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){
DIE *MemberDie = new DIE(DT.getTag());
StringRef Name = DT.getName();
if (!Name.empty())
addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
addType(DW_Unit, MemberDie, DT.getTypeDerivedFrom());
addSourceLine(MemberDie, &DT);
Devang Patel
committed
DIEBlock *MemLocationDie = new DIEBlock();
addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
Devang Patel
committed
uint64_t Size = DT.getSizeInBits();
Devang Patel
committed
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);
Devang Patel
committed
// Here WD_AT_data_member_location points to the anonymous
// field that includes this bit field.
addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3);
Devang Patel
committed
} else
// This is not a bitfield.
addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3);
Devang Patel
committed
addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie);
if (DT.isProtected())
Devang Patel
committed
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag,
dwarf::DW_ACCESS_protected);
else if (DT.isPrivate())
Devang Patel
committed
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag,
dwarf::DW_ACCESS_private);
Devang Patel
committed
else if (DT.getTag() == dwarf::DW_TAG_inheritance)
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag,
dwarf::DW_ACCESS_public);
if (DT.isVirtual())
addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag,
dwarf::DW_VIRTUALITY_virtual);
return MemberDie;
}
/// createRawSubprogramDIE - Create new partially incomplete DIE. This is
/// a helper routine used by createMemberSubprogramDIE and
/// createSubprogramDIE.
DIE *DwarfDebug::createRawSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP) {
DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram);
addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName());
StringRef LinkageName = SP.getLinkageName();
if (!LinkageName.empty()) {
// 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.substr(1);
addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
addSourceLine(SPDie, &SP);
// 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.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
Devang Patel
committed
if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
else
addType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode()));
Devang Patel
committed
unsigned VK = SP.getVirtuality();
if (VK) {
addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK);
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
addUInt(Block, 0, dwarf::DW_FORM_data1, SP.getVirtualIndex());
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block);
ContainingTypeMap.insert(std::make_pair(SPDie, WeakVH(SP.getContainingType().getNode())));
}
return SPDie;
}
/// createMemberSubprogramDIE - Create new member DIE using SP. This routine
/// always returns a die with DW_AT_declaration attribute.
DIE *DwarfDebug::createMemberSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP) {
DIE *SPDie = ModuleCU->getDIE(SP.getNode());
if (!SPDie)
SPDie = createSubprogramDIE(DW_Unit, SP);
// If SPDie has DW_AT_declaration then reuse it.
if (!SP.isDefinition())
return SPDie;
// Otherwise create new DIE for the declaration. First push definition
// DIE at the top level.
if (TopLevelDIEs.insert(SPDie))
TopLevelDIEsVector.push_back(SPDie);
SPDie = createRawSubprogramDIE(DW_Unit, SP);
// Add arguments.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
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);
}
addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
return SPDie;
}
/// createSubprogramDIE - Create new DIE using SP.
DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP) {
DIE *SPDie = ModuleCU->getDIE(SP.getNode());
if (SPDie)
return SPDie;
SPDie = createRawSubprogramDIE(DW_Unit, SP);
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 while processing variables.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
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);
}
}
// DW_TAG_inlined_subroutine may refer to this DIE.
DW_Unit->insertDIE(SP.getNode(), 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;
}
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
/// createDbgScopeVariable - Create a new scope variable.
///
DIE *DwarfDebug::createDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
// Get the descriptor.
const DIVariable &VD = DV->getVariable();
StringRef Name = VD.getName();
if (Name.empty())
return NULL;
// 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);
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.
if (VD.isBlockByrefVariable())
addType(Unit, VariableDie, getBlockByrefType(VD.getType(), Name));
else
addType(Unit, VariableDie, VD.getType());
// Add variable address.
// Variables for abstract instances of inlined functions don't get a
// location.
MachineLocation Location;
unsigned FrameReg;
int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), FrameReg);
Location.set(FrameReg, Offset);
if (VD.hasComplexAddress())
addComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
else if (VD.isBlockByrefVariable())
addBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
else
addAddress(VariableDie, dwarf::DW_AT_location, Location);
return VariableDie;
}
/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction.
/// Initialize scope and update scope hierarchy.
DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
MDNode *InlinedAt) {
assert (N && "Invalid Scope encoding!");
assert (MI && "Missing machine instruction!");
bool GetConcreteScope = (MI && InlinedAt);
Devang Patel
committed
Devang Patel
committed
if (InlinedAt)
NScope = DbgScopeMap.lookup(InlinedAt);
else
NScope = DbgScopeMap.lookup(N);
assert (NScope && "Unable to find working scope!");
if (NScope->getFirstInsn())
return NScope;
DbgScope *Parent = NULL;
if (GetConcreteScope) {
DILocation IL(InlinedAt);
Parent = getUpdatedDbgScope(IL.getScope().getNode(), MI,
IL.getOrigLocation().getNode());
assert (Parent && "Unable to find Parent scope!");
NScope->setParent(Parent);
Parent->addScope(NScope);
} else if (DIDescriptor(N).isLexicalBlock()) {
DILexicalBlock DB(N);
if (!DB.getContext().isNull()) {
Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt);
NScope->setParent(Parent);
Parent->addScope(NScope);
Devang Patel
committed
NScope->setFirstInsn(MI);
Devang Patel
committed
if (!Parent && !InlinedAt) {
StringRef SPName = DISubprogram(N).getLinkageName();
if (SPName == MF->getFunction()->getName())
CurrentFnDbgScope = NScope;
}
if (GetConcreteScope) {
ConcreteScopes[InlinedAt] = NScope;
getOrCreateAbstractScope(N);
}
Devang Patel
committed
Devang Patel
committed
return NScope;
Devang Patel
committed
}
DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) {
assert (N && "Invalid Scope encoding!");
DbgScope *AScope = AbstractScopes.lookup(N);
if (AScope)
return AScope;
DbgScope *Parent = NULL;
DIDescriptor Scope(N);
if (Scope.isLexicalBlock()) {
DILexicalBlock DB(N);
DIDescriptor ParentDesc = DB.getContext();
if (!ParentDesc.isNull())
Parent = getOrCreateAbstractScope(ParentDesc.getNode());
}
AScope = new DbgScope(Parent, DIDescriptor(N), NULL);
if (Parent)
Parent->addScope(AScope);
AScope->setAbstractScope();
AbstractScopes[N] = AScope;
if (DIDescriptor(N).isSubprogram())
AbstractScopesList.push_back(AScope);
return AScope;
}
Devang Patel
committed
/// updateSubprogramScopeDIE - Find DIE for the given subprogram and
/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes.
/// If there are global variables in this scope then create and insert
/// DIEs for these variables.
DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
DIE *SPDie = ModuleCU->getDIE(SPNode);
assert (SPDie && "Unable to find subprogram DIE!");
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);
if (!DISubprogram(SPNode).isLocalToUnit())
addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
// If there are global variables at this scope then add their dies.
for (SmallVector<WeakVH, 4>::iterator SGI = ScopedGVs.begin(),
SGE = ScopedGVs.end(); SGI != SGE; ++SGI) {
MDNode *N = dyn_cast_or_null<MDNode>(*SGI);
if (!N) continue;
DIGlobalVariable GV(N);
if (GV.getContext().getNode() == SPNode) {
DIE *ScopedGVDie = createGlobalVariableDIE(ModuleCU, GV);
SPDie->addChild(ScopedGVDie);
/// constructLexicalScope - Construct new DW_TAG_lexical_block
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
// Ignore empty scopes.
if (StartID == EndID && StartID != 0)
return NULL;
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
: DWLabel("func_begin", SubprogramCount));
addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
: DWLabel("func_end", SubprogramCount));
return ScopeDIE;
}
/// constructInlinedScopeDIE - This scope represents inlined body of
/// a function. Construct DIE to represent this concrete inlined copy
/// of the function.
DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
assert (StartID && "Invalid starting label for an inlined scope!");
assert (EndID && "Invalid end label for an inlined scope!");
// Ignore empty scopes.
if (StartID == EndID && StartID != 0)
return NULL;
DIScope DS(Scope->getScopeNode());
if (DS.isNull())
return NULL;
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
DISubprogram InlinedSP = getDISubprogram(DS.getNode());
DIE *OriginDIE = ModuleCU->getDIE(InlinedSP.getNode());
assert (OriginDIE && "Unable to find Origin DIE!");
addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, OriginDIE);
addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("label", StartID));
addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("label", EndID));
InlinedSubprogramDIEs.insert(OriginDIE);
// Track the start label for this inlined function.
ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
I = InlineInfo.find(InlinedSP.getNode());
if (I == InlineInfo.end()) {
InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartID,
ScopeDIE));
InlinedSPNodes.push_back(InlinedSP.getNode());
} else
I->second.push_back(std::make_pair(StartID, ScopeDIE));
StringPool.insert(InlinedSP.getName());
StringPool.insert(InlinedSP.getLinkageName());
DILocation DL(Scope->getInlinedAt());
addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, ModuleCU->getID());
addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
return ScopeDIE;
}
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV,
DbgScope *Scope, CompileUnit *Unit) {
// Get the descriptor.
const DIVariable &VD = DV->getVariable();
StringRef Name = VD.getName();
if (Name.empty())
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
// 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);
DIE *AbsDIE = NULL;
if (DbgVariable *AV = DV->getAbstractVariable())
AbsDIE = AV->getDIE();
if (AbsDIE) {
DIScope DS(Scope->getScopeNode());
DISubprogram InlinedSP = getDISubprogram(DS.getNode());
DIE *OriginSPDIE = ModuleCU->getDIE(InlinedSP.getNode());
assert (OriginSPDIE && "Unable to find Origin DIE for the SP!");
DIE *AbsDIE = DV->getAbstractVariable()->getDIE();
assert (AbsDIE && "Unable to find Origin DIE for the Variable!");
addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, AbsDIE);
}
else {
addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
addSourceLine(VariableDie, &VD);
// Add variable type.
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
// addresses instead.
if (VD.isBlockByrefVariable())
addType(Unit, VariableDie, getBlockByrefType(VD.getType(), Name));
addType(Unit, VariableDie, VD.getType());
}
// Add variable address.
if (!Scope->isAbstractScope()) {
MachineLocation Location;
unsigned FrameReg;
int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), FrameReg);
Location.set(FrameReg, Offset);
if (VD.hasComplexAddress())
addComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
else if (VD.isBlockByrefVariable())
addBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
addAddress(VariableDie, dwarf::DW_AT_location, Location);
}
DV->setDIE(VariableDie);
return VariableDie;
}
void DwarfDebug::addPubTypes(DISubprogram SP) {
DICompositeType SPTy = SP.getType();
unsigned SPTag = SPTy.getTag();
if (SPTag != dwarf::DW_TAG_subroutine_type)
return;
DIArray Args = SPTy.getTypeArray();
if (Args.isNull())
return;
for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) {
DIType ATy(Args.getElement(i).getNode());
if (ATy.isNull())
continue;
DICompositeType CATy = getDICompositeType(ATy);
if (!CATy.isNull() && !CATy.getName().empty()) {
if (DIEEntry *Entry = ModuleCU->getDIEEntry(CATy.getNode()))
ModuleCU->addGlobalType(CATy.getName(), Entry->getEntry());
}
}
}
/// constructScopeDIE - Construct a DIE for this scope.
DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
if (!Scope)
return NULL;
DIScope DS(Scope->getScopeNode());
if (DS.isNull())
return NULL;
DIE *ScopeDIE = NULL;
if (Scope->getInlinedAt())
ScopeDIE = constructInlinedScopeDIE(Scope);
else if (DS.isSubprogram()) {
if (Scope->isAbstractScope())
ScopeDIE = ModuleCU->getDIE(DS.getNode());
ScopeDIE = updateSubprogramScopeDIE(DS.getNode());
ScopeDIE = constructLexicalScopeDIE(Scope);
if (!ScopeDIE) return NULL;
}
// Add variables to scope.
SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
DIE *VariableDIE = constructVariableDIE(Variables[i], Scope, ModuleCU);
ScopeDIE->addChild(VariableDIE);
}
// Add nested scopes.
SmallVector<DbgScope *, 4> &Scopes = Scope->getScopes();
for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
// Define the Scope debug information entry.
DIE *NestedDIE = constructScopeDIE(Scopes[j]);
ScopeDIE->addChild(NestedDIE);
if (DS.isSubprogram())
addPubTypes(DISubprogram(DS.getNode()));
return ScopeDIE;
/// 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(StringRef DirName, StringRef 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) {
StringRef FN = DIUnit.getFilename();
StringRef 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,
addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
StringRef Flags = DIUnit.getFlags();
if (!Flags.empty())
addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
unsigned RVer = DIUnit.getRunTimeVersion();
if (RVer)
addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
CompileUnit *Unit = new CompileUnit(ID, Die);
// Use first compile unit marked as isMain as the compile unit
// for this module.
CompileUnits.push_back(Unit);
void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
// If debug information is malformed then ignore it.
if (DI_GV.Verify() == false)
return;
// Check for pre-existence.
if (ModuleCU->getDIE(DI_GV.getNode()))
DIE *VariableDie = createGlobalVariableDIE(ModuleCU, DI_GV);
ModuleCU->insertDIE(N, VariableDie);
if (TopLevelDIEs.insert(VariableDie))
TopLevelDIEsVector.push_back(VariableDie);
// Expose as global. FIXME - need to check external flag.
ModuleCU->addGlobal(DI_GV.getName(), VariableDie);
if (GTy.isCompositeType() && !GTy.getName().empty()) {
DIEEntry *Entry = ModuleCU->getDIEEntry(GTy.getNode());
assert (Entry && "Missing global type!");
ModuleCU->addGlobalType(GTy.getName(), Entry->getEntry());
}
void DwarfDebug::constructSubprogramDIE(MDNode *N) {
Bill Wendling
committed
// Check for pre-existence.
if (ModuleCU->getDIE(N))
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
ModuleCU->insertDIE(N, SubprogramDie);
if (SP.getContext().getNode() == SP.getCompileUnit().getNode())
if (TopLevelDIEs.insert(SubprogramDie))
TopLevelDIEsVector.push_back(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) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Devang Patel
committed
if (!MAI->doesSupportDebugInformation())
return;
// Create all the compile unit DIEs.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I)
constructCompileUnit(*I);
if (CompileUnits.empty()) {
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
// If main compile unit for this module is not seen than randomly
// select first compile unit.
E = DbgFinder.global_variable_end(); I != E; ++I) {
DIGlobalVariable GV(*I);
if (GV.getContext().getNode() != GV.getCompileUnit().getNode())
ScopedGVs.push_back(*I);
else
constructGlobalVariableDIE(*I);
}
// Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
constructSubprogramDIE(*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());
emitInitial();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
/// endModule - Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
Devang Patel
committed
if (!ModuleCU)
if (TimePassesIsEnabled)
DebugTimer->startTimer();
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
DIE *ISP = *AI;
addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
// Insert top level DIEs.
for (SmallVector<DIE *, 4>::iterator TI = TopLevelDIEsVector.begin(),
TE = TopLevelDIEsVector.end(); TI != TE; ++TI)
ModuleCU->getCUDie()->addChild(*TI);
Devang Patel
committed
for (DenseMap<DIE *, WeakVH>::iterator CI = ContainingTypeMap.begin(),
CE = ContainingTypeMap.end(); CI != CE; ++CI) {
DIE *SPDie = CI->first;
MDNode *N = dyn_cast_or_null<MDNode>(CI->second);
if (!N) continue;
DIE *NDie = ModuleCU->getDIE(N);
if (!NDie) continue;
addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
addDIEEntry(NDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
}
// 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.
computeSizeAndOffsets();
// 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 pubtypes section.
emitDebugPubTypes();
// 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();
emitDebugInlineInfo();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var,
unsigned FrameIdx,
DILocation &ScopeLoc) {
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var.getNode());
if (AbsDbgVariable)
return AbsDbgVariable;
DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope().getNode());
if (!Scope)
return NULL;
AbsDbgVariable = new DbgVariable(Var, FrameIdx);
Scope->addVariable(AbsDbgVariable);
AbstractVariables[Var.getNode()] = AbsDbgVariable;
return AbsDbgVariable;
}
/// collectVariableInfo - Populate DbgScope entries with variables' info.
void DwarfDebug::collectVariableInfo() {
if (!MMI) return;
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
VE = VMap.end(); VI != VE; ++VI) {
MetadataBase *MB = VI->first;
MDNode *Var = dyn_cast_or_null<MDNode>(MB);
Devang Patel
committed
DIVariable DV (Var);
std::pair< unsigned, MDNode *> VP = VI->second;
DILocation ScopeLoc(VP.second);
DbgScope *Scope =
ConcreteScopes.lookup(ScopeLoc.getOrigLocation().getNode());
if (!Scope)
Scope = DbgScopeMap.lookup(ScopeLoc.getScope().getNode());
// If variable scope is not found then skip this variable.
if (!Scope)
continue;
DbgVariable *RegVar = new DbgVariable(DV, VP.first);
Scope->addVariable(RegVar);
if (DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.first,
ScopeLoc))
RegVar->setAbstractVariable(AbsDbgVariable);
}
}
/// beginScope - Process beginning of a scope starting at Label.
void DwarfDebug::beginScope(const MachineInstr *MI, unsigned Label) {
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
if (I == DbgScopeBeginMap.end())
return;
for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
(*SDI)->setStartLabelID(Label);
}
/// endScope - Process end of a scope.
void DwarfDebug::endScope(const MachineInstr *MI) {
InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
unsigned Label = MMI->NextLabelID();
Asm->printLabel(Label);
O << '\n';
SmallVector<DbgScope *, 2> &SD = I->second;
for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
(*SDI)->setEndLabelID(Label);
return;
}
/// createDbgScope - Create DbgScope for the scope.
void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {
if (!InlinedAt) {
DbgScope *WScope = DbgScopeMap.lookup(Scope);
if (WScope)
return;
WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);