From abb247fc036d55d06b06853cae66ab055269d605 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sun, 17 Aug 2008 13:53:04 +0000 Subject: 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 --- lib/CodeGen/DwarfWriter.cpp | 3930 ------------------------------------------- 1 file changed, 3930 deletions(-) delete mode 100644 lib/CodeGen/DwarfWriter.cpp (limited to 'lib/CodeGen/DwarfWriter.cpp') diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp deleted file mode 100644 index 5d6acc30ba..0000000000 --- a/lib/CodeGen/DwarfWriter.cpp +++ /dev/null @@ -1,3930 +0,0 @@ -//===-- 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 -#include -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 @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 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 &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 Children; - - /// Attributes values. - /// - SmallVector 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 &getChildren() const { return Children; } - SmallVector &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 DescToDieMap; - - /// DescToDIEntryMap - Tracks the mapping of unit level debug informaton - /// descriptors to debug information entries using a DIEntry proxy. - std::map DescToDIEntryMap; - - /// Globals - A map of globally visible named entities for this unit. - /// - std::map Globals; - - /// DiesSet - Used to uniquely define dies within the compile unit. - /// - FoldingSet DiesSet; - - /// Dies - List of all dies in the compile unit. - /// - std::vector 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 &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 &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) + ")"); - else - Asm->EOL(); - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); - } else { - Asm->EmitInt8(DW_CFA_offset_extended); - Asm->EOL("DW_CFA_offset_extended"); - Asm->EmitULEB128Bytes(Reg); - Asm->EOL("Reg"); - Asm->EmitULEB128Bytes(Offset); - Asm->EOL("Offset"); - } - } - } - } - -}; - -//===----------------------------------------------------------------------===// -/// DwarfDebug - Emits Dwarf debug directives. -/// -class DwarfDebug : public Dwarf { - -private: - //===--------------------------------------------------------------------===// - // Attributes used to construct specific Dwarf sections. - // - - /// CompileUnits - All the compile units involved in this build. The index - /// of each entry in this vector corresponds to the sources in MMI. - std::vector CompileUnits; - - /// AbbreviationsSet - Used to uniquely define abbreviations. - /// - FoldingSet AbbreviationsSet; - - /// Abbreviations - A list of all the unique abbreviations in use. - /// - std::vector Abbreviations; - - /// ValuesSet - Used to uniquely define values. - /// - FoldingSet ValuesSet; - - /// Values - A list of all the unique values in use. - /// - std::vector Values; - - /// StringPool - A UniqueVector of strings used by indirect references. - /// - UniqueVector StringPool; - - /// UnitMap - Map debug information descriptor to compile unit. - /// - std::map DescToUnitMap; - - /// SectionMap - Provides a unique id per text section. - /// - UniqueVector SectionMap; - - /// SectionSourceLines - Tracks line numbers per text section. - /// - std::vector > SectionSourceLines; - - /// didInitial - Flag to indicate if initial emission has been done. - /// - bool didInitial; - - /// shouldEmit - Flag to indicate if debug information should be emitted. - /// - bool shouldEmit; - - struct FunctionDebugFrameInfo { - unsigned Number; - std::vector Moves; - - FunctionDebugFrameInfo(unsigned Num, const std::vector &M): - Number(Num), Moves(M) { } - }; - - std::vector DebugFrames; - -public: - - /// ShouldEmitDwarf - Returns true if Dwarf declarations should be made. - /// - bool ShouldEmitDwarf() const { return shouldEmit; } - - /// AssignAbbrevNumber - Define a unique number for the abbreviation. - /// - void AssignAbbrevNumber(DIEAbbrev &Abbrev) { - // Profile the node so that we can make it unique. - FoldingSetNodeID ID; - Abbrev.Profile(ID); - - // Check the set for priors. - DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); - - // If it's newly added. - if (InSet == &Abbrev) { - // Add to abbreviation list. - Abbreviations.push_back(&Abbrev); - // Assign the vector position + 1 as its number. - Abbrev.setNumber(Abbreviations.size()); - } else { - // Assign existing abbreviation number. - Abbrev.setNumber(InSet->getNumber()); - } - } - - /// NewString - Add a string to the constant pool and returns a label. - /// - DWLabel NewString(const std::string &String) { - unsigned StringID = StringPool.insert(String); - return DWLabel("string", StringID); - } - - /// NewDIEntry - Creates a new DIEntry to be a proxy for a debug information - /// entry. - DIEntry *NewDIEntry(DIE *Entry = NULL) { - DIEntry *Value; - - if (Entry) { - FoldingSetNodeID ID; - DIEntry::Profile(ID, Entry); - void *Where; - Value = static_cast(ValuesSet.FindNodeOrInsertPos(ID, Where)); - - if (Value) return Value; - - Value = new DIEntry(Entry); - ValuesSet.InsertNode(Value, Where); - } else { - Value = new DIEntry(Entry); - } - - Values.push_back(Value); - return Value; - } - - /// SetDIEntry - Set a DIEntry once the debug information entry is defined. - /// - void SetDIEntry(DIEntry *Value, DIE *Entry) { - Value->Entry = Entry; - // Add to values set if not already there. If it is, we merely have a - // duplicate in the values list (no harm.) - ValuesSet.GetOrInsertNode(Value); - } - - /// AddUInt - Add an unsigned integer attribute data and value. - /// - void AddUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer) { - if (!Form) Form = DIEInteger::BestForm(false, Integer); - - FoldingSetNodeID ID; - DIEInteger::Profile(ID, Integer); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIEInteger(Integer); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddSInt - Add an signed integer attribute data and value. - /// - void AddSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer) { - if (!Form) Form = DIEInteger::BestForm(true, Integer); - - FoldingSetNodeID ID; - DIEInteger::Profile(ID, (uint64_t)Integer); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIEInteger(Integer); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddString - Add a std::string attribute data and value. - /// - void AddString(DIE *Die, unsigned Attribute, unsigned Form, - const std::string &String) { - FoldingSetNodeID ID; - DIEString::Profile(ID, String); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIEString(String); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddLabel - Add a Dwarf label attribute data and value. - /// - void AddLabel(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Label) { - FoldingSetNodeID ID; - DIEDwarfLabel::Profile(ID, Label); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIEDwarfLabel(Label); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddObjectLabel - Add an non-Dwarf label attribute data and value. - /// - void AddObjectLabel(DIE *Die, unsigned Attribute, unsigned Form, - const std::string &Label) { - FoldingSetNodeID ID; - DIEObjectLabel::Profile(ID, Label); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIEObjectLabel(Label); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddSectionOffset - Add a section offset label attribute data and value. - /// - void AddSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Label, const DWLabel &Section, - bool isEH = false, bool useSet = true) { - FoldingSetNodeID ID; - DIESectionOffset::Profile(ID, Label, Section); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIESectionOffset(Label, Section, isEH, useSet); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddDelta - Add a label delta attribute data and value. - /// - void AddDelta(DIE *Die, unsigned Attribute, unsigned Form, - const DWLabel &Hi, const DWLabel &Lo) { - FoldingSetNodeID ID; - DIEDelta::Profile(ID, Hi, Lo); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = new DIEDelta(Hi, Lo); - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } - - Die->AddValue(Attribute, Form, Value); - } - - /// AddDIEntry - Add a DIE attribute data and value. - /// - void AddDIEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry) { - Die->AddValue(Attribute, Form, NewDIEntry(Entry)); - } - - /// AddBlock - Add block data. - /// - void AddBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block) { - Block->ComputeSize(*this); - FoldingSetNodeID ID; - Block->Profile(ID); - void *Where; - DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); - if (!Value) { - Value = Block; - ValuesSet.InsertNode(Value, Where); - Values.push_back(Value); - } else { - // Already exists, reuse the previous one. - delete Block; - Block = cast(Value); - } - - Die->AddValue(Attribute, Block->BestForm(), Value); - } - -private: - - /// AddSourceLine - Add location information to specified debug information - /// entry. - void AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line) { - if (File && Line) { - CompileUnit *FileUnit = FindCompileUnit(File); - unsigned FileID = FileUnit->getID(); - AddUInt(Die, DW_AT_decl_file, 0, FileID); - AddUInt(Die, DW_AT_decl_line, 0, Line); - } - } - - /// AddAddress - Add an address attribute to a die based on the location - /// provided. - void AddAddress(DIE *Die, unsigned Attribute, - const MachineLocation &Location) { - unsigned Reg = RI->getDwarfRegNum(Location.getRegister(), false); - DIEBlock *Block = new DIEBlock(); - - if (Location.isRegister()) { - if (Reg < 32) { - AddUInt(Block, 0, DW_FORM_data1, DW_OP_reg0 + Reg); - } else { - AddUInt(Block, 0, DW_FORM_data1, DW_OP_regx); - AddUInt(Block, 0, DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) { - AddUInt(Block, 0, DW_FORM_data1, DW_OP_breg0 + Reg); - } else { - AddUInt(Block, 0, DW_FORM_data1, DW_OP_bregx); - AddUInt(Block, 0, DW_FORM_udata, Reg); - } - AddUInt(Block, 0, DW_FORM_sdata, Location.getOffset()); - } - - AddBlock(Die, Attribute, 0, Block); - } - - /// AddBasicType - Add a new basic type attribute to the specified entity. - /// - void AddBasicType(DIE *Entity, CompileUnit *Unit, - const std::string &Name, - unsigned Encoding, unsigned Size) { - DIE *Die = ConstructBasicType(Unit, Name, Encoding, Size); - AddDIEntry(Entity, DW_AT_type, DW_FORM_ref4, Die); - } - - /// ConstructBasicType - Construct a new basic type. - /// - DIE *ConstructBasicType(CompileUnit *Unit, - const std::string &Name, - unsigned Encoding, unsigned Size) { - DIE Buffer(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_byte_size, 0, Size); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, Encoding); - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - return Unit->AddDie(Buffer); - } - - /// AddPointerType - Add a new pointer type attribute to the specified entity. - /// - void AddPointerType(DIE *Entity, CompileUnit *Unit, const std::string &Name) { - DIE *Die = ConstructPointerType(Unit, Name); - AddDIEntry(Entity, DW_AT_type, DW_FORM_ref4, Die); - } - - /// ConstructPointerType - Construct a new pointer type. - /// - DIE *ConstructPointerType(CompileUnit *Unit, const std::string &Name) { - DIE Buffer(DW_TAG_pointer_type); - AddUInt(&Buffer, DW_AT_byte_size, 0, TD->getPointerSize()); - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - return Unit->AddDie(Buffer); - } - - /// AddType - Add a new type attribute to the specified entity. - /// - void AddType(DIE *Entity, TypeDesc *TyDesc, CompileUnit *Unit) { - if (!TyDesc) { - AddBasicType(Entity, Unit, "", DW_ATE_signed, sizeof(int32_t)); - } else { - // Check for pre-existence. - DIEntry *&Slot = Unit->getDIEntrySlotFor(TyDesc); - - // If it exists then use the existing value. - if (Slot) { - Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); - return; - } - - if (SubprogramDesc *SubprogramTy = dyn_cast(TyDesc)) { - // FIXME - Not sure why programs and variables are coming through here. - // Short cut for handling subprogram types (not really a TyDesc.) - AddPointerType(Entity, Unit, SubprogramTy->getName()); - } else if (GlobalVariableDesc *GlobalTy = - dyn_cast(TyDesc)) { - // FIXME - Not sure why programs and variables are coming through here. - // Short cut for handling global variable types (not really a TyDesc.) - AddPointerType(Entity, Unit, GlobalTy->getName()); - } else { - // Set up proxy. - Slot = NewDIEntry(); - - // Construct type. - DIE Buffer(DW_TAG_base_type); - ConstructType(Buffer, TyDesc, Unit); - - // Add debug information entry to entity and unit. - DIE *Die = Unit->AddDie(Buffer); - SetDIEntry(Slot, Die); - Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); - } - } - } - - /// ConstructType - Adds all the required attributes to the type. - /// - void ConstructType(DIE &Buffer, TypeDesc *TyDesc, CompileUnit *Unit) { - // Get core information. - const std::string &Name = TyDesc->getName(); - uint64_t Size = TyDesc->getSize() >> 3; - - if (BasicTypeDesc *BasicTy = dyn_cast(TyDesc)) { - // Fundamental types like int, float, bool - Buffer.setTag(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BasicTy->getEncoding()); - } else if (DerivedTypeDesc *DerivedTy = dyn_cast(TyDesc)) { - // Fetch tag. - unsigned Tag = DerivedTy->getTag(); - // FIXME - Workaround for templates. - if (Tag == DW_TAG_inheritance) Tag = DW_TAG_reference_type; - // Pointers, typedefs et al. - Buffer.setTag(Tag); - // Map to main type, void will not have a type. - if (TypeDesc *FromTy = DerivedTy->getFromType()) - AddType(&Buffer, FromTy, Unit); - } else if (CompositeTypeDesc *CompTy = dyn_cast(TyDesc)){ - // Fetch tag. - unsigned Tag = CompTy->getTag(); - - // Set tag accordingly. - if (Tag == DW_TAG_vector_type) - Buffer.setTag(DW_TAG_array_type); - else - Buffer.setTag(Tag); - - std::vector &Elements = CompTy->getElements(); - - switch (Tag) { - case DW_TAG_vector_type: - AddUInt(&Buffer, DW_AT_GNU_vector, DW_FORM_flag, 1); - // Fall thru - case DW_TAG_array_type: { - // Add element type. - if (TypeDesc *FromTy = CompTy->getFromType()) - AddType(&Buffer, FromTy, Unit); - - // Don't emit size attribute. - Size = 0; - - // Construct an anonymous type for index type. - DIE *IndexTy = ConstructBasicType(Unit, "", DW_ATE_signed, - sizeof(int32_t)); - - // Add subranges to array type. - for(unsigned i = 0, N = Elements.size(); i < N; ++i) { - SubrangeDesc *SRD = cast(Elements[i]); - int64_t Lo = SRD->getLo(); - int64_t Hi = SRD->getHi(); - DIE *Subrange = new DIE(DW_TAG_subrange_type); - - // If a range is available. - if (Lo != Hi) { - AddDIEntry(Subrange, DW_AT_type, DW_FORM_ref4, IndexTy); - // Only add low if non-zero. - if (Lo) AddSInt(Subrange, DW_AT_lower_bound, 0, Lo); - AddSInt(Subrange, DW_AT_upper_bound, 0, Hi); - } - - Buffer.AddChild(Subrange); - } - break; - } - case DW_TAG_structure_type: - case DW_TAG_union_type: { - // Add elements to structure type. - for(unsigned i = 0, N = Elements.size(); i < N; ++i) { - DebugInfoDesc *Element = Elements[i]; - - if (DerivedTypeDesc *MemberDesc = dyn_cast(Element)){ - // Add field or base class. - - unsigned Tag = MemberDesc->getTag(); - - // Extract the basic information. - const std::string &Name = MemberDesc->getName(); - uint64_t Size = MemberDesc->getSize(); - uint64_t Align = MemberDesc->getAlign(); - uint64_t Offset = MemberDesc->getOffset(); - - // Construct member debug information entry. - DIE *Member = new DIE(Tag); - - // Add name if not "". - if (!Name.empty()) - AddString(Member, DW_AT_name, DW_FORM_string, Name); - // Add location if available. - AddSourceLine(Member, MemberDesc->getFile(), MemberDesc->getLine()); - - // Most of the time the field info is the same as the members. - uint64_t FieldSize = Size; - uint64_t FieldAlign = Align; - uint64_t FieldOffset = Offset; - - // Set the member type. - TypeDesc *FromTy = MemberDesc->getFromType(); - AddType(Member, FromTy, Unit); - - // Walk up typedefs until a real size is found. - while (FromTy) { - if (FromTy->getTag() != DW_TAG_typedef) { - FieldSize = FromTy->getSize(); - FieldAlign = FromTy->getSize(); - break; - } - - FromTy = cast(FromTy)->getFromType(); - } - - // Unless we have a bit field. - if (Tag == DW_TAG_member && FieldSize != Size) { - // Construct the alignment mask. - uint64_t AlignMask = ~(FieldAlign - 1); - // Determine the high bit + 1 of the declared size. - uint64_t HiMark = (Offset + FieldSize) & AlignMask; - // Work backwards to determine the base offset of the field. - FieldOffset = HiMark - FieldSize; - // Now normalize offset to the field. - Offset -= FieldOffset; - - // Maybe we need to work from the other end. - if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); - - // Add size and offset. - AddUInt(Member, DW_AT_byte_size, 0, FieldSize >> 3); - AddUInt(Member, DW_AT_bit_size, 0, Size); - AddUInt(Member, DW_AT_bit_offset, 0, Offset); - } - - // Add computation for offset. - DIEBlock *Block = new DIEBlock(); - AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst); - AddUInt(Block, 0, DW_FORM_udata, FieldOffset >> 3); - AddBlock(Member, DW_AT_data_member_location, 0, Block); - - // Add accessibility (public default unless is base class. - if (MemberDesc->isProtected()) { - AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_protected); - } else if (MemberDesc->isPrivate()) { - AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_private); - } else if (Tag == DW_TAG_inheritance) { - AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_public); - } - - Buffer.AddChild(Member); - } else if (GlobalVariableDesc *StaticDesc = - dyn_cast(Element)) { - // Add static member. - - // Construct member debug information entry. - DIE *Static = new DIE(DW_TAG_variable); - - // Add name and mangled name. - const std::string &Name = StaticDesc->getName(); - const std::string &LinkageName = StaticDesc->getLinkageName(); - AddString(Static, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(Static, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - - // Add location. - AddSourceLine(Static, StaticDesc->getFile(), StaticDesc->getLine()); - - // Add type. - if (TypeDesc *StaticTy = StaticDesc->getType()) - AddType(Static, StaticTy, Unit); - - // Add flags. - if (!StaticDesc->isStatic()) - AddUInt(Static, DW_AT_external, DW_FORM_flag, 1); - AddUInt(Static, DW_AT_declaration, DW_FORM_flag, 1); - - Buffer.AddChild(Static); - } else if (SubprogramDesc *MethodDesc = - dyn_cast(Element)) { - // Add member function. - - // Construct member debug information entry. - DIE *Method = new DIE(DW_TAG_subprogram); - - // Add name and mangled name. - const std::string &Name = MethodDesc->getName(); - const std::string &LinkageName = MethodDesc->getLinkageName(); - - AddString(Method, DW_AT_name, DW_FORM_string, Name); - bool IsCTor = TyDesc->getName() == Name; - - if (!LinkageName.empty()) { - AddString(Method, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - - // Add location. - AddSourceLine(Method, MethodDesc->getFile(), MethodDesc->getLine()); - - // Add type. - if (CompositeTypeDesc *MethodTy = - dyn_cast_or_null(MethodDesc->getType())) { - // Get argument information. - std::vector &Args = MethodTy->getElements(); - - // If not a ctor. - if (!IsCTor) { - // Add return type. - AddType(Method, dyn_cast(Args[0]), Unit); - } - - // Add arguments. - for(unsigned i = 1, N = Args.size(); i < N; ++i) { - DIE *Arg = new DIE(DW_TAG_formal_parameter); - AddType(Arg, cast(Args[i]), Unit); - AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); - Method->AddChild(Arg); - } - } - - // Add flags. - if (!MethodDesc->isStatic()) - AddUInt(Method, DW_AT_external, DW_FORM_flag, 1); - AddUInt(Method, DW_AT_declaration, DW_FORM_flag, 1); - - Buffer.AddChild(Method); - } - } - break; - } - case DW_TAG_enumeration_type: { - // Add enumerators to enumeration type. - for(unsigned i = 0, N = Elements.size(); i < N; ++i) { - EnumeratorDesc *ED = cast(Elements[i]); - const std::string &Name = ED->getName(); - int64_t Value = ED->getValue(); - DIE *Enumerator = new DIE(DW_TAG_enumerator); - AddString(Enumerator, DW_AT_name, DW_FORM_string, Name); - AddSInt(Enumerator, DW_AT_const_value, DW_FORM_sdata, Value); - Buffer.AddChild(Enumerator); - } - - break; - } - case DW_TAG_subroutine_type: { - // Add prototype flag. - AddUInt(&Buffer, DW_AT_prototyped, DW_FORM_flag, 1); - // Add return type. - AddType(&Buffer, dyn_cast(Elements[0]), Unit); - - // Add arguments. - for(unsigned i = 1, N = Elements.size(); i < N; ++i) { - DIE *Arg = new DIE(DW_TAG_formal_parameter); - AddType(Arg, cast(Elements[i]), Unit); - Buffer.AddChild(Arg); - } - - break; - } - default: break; - } - } - - // Add size if non-zero (derived types don't have a size.) - if (Size) AddUInt(&Buffer, DW_AT_byte_size, 0, Size); - // Add name if not anonymous or intermediate type. - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - // Add source line info if available. - AddSourceLine(&Buffer, TyDesc->getFile(), TyDesc->getLine()); - } - - /// NewCompileUnit - Create new compile unit and it's debug information entry. - /// - CompileUnit *NewCompileUnit(CompileUnitDesc *UnitDesc, unsigned ID) { - // Construct debug information entry. - DIE *Die = new DIE(DW_TAG_compile_unit); - AddSectionOffset(Die, DW_AT_stmt_list, DW_FORM_data4, - DWLabel("section_line", 0), DWLabel("section_line", 0), false); - AddString(Die, DW_AT_producer, DW_FORM_string, UnitDesc->getProducer()); - AddUInt (Die, DW_AT_language, DW_FORM_data1, UnitDesc->getLanguage()); - AddString(Die, DW_AT_name, DW_FORM_string, UnitDesc->getFileName()); - AddString(Die, DW_AT_comp_dir, DW_FORM_string, UnitDesc->getDirectory()); - - // Construct compile unit. - CompileUnit *Unit = new CompileUnit(UnitDesc, ID, Die); - - // Add Unit to compile unit map. - DescToUnitMap[UnitDesc] = Unit; - - return Unit; - } - - /// GetBaseCompileUnit - Get the main compile unit. - /// - CompileUnit *GetBaseCompileUnit() const { - CompileUnit *Unit = CompileUnits[0]; - assert(Unit && "Missing compile unit."); - return Unit; - } - - /// FindCompileUnit - Get the compile unit for the given descriptor. - /// - CompileUnit *FindCompileUnit(CompileUnitDesc *UnitDesc) { - CompileUnit *Unit = DescToUnitMap[UnitDesc]; - assert(Unit && "Missing compile unit."); - return Unit; - } - - /// NewGlobalVariable - Add a new global variable DIE. - /// - DIE *NewGlobalVariable(GlobalVariableDesc *GVD) { - // Get the compile unit context. - CompileUnitDesc *UnitDesc = - static_cast(GVD->getContext()); - CompileUnit *Unit = GetBaseCompileUnit(); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(GVD); - if (Slot) return Slot; - - // Get the global variable itself. - GlobalVariable *GV = GVD->getGlobalVariable(); - - const std::string &Name = GVD->getName(); - const std::string &FullName = GVD->getFullName(); - const std::string &LinkageName = GVD->getLinkageName(); - // Create the global's variable DIE. - DIE *VariableDie = new DIE(DW_TAG_variable); - AddString(VariableDie, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - AddType(VariableDie, GVD->getType(), Unit); - if (!GVD->isStatic()) - AddUInt(VariableDie, DW_AT_external, DW_FORM_flag, 1); - - // Add source line info if available. - AddSourceLine(VariableDie, UnitDesc, GVD->getLine()); - - // Add address. - DIEBlock *Block = new DIEBlock(); - AddUInt(Block, 0, DW_FORM_data1, DW_OP_addr); - AddObjectLabel(Block, 0, DW_FORM_udata, Asm->getGlobalLinkName(GV)); - AddBlock(VariableDie, DW_AT_location, 0, Block); - - // Add to map. - Slot = VariableDie; - - // Add to context owner. - Unit->getDie()->AddChild(VariableDie); - - // Expose as global. - // FIXME - need to check external flag. - Unit->AddGlobal(FullName, VariableDie); - - return VariableDie; - } - - /// NewSubprogram - Add a new subprogram DIE. - /// - DIE *NewSubprogram(SubprogramDesc *SPD) { - // Get the compile unit context. - CompileUnitDesc *UnitDesc = - static_cast(SPD->getContext()); - CompileUnit *Unit = GetBaseCompileUnit(); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(SPD); - if (Slot) return Slot; - - // Gather the details (simplify add attribute code.) - const std::string &Name = SPD->getName(); - const std::string &FullName = SPD->getFullName(); - const std::string &LinkageName = SPD->getLinkageName(); - - DIE *SubprogramDie = new DIE(DW_TAG_subprogram); - AddString(SubprogramDie, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(SubprogramDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - if (SPD->getType()) AddType(SubprogramDie, SPD->getType(), Unit); - if (!SPD->isStatic()) - AddUInt(SubprogramDie, DW_AT_external, DW_FORM_flag, 1); - AddUInt(SubprogramDie, DW_AT_prototyped, DW_FORM_flag, 1); - - // Add source line info if available. - AddSourceLine(SubprogramDie, UnitDesc, SPD->getLine()); - - // Add to map. - Slot = SubprogramDie; - - // Add to context owner. - Unit->getDie()->AddChild(SubprogramDie); - - // Expose as global. - Unit->AddGlobal(FullName, SubprogramDie); - - return SubprogramDie; - } - - /// NewScopeVariable - Create a new scope variable. - /// - DIE *NewScopeVariable(DebugVariable *DV, CompileUnit *Unit) { - // Get the descriptor. - VariableDesc *VD = DV->getDesc(); - - // Translate tag to proper Dwarf tag. The result variable is dropped for - // now. - unsigned Tag; - switch (VD->getTag()) { - case DW_TAG_return_variable: return NULL; - case DW_TAG_arg_variable: Tag = DW_TAG_formal_parameter; break; - case DW_TAG_auto_variable: // fall thru - default: Tag = DW_TAG_variable; break; - } - - // Define variable debug information entry. - DIE *VariableDie = new DIE(Tag); - AddString(VariableDie, DW_AT_name, DW_FORM_string, VD->getName()); - - // Add source line info if available. - AddSourceLine(VariableDie, VD->getFile(), VD->getLine()); - - // Add variable type. - AddType(VariableDie, VD->getType(), Unit); - - // Add variable address. - MachineLocation Location; - Location.set(RI->getFrameRegister(*MF), - RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); - AddAddress(VariableDie, DW_AT_location, Location); - - return VariableDie; - } - - /// ConstructScope - Construct the components of a scope. - /// - void ConstructScope(DebugScope *ParentScope, - unsigned ParentStartID, unsigned ParentEndID, - DIE *ParentDie, CompileUnit *Unit) { - // Add variables to scope. - std::vector &Variables = ParentScope->getVariables(); - for (unsigned i = 0, N = Variables.size(); i < N; ++i) { - DIE *VariableDie = NewScopeVariable(Variables[i], Unit); - if (VariableDie) ParentDie->AddChild(VariableDie); - } - - // Add nested scopes. - std::vector &Scopes = ParentScope->getScopes(); - for (unsigned j = 0, M = Scopes.size(); j < M; ++j) { - // Define the Scope debug information entry. - DebugScope *Scope = Scopes[j]; - // FIXME - Ignore inlined functions for the time being. - if (!Scope->getParent()) continue; - - unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); - unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); - - // Ignore empty scopes. - if (StartID == EndID && StartID != 0) continue; - if (Scope->getScopes().empty() && Scope->getVariables().empty()) continue; - - if (StartID == ParentStartID && EndID == ParentEndID) { - // Just add stuff to the parent scope. - ConstructScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit); - } else { - DIE *ScopeDie = new DIE(DW_TAG_lexical_block); - - // Add the scope bounds. - if (StartID) { - AddLabel(ScopeDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("label", StartID)); - } else { - AddLabel(ScopeDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - } - if (EndID) { -