diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2008-08-17 13:53:04 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2008-08-17 13:53:04 +0000 |
commit | abb247fc036d55d06b06853cae66ab055269d605 (patch) | |
tree | 28dea7527803dc00201a17e5beee6bae7031aea3 /lib/CodeGen/AsmPrinter/DwarfWriter.cpp | |
parent | 9e422dd4f630fe4d253143371488e25bfe5b0a79 (diff) |
Move all assembler printing related stuff into new libAsmPrinter
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54885 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfWriter.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfWriter.cpp | 3930 |
1 files changed, 3930 insertions, 0 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp new file mode 100644 index 0000000000..5d6acc30ba --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -0,0 +1,3930 @@ +//===-- llvm/CodeGen/DwarfWriter.cpp - Dwarf Framework ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/DwarfWriter.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/UniqueVector.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Mangler.h" +#include "llvm/System/Path.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include <ostream> +#include <string> +using namespace llvm; +using namespace llvm::dwarf; + +namespace llvm { + +//===----------------------------------------------------------------------===// + +/// 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; + +//===----------------------------------------------------------------------===// +/// DWLabel - Labels are used to track locations in the assembler file. +/// Labels appear in the form @verbatim <prefix><Tag><Number> @endverbatim, +/// 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. + /// + const char *Tag; + + /// Number - Value to make label unique. + /// + unsigned Number; + + DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {} + + void Profile(FoldingSetNodeID &ID) const { + ID.AddString(std::string(Tag)); + ID.AddInteger(Number); + } + +#ifndef NDEBUG + void print(std::ostream *O) const { + if (O) print(*O); + } + void print(std::ostream &O) const { + O << "." << Tag; + if (Number) O << Number; + } +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { +private: + /// Attribute - Dwarf attribute code. + /// + unsigned Attribute; + + /// Form - Dwarf form code. + /// + unsigned Form; + +public: + DIEAbbrevData(unsigned A, unsigned F) + : Attribute(A) + , Form(F) + {} + + // Accessors. + unsigned getAttribute() const { return Attribute; } + unsigned getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID)const { + ID.AddInteger(Attribute); + ID.AddInteger(Form); + } +}; + +//===----------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { +private: + /// Tag - Dwarf tag code. + /// + unsigned Tag; + + /// Unique number for node. + /// + unsigned Number; + + /// ChildrenFlag - Dwarf children flag. + /// + unsigned ChildrenFlag; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector<DIEAbbrevData, 8> Data; + +public: + + DIEAbbrev(unsigned T, unsigned C) + : Tag(T) + , ChildrenFlag(C) + , Data() + {} + ~DIEAbbrev() {} + + // Accessors. + unsigned getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + unsigned getChildrenFlag() const { return ChildrenFlag; } + const SmallVector<DIEAbbrevData, 8> &getData() const { return Data; } + 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) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// AddFirstAttribute - Adds a set of attribute information to the front + /// of the abbreviation. + void AddFirstAttribute(unsigned Attribute, unsigned Form) { + Data.insert(Data.begin(), DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) { + ID.AddInteger(Tag); + ID.AddInteger(ChildrenFlag); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) + Data[i].Profile(ID); + } + + /// Emit - Print the abbreviation using the specified Dwarf writer. + /// + void Emit(const DwarfDebug &DD) const; + +#ifndef NDEBUG + void print(std::ostream *O) { + if (O) print(*O); + } + void print(std::ostream &O); + void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// 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. + /// + SmallVector<DIEValue*, 32> Values; + +public: + explicit 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 getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector<DIE *> &getChildren() const { return Children; } + SmallVector<DIEValue*, 32> &getValues() { 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) { + if (O) print(*O, IncIndent); + } + void print(std::ostream &O, unsigned IncIndent = 0); + void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. +/// +class DIEValue : public FoldingSetNode { +public: + enum { + isInteger, + isString, + isLabel, + isAsIsLabel, + isSectionOffset, + isDelta, + isEntry, + isBlock + }; + + /// Type - Type of data stored in the value. + /// + unsigned Type; + + explicit DIEValue(unsigned T) + : Type(T) + {} + virtual ~DIEValue() {} + + // Accessors + unsigned getType() const { return Type; } + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *) { return true; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form) = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const = 0; + + /// Profile - Used to gather unique data for the value folding set. + /// + virtual void Profile(FoldingSetNodeID &ID) = 0; + +#ifndef NDEBUG + void print(std::ostream *O) { + if (O) print(*O); + } + virtual void print(std::ostream &O) = 0; + void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// DWInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { +private: + uint64_t Integer; + +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIEInteger *) { return true; } + static bool classof(const DIEValue *I) { return I->Type == isInteger; } + + /// BestForm - Choose the best form for integer. + /// + 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(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of integer value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, unsigned Integer) { + ID.AddInteger(isInteger); + ID.AddInteger(Integer); + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, 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. +/// +class DIEString : public DIEValue { +public: + const std::string String; + + explicit DIEString(const std::string &S) : DIEValue(isString), String(S) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIEString *) { return true; } + static bool classof(const DIEValue *S) { return S->Type == isString; } + + /// EmitValue - Emit string value. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of string value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const { + return String.size() + sizeof(char); // sizeof('\0'); + } + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const std::string &String) { + ID.AddInteger(isString); + ID.AddString(String); + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, String); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Str: \"" << String << "\""; + } +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIEDwarfLabel - A Dwarf internal label expression DIE. +// +class DIEDwarfLabel : public DIEValue { +public: + + const DWLabel Label; + + explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIEDwarfLabel *) { return true; } + static bool classof(const DIEValue *L) { return L->Type == isLabel; } + + /// EmitValue - Emit label value. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of label value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const DWLabel &Label) { + ID.AddInteger(isLabel); + Label.Profile(ID); + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Lbl: "; + Label.print(O); + } +#endif +}; + + +//===----------------------------------------------------------------------===// +/// DIEObjectLabel - A label to an object in code or data. +// +class DIEObjectLabel : public DIEValue { +public: + const std::string Label; + + explicit DIEObjectLabel(const std::string &L) + : DIEValue(isAsIsLabel), Label(L) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIEObjectLabel *) { return true; } + static bool classof(const DIEValue *L) { return L->Type == isAsIsLabel; } + + /// EmitValue - Emit label value. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of label value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const std::string &Label) { + ID.AddInteger(isAsIsLabel); + ID.AddString(Label); + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Obj: " << Label; + } +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIESectionOffset - A section offset DIE. +// +class DIESectionOffset : public DIEValue { +public: + const DWLabel Label; + const DWLabel Section; + bool IsEH : 1; + bool UseSet : 1; + + DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec, + bool isEH = false, bool useSet = true) + : DIEValue(isSectionOffset), Label(Lab), Section(Sec), + IsEH(isEH), UseSet(useSet) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIESectionOffset *) { return true; } + static bool classof(const DIEValue *D) { return D->Type == isSectionOffset; } + + /// EmitValue - Emit section offset. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of section offset value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const DWLabel &Label, + const DWLabel &Section) { + ID.AddInteger(isSectionOffset); + Label.Profile(ID); + Section.Profile(ID); + // IsEH and UseSet are specific to the Label/Section that we will emit + // the offset for; so Label/Section are enough for uniqueness. + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label, Section); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Off: "; + Label.print(O); + O << "-"; + Section.print(O); + O << "-" << IsEH << "-" << UseSet; + } +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { +public: + const DWLabel LabelHi; + const DWLabel LabelLo; + + DIEDelta(const DWLabel &Hi, const DWLabel &Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIEDelta *) { return true; } + static bool classof(const DIEValue *D) { return D->Type == isDelta; } + + /// EmitValue - Emit delta value. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of delta value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const DWLabel &LabelHi, + const DWLabel &LabelLo) { + ID.AddInteger(isDelta); + LabelHi.Profile(ID); + LabelLo.Profile(ID); + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, LabelHi, LabelLo); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Del: "; + LabelHi.print(O); + O << "-"; + LabelLo.print(O); + } +#endif +}; + +//===----------------------------------------------------------------------===// +/// 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; + + explicit 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; } + + /// EmitValue - Emit debug information entry offset. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of debug information entry in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const { + return sizeof(int32_t); + } + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, DIE *Entry) { + ID.AddInteger(isEntry); + ID.AddPointer(Entry); + } + virtual void Profile(FoldingSetNodeID &ID) { + ID.AddInteger(isEntry); + + 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. +// +class DIEBlock : public DIEValue, public DIE { +public: + unsigned Size; // Size in bytes excluding size header. + + DIEBlock() + : DIEValue(isBlock) + , DIE(0) + , Size(0) + {} + ~DIEBlock() { + } + + // Implement isa/cast/dyncast. + static bool classof(const DIEBlock *) { return true; } + static bool classof(const DIEValue *E) { return E->Type == isBlock; } + + /// ComputeSize - calculate the size of the block. + /// + unsigned ComputeSize(DwarfDebug &DD); + + /// BestForm - Choose the best form for data. + /// + 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. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of block data in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + + /// Profile - Used to gather unique data for the value folding set. + /// + virtual void Profile(FoldingSetNodeID &ID) { + ID.AddInteger(isBlock); + DIE::Profile(ID); + } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Blk: "; + DIE::print(O, 5); + } +#endif +}; + +//===----------------------------------------------------------------------===// +/// CompileUnit - This dwarf writer support class manages information associate +/// with a source file. +class CompileUnit { +private: + /// Desc - Compile unit debug descriptor. + /// + CompileUnitDesc *Desc; + + /// ID - File identifier for source. + /// + unsigned ID; + + /// Die - Compile unit debug information entry. + /// + DIE *Die; + + /// DescToDieMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries. + std::map<DebugInfoDesc *, DIE *> DescToDieMap; + + /// DescToDIEntryMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries using a DIEntry proxy. + std::map<DebugInfoDesc *, DIEntry *> DescToDIEntryMap; + + /// Globals - A map of globally visible named entities for this unit. + /// + std::map<std::string, DIE *> Globals; + + /// DiesSet - Used to uniquely define dies within the compile unit. + /// + FoldingSet<DIE> DiesSet; + + /// Dies - List of all dies in the compile unit. + /// + 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; } + + /// hasContent - Return true if this compile unit has something to write out. + /// + bool hasContent() const { + return !Die->getChildren().empty(); + } + + /// AddGlobal - Add a new global entity to the compile unit. + /// + void AddGlobal(const std::string &Name, DIE *Die) { + Globals[Name] = Die; + } + + /// getDieMapSlotFor - Returns the debug information entry map slot for the + /// specified debug descriptor. + DIE *&getDieMapSlotFor(DebugInfoDesc *DID) { + return DescToDieMap[DID]; + } + + /// getDIEntrySlotFor - Returns the debug information entry proxy slot for the + /// specified debug descriptor. + DIEntry *&getDIEntrySlotFor(DebugInfoDesc *DID) { + return DescToDIEntryMap[DID]; + } + + /// 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 general Dwarf directives. +/// +class Dwarf { + +protected: + + //===--------------------------------------------------------------------===// + // Core attributes used by the Dwarf writer. + // + + // + /// O - Stream to .s file. + /// + std::ostream &O; + + /// Asm - Target of Dwarf emission. + /// + AsmPrinter *Asm; + + /// TAI - Target asm information. + const TargetAsmInfo *TAI; + + /// TD - Target data. + const TargetData *TD; + + /// RI - Register Information. + const TargetRegisterInfo *RI; + + /// M - Current module. + /// + Module *M; + + /// MF - Current machine function. + /// + MachineFunction *MF; + + /// MMI - Collected machine module information. + /// + MachineModuleInfo *MMI; + + /// SubprogramCount - The running count of functions being compiled. + /// + unsigned SubprogramCount; + + /// Flavor - A unique string indicating what dwarf producer this is, used to + /// unique labels. + const char * const Flavor; + + unsigned SetCounter; + Dwarf(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T, + const char *flavor) + : O(OS) + , Asm(A) + , TAI(T) + , TD(Asm->TM.getTargetData()) + , RI(Asm->TM.getRegisterInfo()) + , M(NULL) + , MF(NULL) + , MMI(NULL) + , SubprogramCount(0) + , Flavor(flavor) + , SetCounter(1) + { + } + +public: + + //===--------------------------------------------------------------------===// + // Accessors. + // + AsmPrinter *getAsm() const { return Asm; } + MachineModuleInfo *getMMI() const { return MMI; } + const TargetAsmInfo *getTargetAsmInfo() const { return TAI; } + const TargetData *getTargetData() const { return TD; } + + void PrintRelDirective(bool Force32Bit = false, bool isInSection = false) + const { + if (isInSection && TAI->getDwarfSectionOffsetDirective()) + O << TAI->getDwarfSectionOffsetDirective(); + else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t)) + O << TAI->getData32bitsDirective(); + else + O << TAI->getData64bitsDirective(); + } + + /// 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 { + O << TAI->getPrivateGlobalPrefix() << Tag; + if (Number) O << Number; + } + + void PrintLabelName(const char *Tag, unsigned Number, + const char *Suffix) const { + O << TAI->getPrivateGlobalPrefix() << Tag; + if (Number) O << Number; + O << Suffix; + } + + /// 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 { + PrintLabelName(Tag, Number); + O << ":\n"; + } + + /// EmitReference - Emit a reference to a label. + /// + void EmitReference(DWLabel Label, bool IsPCRelative = false, + bool Force32Bit = false) const { + EmitReference(Label.Tag, Label.Number, IsPCRelative, Force32Bit); + } + void EmitReference(const char *Tag, unsigned Number, + bool IsPCRelative = false, bool Force32Bit = false) const { + PrintRelDirective(Force32Bit); + PrintLabelName(Tag, Number); + + if (IsPCRelative) O << "-" << TAI->getPCSymbol(); + } + void EmitReference(const std::string &Name, bool IsPCRelative = false, + bool Force32Bit = false) const { + PrintRelDirective(Force32Bit); + + O << Name; + + if (IsPCRelative) O << "-" << TAI->getPCSymbol(); + } + + /// EmitDifference - Emit the difference between two labels. Some + /// assemblers do not behave with absolute expressions with data directives, + /// so there is an option (needsSet) to use an intermediary set expression. + void EmitDifference(DWLabel LabelHi, DWLabel LabelLo, + bool IsSmall = false) { + EmitDifference(LabelHi.Tag, LabelHi.Number, + LabelLo.Tag, LabelLo.Number, + IsSmall); + } + void EmitDifference(const char *TagHi, unsigned NumberHi, + const char *TagLo, unsigned NumberLo, + bool IsSmall = false) { + if (TAI->needsSet()) { + O << "\t.set\t"; + PrintLabelName("set", SetCounter, Flavor); + O << ","; + PrintLabelName(TagHi, NumberHi); + O << "-"; + PrintLabelName(TagLo, NumberLo); + O << "\n"; + + PrintRelDirective(IsSmall); + PrintLabelName("set", SetCounter, Flavor); + ++SetCounter; + } else { + PrintRelDirective(IsSmall); + + PrintLabelName(TagHi, NumberHi); + O << "-"; + PrintLabelName(TagLo, NumberLo); + } + } + + void EmitSectionOffset(const char* Label, const char* Section, + unsigned LabelNumber, unsigned SectionNumber, + bool IsSmall = false, bool isEH = false, + bool useSet = true) { + bool printAbsolute = false; + if (isEH) + printAbsolute = TAI->isAbsoluteEHSectionOffsets(); + else + printAbsolute = TAI->isAbsoluteDebugSectionOffsets(); + + if (TAI->needsSet() && useSet) { + O << "\t.set\t"; + PrintLabelName("set", SetCounter, Flavor); + O << ","; + PrintLabelName(Label, LabelNumber); + + if (!printAbsolute) { + O << "-"; + PrintLabelName(Section, SectionNumber); + } + O << "\n"; + + PrintRelDirective(IsSmall); + + PrintLabelName("set", SetCounter, Flavor); + ++SetCounter; + } else { + PrintRelDirective(IsSmall, true); + + PrintLabelName(Label, LabelNumber); + + if (!printAbsolute) { + O << "-"; + PrintLabelName(Section, SectionNumber); + } + } + } + + /// EmitFrameMoves - Emit frame instructions to describe the layout of the + /// frame. + void EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID, + const std::vector<MachineMove> &Moves, bool isEH) { + int stackGrowth = + Asm->TM.getFrameInfo()->getStackGrowthDirection() == + TargetFrameInfo::StackGrowsUp ? + TD->getPointerSize() : -TD->getPointerSize(); + bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + unsigned LabelID = Move.getLabelID(); + + if (LabelID) { + LabelID = MMI->MappedLabel(LabelID); + + // Throw out move if the label is invalid. + if (!LabelID) continue; + } + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) { + Asm->EmitInt8(DW_CFA_advance_loc4); + Asm->EOL("DW_CFA_advance_loc4"); + EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true); + Asm->EOL(); + + BaseLabelID = LabelID; + BaseLabel = "label"; + IsLocal = true; + } + + // If advancing cfa. + if (Dst.isRegister() && Dst.getRegister() == MachineLocation::VirtualFP) { + if (!Src.isRegister()) { + if (Src.getRegister() == MachineLocation::VirtualFP) { + Asm->EmitInt8(DW_CFA_def_cfa_offset); + Asm->EOL("DW_CFA_def_cfa_offset"); + } else { + Asm->EmitInt8(DW_CFA_def_cfa); + Asm->EOL("DW_CFA_def_cfa"); + Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister(), isEH)); + Asm->EOL("Register"); + } + + int Offset = -Src.getOffset(); + + Asm->EmitULEB128Bytes(Offset); + Asm->EOL("Offset"); + } else { + assert(0 && "Machine move no supported yet."); + } + } else if (Src.isRegister() && + Src.getRegister() == MachineLocation::VirtualFP) { + if (Dst.isRegister()) { + Asm->EmitInt8(DW_CFA_def_cfa_register); + Asm->EOL("DW_CFA_def_cfa_register"); + Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getRegister(), isEH)); + Asm->EOL("Register"); + } else { + assert(0 && "Machine move no supported yet."); + } + } else { + unsigned Reg = RI->getDwarfRegNum(Src.getRegister(), isEH); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + Asm->EmitInt8(DW_CFA_offset_extended_sf); + Asm->EOL("DW_CFA_offset_extended_sf"); + Asm->EmitULEB128Bytes(Reg); + Asm->EOL("Reg"); + Asm->EmitSLEB128Bytes(Offset); + Asm->EOL("Offset"); + } else if (Reg < 64) { + Asm->EmitInt8(DW_CFA_offset + Reg); + if (VerboseAsm) + Asm->EOL("DW_CFA_offset + Reg (" + utostr(Reg) + ")"); + |