diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 2613 |
1 files changed, 2613 insertions, 0 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp new file mode 100644 index 0000000000..0122d87a9f --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -0,0 +1,2613 @@ +//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfDebug.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Support/Timer.h" +#include "llvm/System/Path.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include <ostream> +using namespace llvm; + +static TimerGroup &getDwarfTimerGroup() { + static TimerGroup DwarfTimerGroup("Dwarf Debugging"); + return DwarfTimerGroup; +} + +//===----------------------------------------------------------------------===// + +/// Configuration values for initial hash set sizes (log2). +/// +static const unsigned InitDiesSetSize = 9; // log2(512) +static const unsigned InitAbbreviationsSetSize = 9; // log2(512) +static const unsigned InitValuesSetSize = 9; // log2(512) + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// CompileUnit - This dwarf writer support class manages information associate +/// with a source file. +class VISIBILITY_HIDDEN CompileUnit { + /// ID - File identifier for source. + /// + unsigned ID; + + /// Die - Compile unit debug information entry. + /// + DIE *Die; + + /// GVToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + std::map<GlobalVariable *, DIE *> GVToDieMap; + + /// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries using a DIEEntry proxy. + std::map<GlobalVariable *, DIEEntry *> GVToDIEEntryMap; + + /// Globals - A map of globally visible named entities for this unit. + /// + StringMap<DIE*> Globals; + + /// DiesSet - Used to uniquely define dies within the compile unit. + /// + FoldingSet<DIE> DiesSet; +public: + CompileUnit(unsigned I, DIE *D) + : ID(I), Die(D), GVToDieMap(), + GVToDIEEntryMap(), Globals(), DiesSet(InitDiesSetSize) + {} + + ~CompileUnit() { + delete Die; + } + + // Accessors. + unsigned getID() const { return ID; } + DIE* getDie() const { return Die; } + StringMap<DIE*> &getGlobals() { return Globals; } + + /// hasContent - Return true if this compile unit has something to write out. + /// + bool hasContent() const { + return !Die->getChildren().empty(); + } + + /// AddGlobal - Add a new global entity to the compile unit. + /// + void AddGlobal(const std::string &Name, DIE *Die) { + Globals[Name] = Die; + } + + /// getDieMapSlotFor - Returns the debug information entry map slot for the + /// specified debug variable. + DIE *&getDieMapSlotFor(GlobalVariable *GV) { + return GVToDieMap[GV]; + } + + /// getDIEEntrySlotFor - Returns the debug information entry proxy slot for the + /// specified debug variable. + DIEEntry *&getDIEEntrySlotFor(GlobalVariable *GV) { + return GVToDIEEntryMap[GV]; + } + + /// AddDie - Adds or interns the DIE to the compile unit. + /// + DIE *AddDie(DIE &Buffer) { + FoldingSetNodeID ID; + Buffer.Profile(ID); + void *Where; + DIE *Die = DiesSet.FindNodeOrInsertPos(ID, Where); + + if (!Die) { + Die = new DIE(Buffer); + DiesSet.InsertNode(Die, Where); + this->Die->AddChild(Die); + Buffer.Detach(); + } + + return Die; + } +}; + +//===----------------------------------------------------------------------===// +/// DbgVariable - This class is used to track local variable information. +/// +class VISIBILITY_HIDDEN DbgVariable { + DIVariable Var; // Variable Descriptor. + unsigned FrameIndex; // Variable frame index. +public: + DbgVariable(DIVariable V, unsigned I) : Var(V), FrameIndex(I) {} + + // Accessors. + DIVariable getVariable() const { return Var; } + unsigned getFrameIndex() const { return FrameIndex; } +}; + +//===----------------------------------------------------------------------===// +/// DbgScope - This class is used to track scope information. +/// +class DbgConcreteScope; +class VISIBILITY_HIDDEN DbgScope { + DbgScope *Parent; // Parent to this scope. + DIDescriptor Desc; // Debug info descriptor for scope. + // Either subprogram or block. + unsigned StartLabelID; // Label ID of the beginning of scope. + unsigned EndLabelID; // Label ID of the end of scope. + SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope. + SmallVector<DbgVariable *, 8> Variables;// Variables declared in scope. + SmallVector<DbgConcreteScope *, 8> ConcreteInsts;// Concrete insts of funcs. +public: + DbgScope(DbgScope *P, DIDescriptor D) + : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0) {} + virtual ~DbgScope(); + + // Accessors. + DbgScope *getParent() const { return Parent; } + DIDescriptor getDesc() const { return Desc; } + unsigned getStartLabelID() const { return StartLabelID; } + unsigned getEndLabelID() const { return EndLabelID; } + SmallVector<DbgScope *, 4> &getScopes() { return Scopes; } + SmallVector<DbgVariable *, 8> &getVariables() { return Variables; } + SmallVector<DbgConcreteScope*,8> &getConcreteInsts() { return ConcreteInsts; } + void setStartLabelID(unsigned S) { StartLabelID = S; } + void setEndLabelID(unsigned E) { EndLabelID = E; } + + /// AddScope - Add a scope to the scope. + /// + void AddScope(DbgScope *S) { Scopes.push_back(S); } + + /// AddVariable - Add a variable to the scope. + /// + void AddVariable(DbgVariable *V) { Variables.push_back(V); } + + /// AddConcreteInst - Add a concrete instance to the scope. + /// + void AddConcreteInst(DbgConcreteScope *C) { ConcreteInsts.push_back(C); } + +#ifndef NDEBUG + void dump() const; +#endif +}; + +#ifndef NDEBUG +void DbgScope::dump() const { + static unsigned IndentLevel = 0; + std::string Indent(IndentLevel, ' '); + + cerr << Indent; Desc.dump(); + cerr << " [" << StartLabelID << ", " << EndLabelID << "]\n"; + + IndentLevel += 2; + + for (unsigned i = 0, e = Scopes.size(); i != e; ++i) + if (Scopes[i] != this) + Scopes[i]->dump(); + + IndentLevel -= 2; +} +#endif + +//===----------------------------------------------------------------------===// +/// DbgConcreteScope - This class is used to track a scope that holds concrete +/// instance information. +/// +class VISIBILITY_HIDDEN DbgConcreteScope : public DbgScope { + CompileUnit *Unit; + DIE *Die; // Debug info for this concrete scope. +public: + DbgConcreteScope(DIDescriptor D) : DbgScope(NULL, D) {} + + // Accessors. + DIE *getDie() const { return Die; } + void setDie(DIE *D) { Die = D; } +}; + +DbgScope::~DbgScope() { + for (unsigned i = 0, N = Scopes.size(); i < N; ++i) + delete Scopes[i]; + for (unsigned j = 0, M = Variables.size(); j < M; ++j) + delete Variables[j]; + for (unsigned k = 0, O = ConcreteInsts.size(); k < O; ++k) + delete ConcreteInsts[k]; +} + +} // end llvm namespace + +DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) + : Dwarf(OS, A, T, "dbg"), MainCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), + ValuesSet(InitValuesSetSize), Values(), StringPool(), SectionMap(), + SectionSourceLines(), didInitial(false), shouldEmit(false), + FunctionDbgScope(0), DebugTimer(0) { + if (TimePassesIsEnabled) + DebugTimer = new Timer("Dwarf Debug Writer", + getDwarfTimerGroup()); +} +DwarfDebug::~DwarfDebug() { + for (unsigned j = 0, M = Values.size(); j < M; ++j) + delete Values[j]; + + for (DenseMap<const GlobalVariable *, DbgScope *>::iterator + I = AbstractInstanceRootMap.begin(), + E = AbstractInstanceRootMap.end(); I != E;++I) + delete I->second; + + delete DebugTimer; +} + +/// AssignAbbrevNumber - Define a unique number for the abbreviation. +/// +void DwarfDebug::AssignAbbrevNumber(DIEAbbrev &Abbrev) { + // Profile the node so that we can make it unique. + FoldingSetNodeID ID; + Abbrev.Profile(ID); + + // Check the set for priors. + DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); + + // If it's newly added. + if (InSet == &Abbrev) { + // Add to abbreviation list. + Abbreviations.push_back(&Abbrev); + + // Assign the vector position + 1 as its number. + Abbrev.setNumber(Abbreviations.size()); + } else { + // Assign existing abbreviation number. + Abbrev.setNumber(InSet->getNumber()); + } +} + +/// NewDIEEntry - Creates a new DIEEntry to be a proxy for a debug information +/// entry. +DIEEntry *DwarfDebug::NewDIEEntry(DIE *Entry) { + DIEEntry *Value; + + if (Entry) { + FoldingSetNodeID ID; + DIEEntry::Profile(ID, Entry); + void *Where; + Value = static_cast<DIEEntry *>(ValuesSet.FindNodeOrInsertPos(ID, Where)); + + if (Value) return Value; + + Value = new DIEEntry(Entry); + ValuesSet.InsertNode(Value, Where); + } else { + Value = new DIEEntry(Entry); + } + + Values.push_back(Value); + return Value; +} + +/// SetDIEEntry - Set a DIEEntry once the debug information entry is defined. +/// +void DwarfDebug::SetDIEEntry(DIEEntry *Value, DIE *Entry) { + Value->setEntry(Entry); + + // Add to values set if not already there. If it is, we merely have a + // duplicate in the values list (no harm.) + ValuesSet.GetOrInsertNode(Value); +} + +/// AddUInt - Add an unsigned integer attribute data and value. +/// +void DwarfDebug::AddUInt(DIE *Die, unsigned Attribute, + unsigned Form, uint64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(false, Integer); + + FoldingSetNodeID ID; + DIEInteger::Profile(ID, Integer); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIEInteger(Integer); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddSInt - Add an signed integer attribute data and value. +/// +void DwarfDebug::AddSInt(DIE *Die, unsigned Attribute, + unsigned Form, int64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(true, Integer); + + FoldingSetNodeID ID; + DIEInteger::Profile(ID, (uint64_t)Integer); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIEInteger(Integer); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddString - Add a string attribute data and value. +/// +void DwarfDebug::AddString(DIE *Die, unsigned Attribute, unsigned Form, + const std::string &String) { + FoldingSetNodeID ID; + DIEString::Profile(ID, String); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIEString(String); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddLabel - Add a Dwarf label attribute data and value. +/// +void DwarfDebug::AddLabel(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label) { + FoldingSetNodeID ID; + DIEDwarfLabel::Profile(ID, Label); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIEDwarfLabel(Label); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddObjectLabel - Add an non-Dwarf label attribute data and value. +/// +void DwarfDebug::AddObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, + const std::string &Label) { + FoldingSetNodeID ID; + DIEObjectLabel::Profile(ID, Label); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIEObjectLabel(Label); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddSectionOffset - Add a section offset label attribute data and value. +/// +void DwarfDebug::AddSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label, const DWLabel &Section, + bool isEH, bool useSet) { + FoldingSetNodeID ID; + DIESectionOffset::Profile(ID, Label, Section); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIESectionOffset(Label, Section, isEH, useSet); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddDelta - Add a label delta attribute data and value. +/// +void DwarfDebug::AddDelta(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Hi, const DWLabel &Lo) { + FoldingSetNodeID ID; + DIEDelta::Profile(ID, Hi, Lo); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = new DIEDelta(Hi, Lo); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); +} + +/// AddBlock - Add block data. +/// +void DwarfDebug::AddBlock(DIE *Die, unsigned Attribute, unsigned Form, + DIEBlock *Block) { + Block->ComputeSize(TD); + FoldingSetNodeID ID; + Block->Profile(ID); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + + if (!Value) { + Value = Block; + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } else { + // Already exists, reuse the previous one. + delete Block; + Block = cast<DIEBlock>(Value); + } + + Die->AddValue(Attribute, Block->BestForm(), Value); +} + +/// AddSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::AddSourceLine(DIE *Die, const DIVariable *V) { + // If there is no compile unit specified, don't add a line #. + if (V->getCompileUnit().isNull()) + return; + + unsigned Line = V->getLineNumber(); + unsigned FileID = FindCompileUnit(V->getCompileUnit()).getID(); + assert(FileID && "Invalid file id"); + AddUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + AddUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// AddSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::AddSourceLine(DIE *Die, const DIGlobal *G) { + // If there is no compile unit specified, don't add a line #. + if (G->getCompileUnit().isNull()) + return; + + unsigned Line = G->getLineNumber(); + unsigned FileID = FindCompileUnit(G->getCompileUnit()).getID(); + assert(FileID && "Invalid file id"); + AddUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + AddUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} +void DwarfDebug::AddSourceLine(DIE *Die, const DIType *Ty) { + // If there is no compile unit specified, don't add a line #. + DICompileUnit CU = Ty->getCompileUnit(); + if (CU.isNull()) + return; + + unsigned Line = Ty->getLineNumber(); + unsigned FileID = FindCompileUnit(CU).getID(); + assert(FileID && "Invalid file id"); + AddUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + AddUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// AddAddress - Add an address attribute to a die based on the location +/// provided. +void DwarfDebug::AddAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location) { + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + } else { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + AddUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + AddBlock(Die, Attribute, 0, Block); +} + +/// AddType - Add a new type attribute to the specified entity. +void DwarfDebug::AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { + if (Ty.isNull()) + return; + + // Check for pre-existence. + DIEEntry *&Slot = DW_Unit->getDIEEntrySlotFor(Ty.getGV()); + + // If it exists then use the existing value. + if (Slot) { + Entity->AddValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Slot); + return; + } + + // Set up proxy. + Slot = NewDIEEntry(); + + // Construct type. + DIE Buffer(dwarf::DW_TAG_base_type); + if (Ty.isBasicType(Ty.getTag())) + ConstructTypeDIE(DW_Unit, Buffer, DIBasicType(Ty.getGV())); + else if (Ty.isDerivedType(Ty.getTag())) + ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getGV())); + else { + assert(Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType"); + ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getGV())); + } + + // Add debug information entry to entity and appropriate context. + DIE *Die = NULL; + DIDescriptor Context = Ty.getContext(); + if (!Context.isNull()) + Die = DW_Unit->getDieMapSlotFor(Context.getGV()); + + if (Die) { + DIE *Child = new DIE(Buffer); + Die->AddChild(Child); + Buffer.Detach(); + SetDIEEntry(Slot, Child); + } else { + Die = DW_Unit->AddDie(Buffer); + SetDIEEntry(Slot, Die); + } + + Entity->AddValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Slot); +} + +/// ConstructTypeDIE - Construct basic type die from DIBasicType. +void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DIBasicType BTy) { + // Get core information. + std::string Name; + BTy.getName(Name); + Buffer.setTag(dwarf::DW_TAG_base_type); + AddUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + BTy.getEncoding()); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + AddString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + uint64_t Size = BTy.getSizeInBits() >> 3; + AddUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); +} + +/// ConstructTypeDIE - Construct derived type die from DIDerivedType. +void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DIDerivedType DTy) { + // Get core information. + std::string Name; + DTy.getName(Name); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); + + // FIXME - Workaround for templates. + if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; + + Buffer.setTag(Tag); + + // Map to main type, void will not have a type. + DIType FromTy = DTy.getTypeDerivedFrom(); + AddType(DW_Unit, &Buffer, FromTy); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + AddString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + AddUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + + // Add source line info if available and TyDesc is not a forward declaration. + if (!DTy.isForwardDecl()) + AddSourceLine(&Buffer, &DTy); +} + +/// ConstructTypeDIE - Construct type DIE from DICompositeType. +void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DICompositeType CTy) { + // Get core information. + std::string Name; + CTy.getName(Name); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); + + switch (Tag) { + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_array_type: + ConstructArrayTypeDIE(DW_Unit, Buffer, &CTy); + break; + case dwarf::DW_TAG_enumeration_type: { + DIArray Elements = CTy.getTypeArray(); + + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIEnumerator Enum(Elements.getElement(i).getGV()); + ElemDie = ConstructEnumTypeDIE(DW_Unit, &Enum); + Buffer.AddChild(ElemDie); + } + } + break; + case dwarf::DW_TAG_subroutine_type: { + // Add return type. + DIArray Elements = CTy.getTypeArray(); + DIDescriptor RTy = Elements.getElement(0); + AddType(DW_Unit, &Buffer, DIType(RTy.getGV())); + + // Add prototype flag. + AddUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + + // Add arguments. + for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIDescriptor Ty = Elements.getElement(i); + AddType(DW_Unit, Arg, DIType(Ty.getGV())); + Buffer.AddChild(Arg); + } + } + break; + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_class_type: { + // Add elements to structure type. + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + if (Elements.isNull()) + break; + + // Add elements to structure type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIE *ElemDie = NULL; + if (Element.getTag() == dwarf::DW_TAG_subprogram) + ElemDie = CreateSubprogramDIE(DW_Unit, + DISubprogram(Element.getGV())); + else if (Element.getTag() == dwarf::DW_TAG_variable) // ?? + ElemDie = CreateGlobalVariableDIE(DW_Unit, + DIGlobalVariable(Element.getGV())); + else + ElemDie = CreateMemberDIE(DW_Unit, + DIDerivedType(Element.getGV())); + Buffer.AddChild(ElemDie); + } + + // FIXME: We'd like an API to register additional attributes for the + // frontend to use while synthesizing, and then we'd use that api in clang + // instead of this. + if (Name == "__block_literal_generic") + 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. + if (!Name.empty()) + 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); + + if (L != H) { + AddDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); + if (L) + AddSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + AddSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); + } + + 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.getGV()), IndexTy); + } +} + +/// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator. +DIE *DwarfDebug::ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { + DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); + std::string Name; + ETy->getName(Name); + 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); + std::string Name; + GV.getDisplayName(Name); + AddString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + std::string LinkageName; + GV.getLinkageName(LinkageName); + if (!LinkageName.empty()) + AddString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + LinkageName); + AddType(DW_Unit, GVDie, GV.getType()); + 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()); + std::string Name; + DT.getName(Name); + if (!Name.empty()) + 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, + bool IsConstructor) { + DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram); + + std::string Name; + SP.getName(Name); + AddString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + std::string LinkageName; + SP.getLinkageName(LinkageName); + + if (!LinkageName.empty()) + AddString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + LinkageName); + + 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).getGV())); + } + + 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).getGV())); + AddUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + SPDie->AddChild(Arg); + } + } + + if (!SP.isLocalToUnit()) + AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + + // DW_TAG_inlined_subroutine may refer to this DIE. + DIE *&Slot = DW_Unit->getDieMapSlotFor(SP.getGV()); + 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 = + CompileUnitMap.find(Unit.getGV()); + assert(I != CompileUnitMap.end() && "Missing compile unit."); + return *I->second; +} + +/// NewDbgScopeVariable - Create a new scope variable. +/// +DIE *DwarfDebug::NewDbgScopeVariable(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); + std::string Name; + VD.getName(Name); + AddString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add source line info if available. + AddSourceLine(VariableDie, &VD); + + // Add variable type. + AddType(Unit, VariableDie, VD.getType()); + + // Add variable address. + MachineLocation Location; + Location.set(RI->getFrameRegister(*MF), + RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); + AddAddress(VariableDie, dwarf::DW_AT_location, Location); + + return VariableDie; +} + +/// getOrCreateScope - Returns the scope associated with the given descriptor. +/// +DbgScope *DwarfDebug::getOrCreateScope(GlobalVariable *V) { + DbgScope *&Slot = DbgScopeMap[V]; + if (Slot) return Slot; + + DbgScope *Parent = NULL; + DIBlock Block(V); + + // Don't create a new scope if we already created one for an inlined function. + DenseMap<const GlobalVariable *, DbgScope *>::iterator + II = AbstractInstanceRootMap.find(V); + if (II != AbstractInstanceRootMap.end()) + return LexicalScopeStack.back(); + + if (!Block.isNull()) { + DIDescriptor ParentDesc = Block.getContext(); + Parent = + ParentDesc.isNull() ? NULL : getOrCreateScope(ParentDesc.getGV()); + } + + Slot = new DbgScope(Parent, DIDescriptor(V)); + + 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) { + DIE *VariableDie = NewDbgScopeVariable(Variables[i], Unit); + 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, d |