diff options
-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); } - 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, @@ -6 |