aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp2613
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