diff options
author | Jim Laskey <jlaskey@mac.com> | 2006-11-02 20:12:39 +0000 |
---|---|---|
committer | Jim Laskey <jlaskey@mac.com> | 2006-11-02 20:12:39 +0000 |
commit | ef42a01113a1ee8ef0f2c803ec05a5f20eca2854 (patch) | |
tree | 3870dcb9bf0720b3b9dd3706ffc2843a05b30425 | |
parent | e931a37a4eb3e46d73ab0379dd84173dca1214f2 (diff) |
General clean up of teh dwarf writer.
1. Most significant is the folding of debug information entries. This
reduced self hosted -g SelectionDAGISel.s from 120M to 13M and pretty
close to matching .o file sizes with gcc.
2. Debug information entry printing for debugging the dwarf code.
3. Bring all the code closer to llvm standards.
4. Misc. fixes and doc clean ups.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31379 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/DwarfWriter.cpp | 4567 |
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); |