Newer
Older
// Emit derived type.
addType(&Buffer, CTy->getTypeDerivedFrom());
DIArray Elements = CTy->getTypeArray();
// Get an anonymous type for index type.
DIE *IdxTy = ModuleCU->getIndexTyDie();
if (!IdxTy) {
// Construct an anonymous type for index type.
IdxTy = new DIE(dwarf::DW_TAG_base_type);
addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t));
addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
dwarf::DW_ATE_signed);
ModuleCU->addDie(IdxTy);
ModuleCU->setIndexTyDie(IdxTy);
// 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()), IdxTy);
}
}
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator *ETy) {
DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator);
StringRef 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;
}
/// getRealLinkageName - If special LLVM prefix that is used to inform the asm
/// printer to not emit usual symbol prefix before the symbol name is used then
/// return linkage name after skipping this special LLVM prefix.
static StringRef getRealLinkageName(StringRef LinkageName) {
char One = '\1';
if (LinkageName.startswith(StringRef(&One, 1)))
return LinkageName.substr(1);
return LinkageName;
}
/// createGlobalVariableDIE - Create new DIE using GV.
DIE *DwarfDebug::createGlobalVariableDIE(const DIGlobalVariable &GV) {
// If the global variable was optmized out then no need to create debug info
// entry.
if (!GV.getGlobal()) return NULL;
if (GV.getDisplayName().empty()) return NULL;
DIE *GVDie = new DIE(dwarf::DW_TAG_variable);
addString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
StringRef LinkageName = GV.getLinkageName();
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(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(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;
}
/// createSubprogramDIE - Create new DIE using SP.
DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
DIE *SPDie = ModuleCU->getDIE(SP.getNode());
if (SPDie)
return SPDie;
SPDie = new DIE(dwarf::DW_TAG_subprogram);
addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName());
StringRef LinkageName = SP.getLinkageName();
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(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())));
}
if (MakeDecl || !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(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.
ModuleCU->insertDIE(SP.getNode(), SPDie);
return SPDie;
}
/// findCompileUnit - Get the compile unit for the given descriptor.
CompileUnit *DwarfDebug::findCompileUnit(DICompileUnit Unit) {
DenseMap<Value *, CompileUnit *>::const_iterator I =
if (I == CompileUnitMap.end())
return constructCompileUnit(Unit.getNode());
return I->second;
/// 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!");
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
DISubprogram SP(SPNode);
if (SP.isDefinition() && !SP.getContext().isCompileUnit()) {
addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
// 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(Arg, DIType(Args.getElement(i).getNode()));
addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ??
SPDie->addChild(Arg);
}
DIE *SPDeclDie = SPDie;
SPDie = new DIE(dwarf::DW_TAG_subprogram);
addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
SPDeclDie);
ModuleCU->addDie(SPDie);
}
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);
return SPDie;
}
/// 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(getRealLinkageName(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) {
// Get the descriptor.
const DIVariable &VD = DV->getVariable();
StringRef Name = VD.getName();
if (Name.empty())
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
// 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(VariableDie, getBlockByrefType(VD.getType(), Name));
}
// 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);
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));
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) {
DIE *NDie = ModuleCU->getDIE(NS.getNode());
if (NDie)
return NDie;
NDie = new DIE(dwarf::DW_TAG_namespace);
ModuleCU->insertDIE(NS.getNode(), NDie);
if (!NS.getName().empty())
addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName());
addSourceLine(NDie, &NS);
addToContextOwner(NDie, NS.getContext());
return NDie;
}
CompileUnit *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(DI_GV);
Devang Patel
committed
if (!VariableDie)
return;
ModuleCU->insertDIE(N, VariableDie);
if (DI_GV.isDefinition()
&& !DI_GV.getContext().isCompileUnit()) {
// Create specification DIE.
DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
dwarf::DW_FORM_ref4, VariableDie);
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(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
ModuleCU->addDie(VariableSpecDIE);
} else {
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);
}
addToContextOwner(VariableDie, DI_GV.getContext());
// 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(SP);
Bill Wendling
committed
ModuleCU->insertDIE(N, SubprogramDie);
addToContextOwner(SubprogramDie, SP.getContext());
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.
// Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
constructSubprogramDIE(*I);
// Create DIEs for each global variable.
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
E = DbgFinder.global_variable_end(); I != E; ++I)
constructGlobalVariableDIE(*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);
DbgScopeMap.insert(std::make_pair(Scope, WScope));
createDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL);
return;
}
DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
if (WScope)
return;
WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
DILocation DL(InlinedAt);
createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
/// extractScopeInformation - Scan machine instructions in this function
Devang Patel
committed
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool DwarfDebug::extractScopeInformation(MachineFunction *MF) {
Devang Patel
committed
// 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;
DenseMap<const MachineInstr *, unsigned> MIIndexMap;
unsigned MIIndex = 0;
// Scan each instruction and create scopes. First build working set of scopes.
Devang Patel
committed
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;
MIIndexMap[MInsn] = MIIndex++;
Devang Patel
committed
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
Devang Patel
committed
DebugLocTuple DLT = MF->getDebugLocTuple(DL);