aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/DwarfWriter.cpp4567
1 files changed, 2307 insertions, 2260 deletions
diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp
index 7bec4d3cc4..43ea483a36 100644
--- a/lib/CodeGen/DwarfWriter.cpp
+++ b/lib/CodeGen/DwarfWriter.cpp
@@ -45,69 +45,105 @@ DwarfVerbose("dwarf-verbose", cl::Hidden,
namespace llvm {
//===----------------------------------------------------------------------===//
-/// DWLabel - Labels are used to track locations in the assembler file.
-/// Labels appear in the form <prefix>debug_<Tag><Number>, where the tag is a
-/// category of label (Ex. location) and number is a value unique in that
-/// category.
-class DWLabel {
-public:
- const char *Tag; // Label category tag. Should always be
- // a staticly declared C string.
- unsigned Number; // Unique number.
- DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
-};
+/// Configuration values for initial hash set sizes (log2).
+///
+static const unsigned InitDiesSetSize = 9; // 512
+static const unsigned InitAbbreviationsSetSize = 9; // 512
+static const unsigned InitValuesSetSize = 9; // 512
//===----------------------------------------------------------------------===//
/// Forward declarations.
-//
+///
class DIE;
+class DIEValue;
//===----------------------------------------------------------------------===//
-/// CompileUnit - This dwarf writer support class manages information associate
-/// with a source file.
-class CompileUnit {
-private:
- CompileUnitDesc *Desc; // Compile unit debug descriptor.
- unsigned ID; // File ID for source.
- DIE *Die; // Compile unit debug information entry.
- std::map<std::string, DIE *> Globals; // A map of globally visible named
- // entities for this unit.
- std::map<DebugInfoDesc *, DIE *> DescToDieMap;
- // Tracks the mapping of unit level
- // debug informaton descriptors to debug
- // information entries.
+/// LEB 128 number encoding.
-public:
- CompileUnit(CompileUnitDesc *CUD, unsigned I, DIE *D)
- : Desc(CUD)
- , ID(I)
- , Die(D)
- , Globals()
- , DescToDieMap()
- {}
-
- ~CompileUnit();
+/// PrintULEB128 - Print a series of hexidecimal values (separated by commas)
+/// representing an unsigned leb128 value.
+static void PrintULEB128(std::ostream &O, unsigned Value) {
+ do {
+ unsigned Byte = Value & 0x7f;
+ Value >>= 7;
+ if (Value) Byte |= 0x80;
+ O << "0x" << std::hex << Byte << std::dec;
+ if (Value) O << ", ";
+ } while (Value);
+}
+
+/// SizeULEB128 - Compute the number of bytes required for an unsigned leb128
+/// value.
+static unsigned SizeULEB128(unsigned Value) {
+ unsigned Size = 0;
+ do {
+ Value >>= 7;
+ Size += sizeof(int8_t);
+ } while (Value);
+ return Size;
+}
+
+/// PrintSLEB128 - Print a series of hexidecimal values (separated by commas)
+/// representing a signed leb128 value.
+static void PrintSLEB128(std::ostream &O, int Value) {
+ int Sign = Value >> (8 * sizeof(Value) - 1);
+ bool IsMore;
- // Accessors.
- CompileUnitDesc *getDesc() const { return Desc; }
- unsigned getID() const { return ID; }
- DIE* getDie() const { return Die; }
- std::map<std::string, DIE *> &getGlobals() { return Globals; }
+ do {
+ unsigned Byte = Value & 0x7f;
+ Value >>= 7;
+ IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
+ if (IsMore) Byte |= 0x80;
+ O << "0x" << std::hex << Byte << std::dec;
+ if (IsMore) O << ", ";
+ } while (IsMore);
+}
+
+/// SizeSLEB128 - Compute the number of bytes required for a signed leb128
+/// value.
+static unsigned SizeSLEB128(int Value) {
+ unsigned Size = 0;
+ int Sign = Value >> (8 * sizeof(Value) - 1);
+ bool IsMore;
- /// hasContent - Return true if this compile unit has something to write out.
+ do {
+ unsigned Byte = Value & 0x7f;
+ Value >>= 7;
+ IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
+ Size += sizeof(int8_t);
+ } while (IsMore);
+ return Size;
+}
+
+//===----------------------------------------------------------------------===//
+/// DWLabel - Labels are used to track locations in the assembler file.
+/// Labels appear in the form <prefix>debug_<Tag><Number>, where the tag is a
+/// category of label (Ex. location) and number is a value unique in that
+/// category.
+class DWLabel {
+public:
+ /// Tag - Label category tag. Should always be a staticly declared C string.
///
- bool hasContent() const;
+ const char *Tag;
- /// AddGlobal - Add a new global entity to the compile unit.
+ /// Number - Value to make label unique.
///
- void AddGlobal(const std::string &Name, DIE *Die);
+ unsigned Number;
+
+ DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {}
- /// getDieMapSlotFor - Returns the debug information entry map slot for the
- /// specified debug descriptor.
- DIE *&getDieMapSlotFor(DebugInfoDesc *DD) {
- return DescToDieMap[DD];
+ void Profile(FoldingSetNodeID &ID) const {
+ ID.AddString(std::string(Tag));
+ ID.AddInteger(Number);
+ }
+
+#ifndef NDEBUG
+ void print(std::ostream &O) const {
+ O << ".debug_" << Tag;
+ if (Number) O << Number;
}
+#endif
};
//===----------------------------------------------------------------------===//
@@ -115,8 +151,13 @@ public:
/// Dwarf abbreviation.
class DIEAbbrevData {
private:
- unsigned Attribute; // Dwarf attribute code.
- unsigned Form; // Dwarf form code.
+ /// Attribute - Dwarf attribute code.
+ ///
+ unsigned Attribute;
+
+ /// Form - Dwarf form code.
+ ///
+ unsigned Form;
public:
DIEAbbrevData(unsigned A, unsigned F)
@@ -130,7 +171,7 @@ public:
/// Profile - Used to gather unique data for the abbreviation folding set.
///
- void Profile(FoldingSetNodeID &ID) {
+ void Profile(FoldingSetNodeID &ID)const {
ID.AddInteger(Attribute);
ID.AddInteger(Form);
}
@@ -141,29 +182,40 @@ public:
/// information object.
class DIEAbbrev : public FoldingSetNode {
private:
- unsigned Number; // Unique number for abbreviation.
- unsigned Tag; // Dwarf tag code.
- unsigned ChildrenFlag; // Dwarf children flag.
- std::vector<DIEAbbrevData> Data; // Raw data bytes for abbreviation.
+ /// Tag - Dwarf tag code.
+ ///
+ unsigned Tag;
+
+ /// Unique number for node.
+ ///
+ unsigned Number;
+
+ /// ChildrenFlag - Dwarf children flag.
+ ///
+ unsigned ChildrenFlag;
+
+ /// Data - Raw data bytes for abbreviation.
+ ///
+ std::vector<DIEAbbrevData> Data;
public:
DIEAbbrev(unsigned T, unsigned C)
- : Number(0)
- , Tag(T)
+ : Tag(T)
, ChildrenFlag(C)
, Data()
{}
~DIEAbbrev() {}
// Accessors.
- unsigned getNumber() const { return Number; }
unsigned getTag() const { return Tag; }
+ unsigned getNumber() const { return Number; }
unsigned getChildrenFlag() const { return ChildrenFlag; }
const std::vector<DIEAbbrevData> &getData() const { return Data; }
- void setNumber(unsigned N) { Number = N; }
+ void setTag(unsigned T) { Tag = T; }
void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; }
-
+ void setNumber(unsigned N) { Number = N; }
+
/// AddAttribute - Adds another set of attribute information to the
/// abbreviation.
void AddAttribute(unsigned Attribute, unsigned Form) {
@@ -198,9 +250,95 @@ public:
};
//===----------------------------------------------------------------------===//
+/// DIE - A structured debug information entry. Has an abbreviation which
+/// describes it's organization.
+class DIE : public FoldingSetNode {
+protected:
+ /// Abbrev - Buffer for constructing abbreviation.
+ ///
+ DIEAbbrev Abbrev;
+
+ /// Offset - Offset in debug info section.
+ ///
+ unsigned Offset;
+
+ /// Size - Size of instance + children.
+ ///
+ unsigned Size;
+
+ /// Children DIEs.
+ ///
+ std::vector<DIE *> Children;
+
+ /// Attributes values.
+ ///
+ std::vector<DIEValue *> Values;
+
+public:
+ DIE(unsigned Tag)
+ : Abbrev(Tag, DW_CHILDREN_no)
+ , Offset(0)
+ , Size(0)
+ , Children()
+ , Values()
+ {}
+ virtual ~DIE();
+
+ // Accessors.
+ DIEAbbrev &getAbbrev() { return Abbrev; }
+ unsigned getAbbrevNumber() const {
+ return Abbrev.getNumber();
+ }
+ unsigned getOffset() const { return Offset; }
+ unsigned getSize() const { return Size; }
+ const std::vector<DIE *> &getChildren() const { return Children; }
+ const std::vector<DIEValue *> &getValues() const { return Values; }
+ void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
+ void setOffset(unsigned O) { Offset = O; }
+ void setSize(unsigned S) { Size = S; }
+
+ /// AddValue - Add a value and attributes to a DIE.
+ ///
+ void AddValue(unsigned Attribute, unsigned Form, DIEValue *Value) {
+ Abbrev.AddAttribute(Attribute, Form);
+ Values.push_back(Value);
+ }
+
+ /// SiblingOffset - Return the offset of the debug information entry's
+ /// sibling.
+ unsigned SiblingOffset() const { return Offset + Size; }
+
+ /// AddSiblingOffset - Add a sibling offset field to the front of the DIE.
+ ///
+ void AddSiblingOffset();
+
+ /// AddChild - Add a child to the DIE.
+ ///
+ void AddChild(DIE *Child) {
+ Abbrev.setChildrenFlag(DW_CHILDREN_yes);
+ Children.push_back(Child);
+ }
+
+ /// Detach - Detaches objects connected to it after copying.
+ ///
+ void Detach() {
+ Children.clear();
+ }
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ void Profile(FoldingSetNodeID &ID) ;
+
+#ifndef NDEBUG
+ void print(std::ostream &O, unsigned IncIndent = 0);
+ void dump();
+#endif
+};
+
+//===----------------------------------------------------------------------===//
/// DIEValue - A debug information entry value.
-//
-class DIEValue {
+///
+class DIEValue : public FoldingSetNode {
public:
enum {
isInteger,
@@ -212,11 +350,24 @@ public:
isBlock
};
- unsigned Type; // Type of the value
+ /// Type - Type of data stored in the value.
+ ///
+ unsigned Type;
+
+ /// Usage - Number of uses of this value.
+ ///
+ unsigned Usage;
- DIEValue(unsigned T) : Type(T) {}
+ DIEValue(unsigned T)
+ : Type(T)
+ , Usage(1)
+ {}
virtual ~DIEValue() {}
+ unsigned getType() const { return Type; }
+ unsigned getUsage() const { return Usage; }
+ void IncUsage() { ++Usage; }
+
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *) { return true; }
@@ -227,6 +378,15 @@ public:
/// SizeOf - Return the size of a value in bytes.
///
virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const = 0;
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID) = 0;
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) = 0;
+ void dump();
+#endif
};
//===----------------------------------------------------------------------===//
@@ -245,21 +405,62 @@ public:
/// BestForm - Choose the best form for integer.
///
- unsigned BestForm(bool IsSigned);
-
+ static unsigned BestForm(bool IsSigned, uint64_t Integer) {
+ if (IsSigned) {
+ if ((char)Integer == (signed)Integer) return DW_FORM_data1;
+ if ((short)Integer == (signed)Integer) return DW_FORM_data2;
+ if ((int)Integer == (signed)Integer) return DW_FORM_data4;
+ } else {
+ if ((unsigned char)Integer == Integer) return DW_FORM_data1;
+ if ((unsigned short)Integer == Integer) return DW_FORM_data2;
+ if ((unsigned int)Integer == Integer) return DW_FORM_data4;
+ }
+ return DW_FORM_data8;
+ }
+
/// EmitValue - Emit integer of appropriate size.
///
virtual void EmitValue(const Dwarf &DW, unsigned Form) const;
/// SizeOf - Determine size of integer value in bytes.
///
- virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+ virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const {
+ switch (Form) {
+ case DW_FORM_flag: // Fall thru
+ case DW_FORM_ref1: // Fall thru
+ case DW_FORM_data1: return sizeof(int8_t);
+ case DW_FORM_ref2: // Fall thru
+ case DW_FORM_data2: return sizeof(int16_t);
+ case DW_FORM_ref4: // Fall thru
+ case DW_FORM_data4: return sizeof(int32_t);
+ case DW_FORM_ref8: // Fall thru
+ case DW_FORM_data8: return sizeof(int64_t);
+ case DW_FORM_udata: return SizeULEB128(Integer);
+ case DW_FORM_sdata: return SizeSLEB128(Integer);
+ default: assert(0 && "DIE Value form not supported yet"); break;
+ }
+ return 0;
+ }
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID) {
+ ID.AddInteger(Integer);
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Int: " << (int64_t)Integer
+ << " 0x" << std::hex << Integer << std::dec;
+ }
+#endif
};
//===----------------------------------------------------------------------===//
/// DIEString - A string value DIE.
///
-struct DIEString : public DIEValue {
+class DIEString : public DIEValue {
+public:
const std::string String;
DIEString(const std::string &S) : DIEValue(isString), String(S) {}
@@ -274,13 +475,29 @@ struct DIEString : public DIEValue {
/// SizeOf - Determine size of string value in bytes.
///
- virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+ virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const {
+ return String.size() + sizeof(char); // sizeof('\0');
+ }
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID) {
+ ID.AddString(String);
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Str: \"" << String << "\"";
+ }
+#endif
};
//===----------------------------------------------------------------------===//
/// DIEDwarfLabel - A Dwarf internal label expression DIE.
//
-struct DIEDwarfLabel : public DIEValue {
+class DIEDwarfLabel : public DIEValue {
+public:
+
const DWLabel Label;
DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
@@ -296,13 +513,27 @@ struct DIEDwarfLabel : public DIEValue {
/// SizeOf - Determine size of label value in bytes.
///
virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID) {
+ Label.Profile(ID);
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Lbl: ";
+ Label.print(O);
+ }
+#endif
};
//===----------------------------------------------------------------------===//
/// DIEObjectLabel - A label to an object in code or data.
//
-struct DIEObjectLabel : public DIEValue {
+class DIEObjectLabel : public DIEValue {
+public:
const std::string Label;
DIEObjectLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {}
@@ -318,12 +549,25 @@ struct DIEObjectLabel : public DIEValue {
/// SizeOf - Determine size of label value in bytes.
///
virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID) {
+ ID.AddString(Label);
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Obj: " << Label;
+ }
+#endif
};
//===----------------------------------------------------------------------===//
/// DIEDelta - A simple label difference DIE.
///
-struct DIEDelta : public DIEValue {
+class DIEDelta : public DIEValue {
+public:
const DWLabel LabelHi;
const DWLabel LabelLo;
@@ -341,16 +585,34 @@ struct DIEDelta : public DIEValue {
/// SizeOf - Determine size of delta value in bytes.
///
virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID){
+ LabelHi.Profile(ID);
+ LabelLo.Profile(ID);
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Del: ";
+ LabelHi.print(O);
+ O << "-";
+ LabelLo.print(O);
+ }
+#endif
};
//===----------------------------------------------------------------------===//
-/// DIEntry - A pointer to a debug information entry.
-///
-struct DIEntry : public DIEValue {
+/// DIEntry - A pointer to another debug information entry. An instance of this
+/// class can also be used as a proxy for a debug information entry not yet
+/// defined (ie. types.)
+class DIEntry : public DIEValue {
+public:
DIE *Entry;
DIEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
-
+
// Implement isa/cast/dyncast.
static bool classof(const DIEntry *) { return true; }
static bool classof(const DIEValue *E) { return E->Type == isEntry; }
@@ -361,25 +623,42 @@ struct DIEntry : public DIEValue {
/// SizeOf - Determine size of debug information entry in bytes.
///
- virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+ virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const {
+ return sizeof(int32_t);
+ }
+
+ /// Profile - Used to gather unique data for the value folding set.
+ ///
+ virtual void Profile(FoldingSetNodeID &ID) {
+ if (Entry) {
+ ID.AddPointer(Entry);
+ } else {
+ ID.AddPointer(this);
+ }
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Die: 0x" << std::hex << (intptr_t)Entry << std::dec;
+ }
+#endif
};
//===----------------------------------------------------------------------===//
/// DIEBlock - A block of values. Primarily used for location expressions.
//
-struct DIEBlock : public DIEValue {
+class DIEBlock : public DIEValue, public DIE {
+public:
unsigned Size; // Size in bytes excluding size header.
- std::vector<unsigned> Forms; // Data forms.
- std::vector<DIEValue *> Values; // Block values.
DIEBlock()
: DIEValue(isBlock)
+ , DIE(0)
, Size(0)
- , Forms()
- , Values()
{}
- ~DIEBlock();
-
+ ~DIEBlock() {
+ }
+
// Implement isa/cast/dyncast.
static bool classof(const DIEBlock *) { return true; }
static bool classof(const DIEValue *E) { return E->Type == isBlock; }
@@ -390,7 +669,12 @@ struct DIEBlock : public DIEValue {
/// BestForm - Choose the best form for data.
///
- unsigned BestForm();
+ unsigned BestForm() const {
+ if ((unsigned char)Size == Size) return DW_FORM_block1;
+ if ((unsigned short)Size == Size) return DW_FORM_block2;
+ if ((unsigned int)Size == Size) return DW_FORM_block4;
+ return DW_FORM_block;
+ }
/// EmitValue - Emit block data.
///
@@ -399,118 +683,130 @@ struct DIEBlock : public DIEValue {
/// SizeOf - Determine size of block data in bytes.
///
virtual unsigned SizeOf(const Dwarf &DW, unsigned Form) const;
+
- /// AddUInt - Add an unsigned integer value.
- ///
- void AddUInt(unsigned Form, uint64_t Integer);
-
- /// AddSInt - Add an signed integer value.
- ///
- void AddSInt(unsigned Form, int64_t Integer);
-
- /// AddString - Add a std::string value.
+ /// Profile - Used to gather unique data for the value folding set.
///
- void AddString(unsigned Form, const std::string &String);
-
- /// AddLabel - Add a Dwarf label value.
- ///
- void AddLabel(unsigned Form, const DWLabel &Label);
-
- /// AddObjectLabel - Add a non-Dwarf label value.
- ///
- void AddObjectLabel(unsigned Form, const std::string &Label);
-
- /// AddDelta - Add a label delta value.
- ///
- void AddDelta(unsigned Form, const DWLabel &Hi, const DWLabel &Lo);
-
- /// AddDIEntry - Add a DIE value.
- ///
- void AddDIEntry(unsigned Form, DIE *Entry);
-
+ virtual void DIEBlock::Profile(FoldingSetNodeID &ID) {
+ DIE::Profile(ID);
+ }
+
+#ifndef NDEBUG
+ virtual void print(std::ostream &O) {
+ O << "Blk: ";
+ DIE::print(O, 5);
+ }
+#endif
};
//===----------------------------------------------------------------------===//
-/// DIE - A structured debug information entry. Has an abbreviation which
-/// describes it's organization.
-class DIE {
+/// CompileUnit - This dwarf writer support class manages information associate
+/// with a source file.
+class CompileUnit {
private:
- DIEAbbrev Abbrev; // Buffer for constructing abbreviation.
- unsigned Offset; // Offset in debug info section.
- unsigned Size; // Size of instance + children.
- std::vector<DIE *> Children; // Children DIEs.
- std::vector<DIEValue *> Values; // Attributes values.
-
-public:
- DIE(unsigned Tag);
- ~DIE();
-
- // Accessors.
- unsigned getAbbrevNumber() const {
- return Abbrev.getNumber();
- }
- unsigned getOffset() const { return Offset; }
- unsigned getSize() const { return Size; }
- const std::vector<DIE *> &getChildren() const { return Children; }
- const std::vector<DIEValue *> &getValues() const { return Values; }
- void setOffset(unsigned O) { Offset = O; }
- void setSize(unsigned S) { Size = S; }
+ /// Desc - Compile unit debug descriptor.
+ ///
+ CompileUnitDesc *Desc;
- /// SiblingOffset - Return the offset of the debug information entry's
- /// sibling.
- unsigned SiblingOffset() const { return Offset + Size; }
+ /// ID - File identifier for source.
+ ///
+ unsigned ID;
- /// AddSiblingOffset - Add a sibling offset field to the front of the DIE.
+ /// Die - Compile unit debug information entry.
///
- void AddSiblingOffset();
+ DIE *Die;
+
+ /// DescToDieMap - Tracks the mapping of unit level debug informaton
+ /// descriptors to debug information entries.
+ std::map<DebugInfoDesc *, DIE *> DescToDieMap;
- /// AddUInt - Add an unsigned integer attribute data and value.
- ///
- void AddUInt(unsigned Attribute, unsigned Form, uint64_t Integer);
+ /// DescToDIEntryMap - Tracks the mapping of unit level debug informaton
+ /// descriptors to debug information entries using a DIEntry proxy.
+ std::map<DebugInfoDesc *, DIEntry *> DescToDIEntryMap;
- /// AddSInt - Add an signed integer attribute data and value.
- ///
- void AddSInt(unsigned Attribute, unsigned Form, int64_t Integer);
-
- /// AddString - Add a std::string attribute data and value.
- ///
- void AddString(unsigned Attribute, unsigned Form,
- const std::string &String);
-
- /// AddLabel - Add a Dwarf label attribute data and value.
- ///
- void AddLabel(unsigned Attribute, unsigned Form, const DWLabel &Label);
-
- /// AddObjectLabel - Add a non-Dwarf label attribute data and value.
+ /// Globals - A map of globally visible named entities for this unit.
///
- void AddObjectLabel(unsigned Attribute, unsigned Form,
- const std::string &Label);
-
- /// AddDelta - Add a label delta attribute data and value.
+ std::map<std::string, DIE *> Globals;
+
+ /// DiesSet - Used to uniquely define dies within the compile unit.
///
- void AddDelta(unsigned Attribute, unsigned Form,
- const DWLabel &Hi, const DWLabel &Lo);
-
- /// AddDIEntry - Add a DIE attribute data and value.
+ FoldingSet<DIE> DiesSet;
+
+ /// Dies - List of all dies in the compile unit.
///
- void AddDIEntry(unsigned Attribute, unsigned Form, DIE *Entry);
+ std::vector<DIE *> Dies;
+
+public:
+ CompileUnit(CompileUnitDesc *CUD, unsigned I, DIE *D)
+ : Desc(CUD)
+ , ID(I)
+ , Die(D)
+ , DescToDieMap()
+ , DescToDIEntryMap()
+ , Globals()
+ , DiesSet(InitDiesSetSize)
+ , Dies()
+ {}
+
+ ~CompileUnit() {
+ delete Die;
+
+ for (unsigned i = 0, N = Dies.size(); i < N; ++i)
+ delete Dies[i];
+ }
+
+ // Accessors.
+ CompileUnitDesc *getDesc() const { return Desc; }
+ unsigned getID() const { return ID; }
+ DIE* getDie() const { return Die; }
+ std::map<std::string, DIE *> &getGlobals() { return Globals; }
- /// AddBlock - Add block data.
+ /// hasContent - Return true if this compile unit has something to write out.
///
- void AddBlock(unsigned Attribute, unsigned Form, DIEBlock *Block);
+ bool hasContent() const {
+ return !Die->getChildren().empty();
+ }
- /// Complete - Indicate that all attributes have been added and
- /// ready to get an abbreviation ID.
+ /// AddGlobal - Add a new global entity to the compile unit.
///
- void Complete(Dwarf &DW);
+ void AddGlobal(const std::string &Name, DIE *Die) {
+ Globals[Name] = Die;
+ }
- /// AddChild - Add a child to the DIE.
- void AddChild(DIE *Child);
+ /// getDieMapSlotFor - Returns the debug information entry map slot for the
+ /// specified debug descriptor.
+ DIE *&getDieMapSlotFor(DebugInfoDesc *DD) {
+ return DescToDieMap[DD];
+ }
+
+ /// getDIEntrySlotFor - Returns the debug information entry proxy slot for the
+ /// specified debug descriptor.
+ DIEntry *&getDIEntrySlotFor(DebugInfoDesc *DD) {
+ return DescToDIEntryMap[DD];
+ }
+
+ /// 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;
+ }
};
//===----------------------------------------------------------------------===//
-/// Dwarf - Emits Dwarf debug and exception handling directives.
-//
+/// Dwarf - Emits Dwarf debug and exception handling directives.
+///
class Dwarf {
private:
@@ -569,7 +865,7 @@ private:
/// of each entry in this vector corresponds to the sources in DebugInfo.
std::vector<CompileUnit *> CompileUnits;
- /// AbbreviationsSet - Used to uniquely define the abbreviations.
+ /// AbbreviationsSet - Used to uniquely define abbreviations.
///
FoldingSet<DIEAbbrev> AbbreviationsSet;
@@ -577,19 +873,22 @@ private:
///
std::vector<DIEAbbrev *> Abbreviations;
+ /// ValuesSet - Used to uniquely define values.
+ ///
+ FoldingSet<DIEValue> ValuesSet;
+
+ /// Values - A list of all the unique values in use.
+ ///
+ std::vector<DIEValue *> Values;
+
/// StringPool - A UniqueVector of strings used by indirect references.
- /// UnitMap - Map debug information descriptor to compile unit.
- ///
+ ///
UniqueVector<std::string> StringPool;
/// UnitMap - Map debug information descriptor to compile unit.
///
std::map<DebugInfoDesc *, CompileUnit *> DescToUnitMap;
- /// DescToDieMap - Tracks the mapping of top level debug informaton
- /// descriptors to debug information entries.
- std::map<DebugInfoDesc *, DIE *> DescToDieMap;
-
/// SectionMap - Provides a unique id per text section.
///
UniqueVector<std::string> SectionMap;
@@ -607,82 +906,167 @@ public:
/// PrintHex - Print a value as a hexidecimal value.
///
- void PrintHex(int Value) const;
+ void PrintHex(int Value) const {
+ O << "0x" << std::hex << Value << std::dec;
+ }
/// EOL - Print a newline character to asm stream. If a comment is present
/// then it will be printed first. Comments should not contain '\n'.
- void EOL(const std::string &Comment) const;
+ void EOL(const std::string &Comment) const {
+ if (DwarfVerbose && !Comment.empty()) {
+ O << "\t"
+ << TAI->getCommentString()
+ << " "
+ << Comment;
+ }
+ O << "\n";
+ }
/// EmitAlign - Print a align directive.
///
- void EmitAlign(unsigned Alignment) const;
+ void EmitAlign(unsigned Alignment) const {
+ O << TAI->getAlignDirective() << Alignment << "\n";
+ }
/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
/// unsigned leb128 value.
- void EmitULEB128Bytes(unsigned Value) const;
+ void EmitULEB128Bytes(unsigned Value) const {
+ if (TAI->hasLEB128()) {
+ O << "\t.uleb128\t"
+ << Value;
+ } else {
+ O << TAI->getData8bitsDirective();
+ PrintULEB128(O, Value);
+ }
+ }
/// EmitSLEB128Bytes - print an assembler byte data directive to compose a
/// signed leb128 value.
- void EmitSLEB128Bytes(int Value) const;
-
- /// PrintULEB128 - Print a series of hexidecimal values (separated by
- /// commas) representing an unsigned leb128 value.
- void PrintULEB128(unsigned Value) const;
-
- /// SizeULEB128 - Compute the number of bytes required for an unsigned
- /// leb128 value.
- static unsigned SizeULEB128(unsigned Value);
-
- /// PrintSLEB128 - Print a series of hexidecimal values (separated by
- /// commas) representing a signed leb128 value.
- void PrintSLEB128(int Value) const;
-
- /// SizeSLEB128 - Compute the number of bytes required for a signed leb128
- /// value.
- static unsigned SizeSLEB128(int Value);
+ void EmitSLEB128Bytes(int Value) const {
+ if (TAI->hasLEB128()) {
+ O << "\t.sleb128\t"
+ << Value;
+ } else {
+ O << TAI->getData8bitsDirective();
+ PrintSLEB128(O, Value);
+ }
+ }
/// EmitInt8 - Emit a byte directive and value.
///
- void EmitInt8(int Value) const;
+ void EmitInt8(int Value) const {
+ O << TAI->getData8bitsDirective();
+ PrintHex(Value & 0xFF);
+ }
/// EmitInt16 - Emit a short directive and value.
///
- void EmitInt16(int Value) const;
+ void EmitInt16(int Value) const {
+ O << TAI->getData16bitsDirective();
+ PrintHex(Value & 0xFFFF);
+ }
/// EmitInt32 - Emit a long directive and value.
///
- void EmitInt32(int Value) const;
-
+ void EmitInt32(int Value) const {
+ O << TAI->getData32bitsDirective();
+ PrintHex(Value);
+ }
+
/// EmitInt64 - Emit a long long directive and value.
///
- void EmitInt64(uint64_t Value) const;
-
+ void EmitInt64(uint64_t Value) const {
+ if (TAI->getData64bitsDirective()) {
+ O << TAI->getData64bitsDirective();
+ PrintHex(Value);
+ } else {
+ if (TD->isBigEndian()) {
+ EmitInt32(unsigned(Value >> 32)); O << "\n";
+ EmitInt32(unsigned(Value));
+ } else {
+ EmitInt32(unsigned(Value)); O << "\n";
+ EmitInt32(unsigned(Value >> 32));
+ }
+ }
+ }
+
/// EmitString - Emit a string with quotes and a null terminator.
- /// Special characters are emitted properly.
+ /// Special characters are emitted properly.
/// \literal (Eg. '\t') \endliteral
- void EmitString(const std::string &String) const;
+ void EmitString(const std::string &String) const {
+ O << TAI->getAsciiDirective()
+ << "\"";
+ for (unsigned i = 0, N = String.size(); i < N; ++i) {
+ unsigned char C = String[i];
+
+ if (!isascii(C) || iscntrl(C)) {
+ switch(C) {
+ case '\b': O << "\\b"; break;
+ case '\f': O << "\\f"; break;
+ case '\n': O << "\\n"; break;
+ case '\r': O << "\\r"; break;
+ case '\t': O << "\\t"; break;
+ default:
+ O << '\\';
+ O << char('0' + ((C >> 6) & 7));
+ O << char('0' + ((C >> 3) & 7));
+ O << char('0' + ((C >> 0) & 7));
+ break;
+ }
+ } else if (C == '\"') {
+ O << "\\\"";
+ } else if (C == '\'') {
+ O << "\\\'";
+ } else {
+ O << C;
+ }
+ }
+ O << "\\0\"";
+ }
/// PrintLabelName - Print label name in form used by Dwarf writer.
///
void PrintLabelName(DWLabel Label) const {
PrintLabelName(Label.Tag, Label.Number);
}
- void PrintLabelName(const char *Tag, unsigned Number) const;
+ void PrintLabelName(const char *Tag, unsigned Number) const {
+ O << TAI->getPrivateGlobalPrefix()
+ << "debug_"
+ << Tag;
+ if (Number) O << Number;
+ }
/// EmitLabel - Emit location label for internal use by Dwarf.
///
void EmitLabel(DWLabel Label) const {
EmitLabel(Label.Tag, Label.Number);
}
- void EmitLabel(const char *Tag, unsigned Number) const;
+ void EmitLabel(const char *Tag, unsigned Number) const {
+ PrintLabelName(Tag, Number);
+ O << ":\n";
+ }
/// EmitReference - Emit a reference to a label.
///
void EmitReference(DWLabel Label) const {
EmitReference(Label.Tag, Label.Number);
}
- void EmitReference(const char *Tag, unsigned Number) const;
- void EmitReference(const std::string &Name) const;
+ void EmitReference(const char *Tag, unsigned Number) const {
+ if (TAI->getAddressSize() == 4)
+ O << TAI->getData32bitsDirective();
+ else
+ O << TAI->getData64bitsDirective();
+
+ PrintLabelName(Tag, Number);
+ }
+ void EmitReference(const std::string &Name) const {
+ if (TAI->getAddressSize() == 4)
+ O << TAI->getData32bitsDirective();
+ else
+ O << TAI->getData64bitsDirective();
+
+ O << Name;
+ }
/// EmitDifference - Emit the difference between two labels. Some
/// assemblers do not behave with absolute expressions with data directives,
@@ -691,201 +1075,1742 @@ public:
EmitDifference(LabelHi.Tag, LabelHi.Number, LabelLo.Tag, LabelLo.Number);
}
void EmitDifference(const char *TagHi, unsigned NumberHi,