X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfWriter.cpp;h=4120d9f917105721e3490c31557a796218456ff1;hb=b169426272b85ce28a9a56d13154e61b158fc47a;hp=e17dd527c5e6d377ea2fac89e3375eba4bd5ff39;hpb=e2051627b81c713fd29f61ce6d4424d0388cc37d;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index e17dd527c5e..4120d9f9171 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -12,13 +12,9 @@ //===----------------------------------------------------------------------===// #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/DerivedTypes.h" +#include "llvm/Constants.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -29,6 +25,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Mangler.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/Target/TargetAsmInfo.h" @@ -38,6 +35,10 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include #include using namespace llvm; @@ -47,15 +48,20 @@ static RegisterPass X("dwarfwriter", "DWARF Information Writer"); char DwarfWriter::ID = 0; +static TimerGroup &getDwarfTimerGroup() { + static TimerGroup DwarfTimerGroup("Dwarf Exception and Debugging"); + return DwarfTimerGroup; +} + 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 +static const unsigned InitDiesSetSize = 9; // log2(512) +static const unsigned InitAbbreviationsSetSize = 9; // log2(512) +static const unsigned InitValuesSetSize = 9; // log2(512) //===----------------------------------------------------------------------===// /// Forward declarations. @@ -66,38 +72,23 @@ class DIEValue; //===----------------------------------------------------------------------===// /// Utility routines. /// -/// getGlobalVariablesUsing - Return all of the GlobalVariables which have the -/// specified value in their initializer somewhere. -static void -getGlobalVariablesUsing(Value *V, std::vector &Result) { - // Scan though value users. - for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { - if (GlobalVariable *GV = dyn_cast(*I)) { - // If the user is a GlobalVariable then add to result. - Result.push_back(GV); - } else if (Constant *C = dyn_cast(*I)) { - // If the user is a constant variable then scan its users - getGlobalVariablesUsing(C, Result); +/// getGlobalVariable - Return either a direct or cast Global value. +/// +static GlobalVariable *getGlobalVariable(Value *V) { + if (GlobalVariable *GV = dyn_cast(V)) { + return GV; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() == Instruction::BitCast) { + return dyn_cast(CE->getOperand(0)); + } else if (CE->getOpcode() == Instruction::GetElementPtr) { + for (unsigned int i=1; igetNumOperands(); i++) { + if (!CE->getOperand(i)->isNullValue()) + return NULL; + } + return dyn_cast(CE->getOperand(0)); } } -} - -/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the -/// named GlobalVariable. -static void -getGlobalVariablesUsing(Module &M, const std::string &RootName, - std::vector &Result) { - std::vector FieldTypes; - FieldTypes.push_back(Type::Int32Ty); - FieldTypes.push_back(Type::Int32Ty); - - // Get the GlobalVariable root. - GlobalVariable *UseRoot = M.getGlobalVariable(RootName, - StructType::get(FieldTypes)); - - // If present and linkonce then scan for users. - if (UseRoot && UseRoot->hasLinkOnceLinkage()) - getGlobalVariablesUsing(UseRoot, Result); + return NULL; } //===----------------------------------------------------------------------===// @@ -118,7 +109,7 @@ public: DWLabel(const char *T, unsigned N) : Tag(T), Number(N) {} void Profile(FoldingSetNodeID &ID) const { - ID.AddString(std::string(Tag)); + ID.AddString(Tag); ID.AddInteger(Number); } @@ -137,7 +128,6 @@ public: /// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a /// Dwarf abbreviation. class DIEAbbrevData { -private: /// Attribute - Dwarf attribute code. /// unsigned Attribute; @@ -145,12 +135,8 @@ private: /// Form - Dwarf form code. /// unsigned Form; - public: - DIEAbbrevData(unsigned A, unsigned F) - : Attribute(A) - , Form(F) - {} + DIEAbbrevData(unsigned A, unsigned F) : Attribute(A), Form(F) {} // Accessors. unsigned getAttribute() const { return Attribute; } @@ -184,15 +170,9 @@ private: /// Data - Raw data bytes for abbreviation. /// SmallVector Data; - public: - - DIEAbbrev(unsigned T, unsigned C) - : Tag(T) - , ChildrenFlag(C) - , Data() - {} - ~DIEAbbrev() {} + DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} + virtual ~DIEAbbrev() {} // Accessors. unsigned getTag() const { return Tag; } @@ -266,12 +246,7 @@ protected: public: explicit DIE(unsigned Tag) - : Abbrev(Tag, DW_CHILDREN_no) - , Offset(0) - , Size(0) - , Children() - , Values() - {} + : Abbrev(Tag, DW_CHILDREN_no), Offset(0), Size(0), Children(), Values() {} virtual ~DIE(); // Accessors. @@ -349,9 +324,7 @@ public: /// unsigned Type; - explicit DIEValue(unsigned T) - : Type(T) - {} + explicit DIEValue(unsigned T) : Type(T) {} virtual ~DIEValue() {} // Accessors @@ -438,10 +411,9 @@ public: /// DIEString - A string value DIE. /// class DIEString : public DIEValue { + const std::string Str; public: - const std::string String; - - explicit DIEString(const std::string &S) : DIEValue(isString), String(S) {} + explicit DIEString(const std::string &S) : DIEValue(isString), Str(S) {} // Implement isa/cast/dyncast. static bool classof(const DIEString *) { return true; } @@ -454,20 +426,20 @@ public: /// SizeOf - Determine size of string value in bytes. /// virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const { - return String.size() + sizeof(char); // sizeof('\0'); + return Str.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) { + static void Profile(FoldingSetNodeID &ID, const std::string &Str) { ID.AddInteger(isString); - ID.AddString(String); + ID.AddString(Str); } - virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, String); } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Str); } #ifndef NDEBUG virtual void print(std::ostream &O) { - O << "Str: \"" << String << "\""; + O << "Str: \"" << Str << "\""; } #endif }; @@ -476,10 +448,8 @@ public: /// DIEDwarfLabel - A Dwarf internal label expression DIE. // class DIEDwarfLabel : public DIEValue { -public: - const DWLabel Label; - +public: explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {} // Implement isa/cast/dyncast. @@ -510,14 +480,12 @@ public: #endif }; - //===----------------------------------------------------------------------===// /// DIEObjectLabel - A label to an object in code or data. // class DIEObjectLabel : public DIEValue { -public: const std::string Label; - +public: explicit DIEObjectLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {} @@ -539,7 +507,7 @@ public: ID.AddInteger(isAsIsLabel); ID.AddString(Label); } - virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label); } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label.c_str()); } #ifndef NDEBUG virtual void print(std::ostream &O) { @@ -552,16 +520,15 @@ public: /// DIESectionOffset - A section offset DIE. // class DIESectionOffset : public DIEValue { -public: const DWLabel Label; const DWLabel Section; bool IsEH : 1; bool UseSet : 1; - +public: DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec, bool isEH = false, bool useSet = true) - : DIEValue(isSectionOffset), Label(Lab), Section(Sec), - IsEH(isEH), UseSet(useSet) {} + : DIEValue(isSectionOffset), Label(Lab), Section(Sec), + IsEH(isEH), UseSet(useSet) {} // Implement isa/cast/dyncast. static bool classof(const DIESectionOffset *) { return true; } @@ -602,12 +569,11 @@ public: /// DIEDelta - A simple label difference DIE. /// class DIEDelta : public DIEValue { -public: const DWLabel LabelHi; const DWLabel LabelLo; - +public: DIEDelta(const DWLabel &Hi, const DWLabel &Lo) - : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} // Implement isa/cast/dyncast. static bool classof(const DIEDelta *) { return true; } @@ -646,11 +612,12 @@ public: /// 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; - +public: explicit DIEntry(DIE *E) : DIEValue(isEntry), Entry(E) {} + void setEntry(DIE *E) { Entry = E; } + // Implement isa/cast/dyncast. static bool classof(const DIEntry *) { return true; } static bool classof(const DIEValue *E) { return E->Type == isEntry; } @@ -692,16 +659,11 @@ public: /// DIEBlock - A block of values. Primarily used for location expressions. // class DIEBlock : public DIEValue, public DIE { + unsigned Size; // Size in bytes excluding size header. public: - unsigned Size; // Size in bytes excluding size header. - DIEBlock() - : DIEValue(isBlock) - , DIE(0) - , Size(0) - {} - ~DIEBlock() { - } + : DIEValue(isBlock), DIE(0), Size(0) {} + virtual ~DIEBlock() {} // Implement isa/cast/dyncast. static bool classof(const DIEBlock *) { return true; } @@ -728,7 +690,6 @@ public: /// 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) { @@ -748,11 +709,6 @@ public: /// 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; @@ -761,15 +717,13 @@ private: /// DIE *Die; - /// DescToDieMap - Tracks the mapping of unit level debug informaton - /// descriptors to debug information entries. - std::map DescToDieMap; - DenseMap GVToDieMap; + /// GVToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + std::map GVToDieMap; - /// DescToDIEntryMap - Tracks the mapping of unit level debug informaton + /// GVToDIEntryMap - Tracks the mapping of unit level debug informaton /// descriptors to debug information entries using a DIEntry proxy. - std::map DescToDIEntryMap; - DenseMap GVToDIEntryMap; + std::map GVToDIEntryMap; /// Globals - A map of globally visible named entities for this unit. /// @@ -778,39 +732,17 @@ private: /// 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(unsigned I, DIE *D) - : ID(I), Die(D), DescToDieMap(), GVToDieMap(), DescToDIEntryMap(), - GVToDIEntryMap(), Globals(), DiesSet(InitDiesSetSize), Dies() - {} - - CompileUnit(CompileUnitDesc *CUD, unsigned I, DIE *D) - : Desc(CUD) - , ID(I) - , Die(D) - , DescToDieMap() - , GVToDieMap() - , DescToDIEntryMap() - , GVToDIEntryMap() - , Globals() - , DiesSet(InitDiesSetSize) - , Dies() + : ID(I), Die(D), GVToDieMap(), + GVToDIEntryMap(), Globals(), DiesSet(InitDiesSetSize) {} ~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; } @@ -828,19 +760,13 @@ public: } /// getDieMapSlotFor - Returns the debug information entry map slot for the - /// specified debug descriptor. - DIE *&getDieMapSlotFor(DebugInfoDesc *DID) { - return DescToDieMap[DID]; - } + /// specified debug variable. DIE *&getDieMapSlotFor(GlobalVariable *GV) { return GVToDieMap[GV]; } /// getDIEntrySlotFor - Returns the debug information entry proxy slot for the - /// specified debug descriptor. - DIEntry *&getDIEntrySlotFor(DebugInfoDesc *DID) { - return DescToDIEntryMap[DID]; - } + /// specified debug variable. DIEntry *&getDIEntrySlotFor(GlobalVariable *GV) { return GVToDIEntryMap[GV]; } @@ -868,9 +794,7 @@ public: /// Dwarf - Emits general Dwarf directives. /// class Dwarf { - protected: - //===--------------------------------------------------------------------===// // Core attributes used by the Dwarf writer. // @@ -931,7 +855,6 @@ protected: } public: - //===--------------------------------------------------------------------===// // Accessors. // @@ -1179,7 +1102,7 @@ class SrcLineInfo { unsigned LabelID; // Label in code ID number. public: SrcLineInfo(unsigned L, unsigned C, unsigned S, unsigned I) - : Line(L), Column(C), SourceID(S), LabelID(I) {} + : Line(L), Column(C), SourceID(S), LabelID(I) {} // Accessors unsigned getLine() const { return Line; } @@ -1188,47 +1111,17 @@ public: unsigned getLabelID() const { return LabelID; } }; - -//===----------------------------------------------------------------------===// -/// SrcFileInfo - This class is used to track source information. -/// -class SrcFileInfo { - unsigned DirectoryID; // Directory ID number. - std::string Name; // File name (not including directory.) -public: - SrcFileInfo(unsigned D, const std::string &N) : DirectoryID(D), Name(N) {} - - // Accessors - unsigned getDirectoryID() const { return DirectoryID; } - const std::string &getName() const { return Name; } - - /// operator== - Used by UniqueVector to locate entry. - /// - bool operator==(const SourceFileInfo &SI) const { - return getDirectoryID() == SI.getDirectoryID() && getName() == SI.getName(); - } - - /// operator< - Used by UniqueVector to locate entry. - /// - bool operator<(const SrcFileInfo &SI) const { - return getDirectoryID() < SI.getDirectoryID() || - (getDirectoryID() == SI.getDirectoryID() && getName() < SI.getName()); - } -}; - //===----------------------------------------------------------------------===// /// DbgVariable - This class is used to track local variable information. /// class DbgVariable { -private: - DIVariable *Var; // Variable Descriptor. + DIVariable Var; // Variable Descriptor. unsigned FrameIndex; // Variable frame index. - public: - DbgVariable(DIVariable *V, unsigned I) : Var(V), FrameIndex(I) {} + DbgVariable(DIVariable V, unsigned I) : Var(V), FrameIndex(I) {} // Accessors. - DIVariable *getVariable() const { return Var; } + DIVariable getVariable() const { return Var; } unsigned getFrameIndex() const { return FrameIndex; } }; @@ -1236,17 +1129,15 @@ public: /// DbgScope - This class is used to track scope information. /// class DbgScope { -private: DbgScope *Parent; // Parent to this scope. - DIDescriptor *Desc; // Debug info descriptor for scope. + DIDescriptor Desc; // Debug info descriptor for scope. // Either subprogram or block. unsigned StartLabelID; // Label ID of the beginning of scope. unsigned EndLabelID; // Label ID of the end of scope. - SmallVector Scopes; // Scopes defined in scope. + SmallVector Scopes; // Scopes defined in scope. SmallVector Variables;// Variables declared in scope. - public: - DbgScope(DbgScope *P, DIDescriptor *D) + DbgScope(DbgScope *P, DIDescriptor D) : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0), Scopes(), Variables() {} ~DbgScope() { @@ -1255,8 +1146,8 @@ public: } // Accessors. - DbgScope *getParent() const { return Parent; } - DIDescriptor *getDesc() const { return Desc; } + DbgScope *getParent() const { return Parent; } + DIDescriptor getDesc() const { return Desc; } unsigned getStartLabelID() const { return StartLabelID; } unsigned getEndLabelID() const { return EndLabelID; } SmallVector &getScopes() { return Scopes; } @@ -1277,16 +1168,21 @@ public: /// 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; - DenseMap DW_CUs; + /// CompileUnitMap - A map of global variables representing compile units to + /// compile units. + DenseMap CompileUnitMap; + + /// CompileUnits - All the compile units in this module. + /// + SmallVector CompileUnits; + + /// MainCU - Some platform prefers one compile unit per .o file. In such + /// cases, all dies are inserted in MainCU. + CompileUnit *MainCU; /// AbbreviationsSet - Used to uniquely define abbreviations. /// @@ -1296,17 +1192,33 @@ private: /// std::vector Abbreviations; - /// ValuesSet - Used to uniquely define values. + /// DirectoryIdMap - Directory name to directory id map. + /// + StringMap DirectoryIdMap; + + /// DirectoryNames - A list of directory names. + SmallVector DirectoryNames; + + /// SourceFileIdMap - Source file name to source file id map. /// - // Directories - Uniquing vector for directories. - UniqueVector Directories; + StringMap SourceFileIdMap; + + /// SourceFileNames - A list of source file names. + SmallVector SourceFileNames; - // SourceFiles - Uniquing vector for source files. - UniqueVector SrcFiles; + /// SourceIdMap - Source id map, i.e. pair of directory id and source file + /// id mapped to a unique id. + DenseMap, unsigned> SourceIdMap; + + /// SourceIds - Reverse map from source id to directory id + file id pair. + /// + SmallVector, 8> SourceIds; - // Lines - List of of source line correspondence. + /// Lines - List of of source line correspondence. std::vector Lines; + /// ValuesSet - Used to uniquely define values. + /// FoldingSet ValuesSet; /// Values - A list of all the unique values in use. @@ -1317,10 +1229,6 @@ private: /// UniqueVector StringPool; - /// UnitMap - Map debug information descriptor to compile unit. - /// - std::map DescToUnitMap; - /// SectionMap - Provides a unique id per text section. /// UniqueVector SectionMap; @@ -1337,12 +1245,15 @@ private: /// bool shouldEmit; - // RootScope - Top level scope for the current function. + // RootDbgScope - Top level scope for the current function. // DbgScope *RootDbgScope; - // DbgScopeMap - Tracks the scopes in the current function. + /// DbgScopeMap - Tracks the scopes in the current function. DenseMap DbgScopeMap; + + /// DebugTimer - Timer for the Dwarf debug writer. + Timer *DebugTimer; struct FunctionDebugFrameInfo { unsigned Number; @@ -1354,11 +1265,36 @@ private: std::vector DebugFrames; -public: +private: + /// getSourceDirectoryAndFileIds - Return the directory and file ids that + /// maps to the source id. Source id starts at 1. + std::pair + getSourceDirectoryAndFileIds(unsigned SId) const { + return SourceIds[SId-1]; + } - /// ShouldEmitDwarf - Returns true if Dwarf declarations should be made. - /// - bool ShouldEmitDwarf() const { return shouldEmit; } + /// getNumSourceDirectories - Return the number of source directories in the + /// debug info. + unsigned getNumSourceDirectories() const { + return DirectoryNames.size(); + } + + /// getSourceDirectoryName - Return the name of the directory corresponding + /// to the id. + const std::string &getSourceDirectoryName(unsigned Id) const { + return DirectoryNames[Id - 1]; + } + + /// getSourceFileName - Return the name of the source file corresponding + /// to the id. + const std::string &getSourceFileName(unsigned Id) const { + return SourceFileNames[Id - 1]; + } + + /// getNumSourceIds - Return the number of unique source ids. + unsigned getNumSourceIds() const { + return SourceIds.size(); + } /// AssignAbbrevNumber - Define a unique number for the abbreviation. /// @@ -1415,7 +1351,7 @@ public: /// SetDIEntry - Set a DIEntry once the debug information entry is defined. /// void SetDIEntry(DIEntry *Value, DIE *Entry) { - Value->Entry = Entry; + Value->setEntry(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); @@ -1457,7 +1393,7 @@ public: Die->AddValue(Attribute, Form, Value); } - /// AddString - Add a std::string attribute data and value. + /// AddString - Add a string attribute data and value. /// void AddString(DIE *Die, unsigned Attribute, unsigned Form, const std::string &String) { @@ -1570,70 +1506,39 @@ public: 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); - } - } - /// AddSourceLine - Add location information to specified debug information /// entry. - void AddSourceLine(DIE *Die, DIVariable *V) { + void AddSourceLine(DIE *Die, const DIVariable *V) { unsigned FileID = 0; unsigned Line = V->getLineNumber(); - if (V->getVersion() < DIDescriptor::Version7) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(V->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIVariable - // directly. - unsigned DID = Directories.idFor(V->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, V->getFilename())); - } + CompileUnit *Unit = FindCompileUnit(V->getCompileUnit()); + FileID = Unit->getID(); + assert (FileID && "Invalid file id"); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } /// AddSourceLine - Add location information to specified debug information /// entry. - void AddSourceLine(DIE *Die, DIGlobal *G) { + void AddSourceLine(DIE *Die, const DIGlobal *G) { unsigned FileID = 0; unsigned Line = G->getLineNumber(); - if (G->getVersion() < DIDescriptor::Version7) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIGlobal - // directly. - unsigned DID = Directories.idFor(G->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, G->getFilename())); - } + CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); + FileID = Unit->getID(); + assert (FileID && "Invalid file id"); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } - void AddSourceLine(DIE *Die, DIType *G) { + void AddSourceLine(DIE *Die, const DIType *Ty) { unsigned FileID = 0; - unsigned Line = G->getLineNumber(); - if (G->getVersion() < DIDescriptor::Version7) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIGlobal - // directly. - unsigned DID = Directories.idFor(G->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, G->getFilename())); - } + unsigned Line = Ty->getLineNumber(); + DICompileUnit CU = Ty->getCompileUnit(); + if (CU.isNull()) + return; + CompileUnit *Unit = FindCompileUnit(CU); + FileID = Unit->getID(); + assert (FileID && "Invalid file id"); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } @@ -1665,76 +1570,10 @@ private: 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 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); - DIE *BasicTypeDie = Unit->AddDie(Buffer); - AddDIEntry(Entity, DW_AT_type, DW_FORM_ref4, BasicTypeDie); - } - - /// AddPointerType - Add a new pointer type attribute to the specified entity. - /// - void AddPointerType(DIE *Entity, 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); - DIE *PointerTypeDie = Unit->AddDie(Buffer); - AddDIEntry(Entity, DW_AT_type, DW_FORM_ref4, PointerTypeDie); - } - - /// 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); - } - } - } - /// AddType - Add a new type attribute to the specified entity. void AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { - if (Ty.isNull()) { - AddBasicType(Entity, DW_Unit, "", DW_ATE_signed, sizeof(int32_t)); + if (Ty.isNull()) return; - } // Check for pre-existence. DIEntry *&Slot = DW_Unit->getDIEntrySlotFor(Ty.getGV()); @@ -1749,52 +1588,72 @@ private: // Construct type. DIE Buffer(DW_TAG_base_type); - if (DIBasicType *BT = dyn_cast(&Ty)) - ConstructTypeDIE(DW_Unit, Buffer, BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - ConstructTypeDIE(DW_Unit, Buffer, DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - ConstructTypeDIE(DW_Unit, Buffer, CT); - - // Add debug information entry to entity and unit. - DIE *Die = DW_Unit->AddDie(Buffer); - SetDIEntry(Slot, Die); + if (Ty.isBasicType(Ty.getTag())) + ConstructTypeDIE(DW_Unit, Buffer, DIBasicType(Ty.getGV())); + else if (Ty.isDerivedType(Ty.getTag())) + ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getGV())); + else { + assert(Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType"); + ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getGV())); + } + + // Add debug information entry to entity and appropriate context. + DIE *Die = NULL; + DIDescriptor Context = Ty.getContext(); + if (!Context.isNull()) + Die = DW_Unit->getDieMapSlotFor(Context.getGV()); + + if (Die) { + DIE *Child = new DIE(Buffer); + Die->AddChild(Child); + Buffer.Detach(); + SetDIEntry(Slot, Child); + } else { + Die = DW_Unit->AddDie(Buffer); + SetDIEntry(Slot, Die); + } + Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); } /// ConstructTypeDIE - Construct basic type die from DIBasicType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DIBasicType *BTy) { + DIBasicType BTy) { // Get core information. - const std::string &Name = BTy->getName(); + std::string Name; + BTy.getName(Name); Buffer.setTag(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BTy->getEncoding()); + AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BTy.getEncoding()); // Add name if not anonymous or intermediate type. if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - uint64_t Size = BTy->getSizeInBits() >> 3; + uint64_t Size = BTy.getSizeInBits() >> 3; AddUInt(&Buffer, DW_AT_byte_size, 0, Size); } /// ConstructTypeDIE - Construct derived type die from DIDerivedType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DIDerivedType *DTy) { + DIDerivedType DTy) { // Get core information. - const std::string &Name = DTy->getName(); - uint64_t Size = DTy->getSizeInBits() >> 3; - unsigned Tag = DTy->getTag(); + std::string Name; + DTy.getName(Name); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); + // FIXME - Workaround for templates. if (Tag == DW_TAG_inheritance) Tag = DW_TAG_reference_type; Buffer.setTag(Tag); + // Map to main type, void will not have a type. - DIType FromTy = DTy->getTypeDerivedFrom(); + DIType FromTy = DTy.getTypeDerivedFrom(); AddType(DW_Unit, &Buffer, FromTy); // Add name if not anonymous or intermediate type. - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); + if (!Name.empty()) + AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); // Add size if non-zero (derived types might be zero-sized.) if (Size) @@ -1802,55 +1661,52 @@ private: // Add source line info if available and TyDesc is not a forward // declaration. - // FIXME - Enable this. if (!DTy->isForwardDecl()) - // FIXME - Enable this. AddSourceLine(&Buffer, *DTy); + if (!DTy.isForwardDecl()) + AddSourceLine(&Buffer, &DTy); } /// ConstructTypeDIE - Construct type DIE from DICompositeType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DICompositeType *CTy) { + DICompositeType CTy) { + // Get core information. + std::string Name; + CTy.getName(Name); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); - // Get core information. - const std::string &Name = CTy->getName(); - uint64_t Size = CTy->getSizeInBits() >> 3; - unsigned Tag = CTy->getTag(); switch (Tag) { case DW_TAG_vector_type: case DW_TAG_array_type: - ConstructArrayTypeDIE(DW_Unit, Buffer, CTy); + ConstructArrayTypeDIE(DW_Unit, Buffer, &CTy); + break; + case DW_TAG_enumeration_type: + { + DIArray Elements = CTy.getTypeArray(); + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIEnumerator Enum(Elements.getElement(i).getGV()); + ElemDie = ConstructEnumTypeDIE(DW_Unit, &Enum); + Buffer.AddChild(ElemDie); + } + } break; - //FIXME - Enable this. - // case DW_TAG_enumeration_type: - // DIArray Elements = CTy->getTypeArray(); - // // Add enumerators to enumeration type. - // for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) - // ConstructEnumTypeDIE(Buffer, &Elements.getElement(i)); - // break; case DW_TAG_subroutine_type: { // Add prototype flag. AddUInt(&Buffer, DW_AT_prototyped, DW_FORM_flag, 1); - DIArray Elements = CTy->getTypeArray(); + DIArray Elements = CTy.getTypeArray(); // Add return type. DIDescriptor RTy = Elements.getElement(0); - if (DIBasicType *BT = dyn_cast(&RTy)) - AddType(DW_Unit, &Buffer, *BT); - else if (DIDerivedType *DT = dyn_cast(&RTy)) - AddType(DW_Unit, &Buffer, *DT); - else if (DICompositeType *CT = dyn_cast(&RTy)) - AddType(DW_Unit, &Buffer, *CT); - - //AddType(DW_Unit, &Buffer, Elements.getElement(0)); + AddType(DW_Unit, &Buffer, DIType(RTy.getGV())); + // Add arguments. for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(DW_TAG_formal_parameter); DIDescriptor Ty = Elements.getElement(i); - if (DIBasicType *BT = dyn_cast(&Ty)) - AddType(DW_Unit, &Buffer, *BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - AddType(DW_Unit, &Buffer, *DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - AddType(DW_Unit, &Buffer, *CT); + AddType(DW_Unit, Arg, DIType(Ty.getGV())); Buffer.AddChild(Arg); } } @@ -1859,17 +1715,30 @@ private: case DW_TAG_union_type: { // Add elements to structure type. - DIArray Elements = CTy->getTypeArray(); + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + if (Elements.isNull()) + break; + // Add elements to structure type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); - if (DISubprogram *SP = dyn_cast(&Element)) - ConstructFieldTypeDIE(DW_Unit, Buffer, SP); - else if (DIDerivedType *DT = dyn_cast(&Element)) - ConstructFieldTypeDIE(DW_Unit, Buffer, DT); - else if (DIGlobalVariable *GV = dyn_cast(&Element)) - ConstructFieldTypeDIE(DW_Unit, Buffer, GV); + DIE *ElemDie = NULL; + if (Element.getTag() == dwarf::DW_TAG_subprogram) + ElemDie = CreateSubprogramDIE(DW_Unit, + DISubprogram(Element.getGV())); + else if (Element.getTag() == dwarf::DW_TAG_variable) // ??? + ElemDie = CreateGlobalVariableDIE(DW_Unit, + DIGlobalVariable(Element.getGV())); + else + ElemDie = CreateMemberDIE(DW_Unit, + DIDerivedType(Element.getGV())); + Buffer.AddChild(ElemDie); } + unsigned RLang = CTy.getRunTimeLang(); + if (RLang) + AddUInt(&Buffer, DW_AT_APPLE_runtime_class, DW_FORM_data1, RLang); } break; default: @@ -1877,37 +1746,38 @@ private: } // Add name if not anonymous or intermediate type. - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); + if (!Name.empty()) + AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - AddUInt(&Buffer, DW_AT_byte_size, 0, Size); - else { - // Add zero size even if it is not a forward declaration. - // FIXME - Enable this. - // if (!CTy->isDefinition()) - // AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1); - // else - // AddUInt(&Buffer, DW_AT_byte_size, 0, 0); + if (Tag == DW_TAG_enumeration_type || Tag == DW_TAG_structure_type + || Tag == DW_TAG_union_type) { + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + AddUInt(&Buffer, DW_AT_byte_size, 0, Size); + else { + // Add zero size if it is not a forward declaration. + if (CTy.isForwardDecl()) + AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1); + else + AddUInt(&Buffer, DW_AT_byte_size, 0, 0); + } + + // Add source line info if available. + if (!CTy.isForwardDecl()) + AddSourceLine(&Buffer, &CTy); } - - // Add source line info if available and TyDesc is not a forward - // declaration. - // FIXME - Enable this. - // if (CTy->isForwardDecl()) - // AddSourceLine(&Buffer, *CTy); } - // ConstructSubrangeDIE - Construct subrange DIE from DISubrange. - void ConstructSubrangeDIE (DIE &Buffer, DISubrange *SR, DIE *IndexTy) { - int64_t L = SR->getLo(); - int64_t H = SR->getHi(); + /// ConstructSubrangeDIE - Construct subrange DIE from DISubrange. + void ConstructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { + int64_t L = SR.getLo(); + int64_t H = SR.getHi(); DIE *DW_Subrange = new DIE(DW_TAG_subrange_type); if (L != H) { AddDIEntry(DW_Subrange, DW_AT_type, DW_FORM_ref4, IndexTy); if (L) - AddSInt(DW_Subrange, DW_AT_lower_bound, 0, L); - AddSInt(DW_Subrange, DW_AT_upper_bound, 0, H); + AddSInt(DW_Subrange, DW_AT_lower_bound, 0, L); + AddSInt(DW_Subrange, DW_AT_upper_bound, 0, H); } Buffer.AddChild(DW_Subrange); } @@ -1919,9 +1789,9 @@ private: if (CTy->getTag() == DW_TAG_vector_type) AddUInt(&Buffer, DW_AT_GNU_vector, DW_FORM_flag, 1); + // Emit derived type. + AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom()); DIArray Elements = CTy->getTypeArray(); - // FIXME - Enable this. - AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom()); // Construct an anonymous type for index type. DIE IdxBuffer(DW_TAG_base_type); @@ -1932,587 +1802,152 @@ private: // Add subranges to array type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); - if (DISubrange *SR = dyn_cast(&Element)) - ConstructSubrangeDIE(Buffer, SR, IndexTy); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + ConstructSubrangeDIE(Buffer, DISubrange(Element.getGV()), IndexTy); } } - /// ConstructEnumTypeDIE - Construct enum type DIE from - /// DIEnumerator. - void ConstructEnumTypeDIE(CompileUnit *DW_Unit, - DIE &Buffer, DIEnumerator *ETy) { + /// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator. + DIE *ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { DIE *Enumerator = new DIE(DW_TAG_enumerator); - AddString(Enumerator, DW_AT_name, DW_FORM_string, ETy->getName()); + std::string Name; + ETy->getName(Name); + AddString(Enumerator, DW_AT_name, DW_FORM_string, Name); int64_t Value = ETy->getEnumValue(); AddSInt(Enumerator, DW_AT_const_value, DW_FORM_sdata, Value); - Buffer.AddChild(Enumerator); + return Enumerator; } - /// ConstructFieldTypeDIE - Construct variable DIE for a struct field. - void ConstructFieldTypeDIE(CompileUnit *DW_Unit, - DIE &Buffer, DIGlobalVariable *V) { - - DIE *VariableDie = new DIE(DW_TAG_variable); - const std::string &LinkageName = V->getLinkageName(); - if (!LinkageName.empty()) - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - // FIXME - Enable this. AddSourceLine(VariableDie, V); - AddType(DW_Unit, VariableDie, V->getType()); - if (!V->isLocalToUnit()) - AddUInt(VariableDie, DW_AT_external, DW_FORM_flag, 1); - AddUInt(VariableDie, DW_AT_declaration, DW_FORM_flag, 1); - Buffer.AddChild(VariableDie); - } - - /// ConstructFieldTypeDIE - Construct subprogram DIE for a struct field. - void ConstructFieldTypeDIE(CompileUnit *DW_Unit, - DIE &Buffer, DISubprogram *SP, - bool IsConstructor = false) { - DIE *Method = new DIE(DW_TAG_subprogram); - AddString(Method, DW_AT_name, DW_FORM_string, SP->getName()); - const std::string &LinkageName = SP->getLinkageName(); + /// CreateGlobalVariableDIE - Create new DIE using GV. + DIE *CreateGlobalVariableDIE(CompileUnit *DW_Unit, const DIGlobalVariable &GV) + { + DIE *GVDie = new DIE(DW_TAG_variable); + std::string Name; + GV.getDisplayName(Name); + AddString(GVDie, DW_AT_name, DW_FORM_string, Name); + std::string LinkageName; + GV.getLinkageName(LinkageName); if (!LinkageName.empty()) - AddString(Method, DW_AT_MIPS_linkage_name, DW_FORM_string, LinkageName); - // FIXME - Enable this. AddSourceLine(Method, SP); - - DICompositeType MTy = SP->getType(); - DIArray Args = MTy.getTypeArray(); - - // Add Return Type. - if (!IsConstructor) { - DIDescriptor Ty = Args.getElement(0); - if (DIBasicType *BT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *CT); - } - - // Add arguments. - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(DW_TAG_formal_parameter); - DIDescriptor Ty = Args.getElement(i); - if (DIBasicType *BT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *CT); - AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); // ??? - Method->AddChild(Arg); - } - - if (!SP->isLocalToUnit()) - AddUInt(Method, DW_AT_external, DW_FORM_flag, 1); - Buffer.AddChild(Method); - } + AddString(GVDie, DW_AT_MIPS_linkage_name, DW_FORM_string, LinkageName); + AddType(DW_Unit, GVDie, GV.getType()); + if (!GV.isLocalToUnit()) + AddUInt(GVDie, DW_AT_external, DW_FORM_flag, 1); + AddSourceLine(GVDie, &GV); + return GVDie; + } + + /// CreateMemberDIE - Create new member DIE. + DIE *CreateMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT) { + DIE *MemberDie = new DIE(DT.getTag()); + std::string Name; + DT.getName(Name); + if (!Name.empty()) + AddString(MemberDie, DW_AT_name, DW_FORM_string, Name); - /// COnstructFieldTypeDIE - Construct derived type DIE for a struct field. - void ConstructFieldTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DIDerivedType *DTy) { - unsigned Tag = DTy->getTag(); - DIE *MemberDie = new DIE(Tag); - if (!DTy->getName().empty()) - AddString(MemberDie, DW_AT_name, DW_FORM_string, DTy->getName()); - // FIXME - Enable this. AddSourceLine(MemberDie, DTy); + AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom()); - DIType FromTy = DTy->getTypeDerivedFrom(); - AddType(DW_Unit, MemberDie, FromTy); + AddSourceLine(MemberDie, &DT); - uint64_t Size = DTy->getSizeInBits(); - uint64_t Offset = DTy->getOffsetInBits(); + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); - // FIXME Handle bitfields + if (Size != FieldSize) { + // Handle bitfield. + AddUInt(MemberDie, DW_AT_byte_size, 0, DT.getOriginalTypeSize() >> 3); + AddUInt(MemberDie, DW_AT_bit_size, 0, DT.getSizeInBits()); - // Add size. - AddUInt(MemberDie, DW_AT_bit_size, 0, Size); - // Add computation for offset. + uint64_t Offset = DT.getOffsetInBits(); + uint64_t FieldOffset = Offset; + uint64_t AlignMask = ~(DT.getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + // Maybe we need to work from the other end. + if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); + AddUInt(MemberDie, DW_AT_bit_offset, 0, Offset); + } DIEBlock *Block = new DIEBlock(); AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst); - AddUInt(Block, 0, DW_FORM_udata, Offset >> 3); + AddUInt(Block, 0, DW_FORM_udata, DT.getOffsetInBits() >> 3); AddBlock(MemberDie, DW_AT_data_member_location, 0, Block); - // FIXME Handle DW_AT_accessibility. + if (DT.isProtected()) + AddUInt(MemberDie, DW_AT_accessibility, 0, DW_ACCESS_protected); + else if (DT.isPrivate()) + AddUInt(MemberDie, DW_AT_accessibility, 0, DW_ACCESS_private); - Buffer.AddChild(MemberDie); + return MemberDie; } - /// 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 Buffer(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_byte_size, 0, sizeof(int32_t)); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, DW_ATE_signed); - DIE *IndexTy = Unit->AddDie(Buffer); - - // 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->getAlign(); - 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); - } + /// CreateSubprogramDIE - Create new DIE using SP. + DIE *CreateSubprogramDIE(CompileUnit *DW_Unit, + const DISubprogram &SP, + bool IsConstructor = false) { + DIE *SPDie = new DIE(DW_TAG_subprogram); + std::string Name; + SP.getName(Name); + AddString(SPDie, DW_AT_name, DW_FORM_string, Name); + std::string LinkageName; + SP.getLinkageName(LinkageName); + if (!LinkageName.empty()) + AddString(SPDie, DW_AT_MIPS_linkage_name, DW_FORM_string, + LinkageName); + AddSourceLine(SPDie, &SP); - 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); + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + + // Add Return Type. + if (!IsConstructor) { + if (Args.isNull()) + AddType(DW_Unit, SPDie, SPTy); + else + AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getGV())); + } - // Add arguments. - for (unsigned i = 1, N = Elements.size(); i < N; ++i) { + if (!SP.isDefinition()) { + AddUInt(SPDie, DW_AT_declaration, DW_FORM_flag, 1); + // Add arguments. + // Do not add arguments for subprogram definition. They will be + // handled through RecordVariable. + if (!Args.isNull()) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(DW_TAG_formal_parameter); - AddType(Arg, cast(Elements[i]), Unit); - Buffer.AddChild(Arg); + AddType(DW_Unit, Arg, DIType(Args.getElement(i).getGV())); + AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); // ??? + SPDie->AddChild(Arg); } - - break; - } - default: break; - } - } - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - AddUInt(&Buffer, DW_AT_byte_size, 0, Size); - else if (isa(TyDesc)) { - // If TyDesc is a composite type, then add size even if it's zero unless - // it's a forward declaration. - if (TyDesc->isForwardDecl()) - AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1); - else - AddUInt(&Buffer, DW_AT_byte_size, 0, 0); } - // Add source line info if available and TyDesc is not a forward - // declaration. - if (!TyDesc->isForwardDecl()) - 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()); - if (!UnitDesc->getDirectory().empty()) - 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; - } + unsigned Lang = SP.getCompileUnit().getLanguage(); + if (Lang == DW_LANG_C99 || Lang == DW_LANG_C89 + || Lang == DW_LANG_ObjC) + AddUInt(SPDie, DW_AT_prototyped, DW_FORM_flag, 1); - /// GetBaseCompileUnit - Get the main compile unit. - /// - CompileUnit *GetBaseCompileUnit() const { - CompileUnit *Unit = CompileUnits[0]; - assert(Unit && "Missing compile unit."); - return Unit; + if (!SP.isLocalToUnit()) + AddUInt(SPDie, DW_AT_external, DW_FORM_flag, 1); + return SPDie; } - /// FindCompileUnit - Get the compile unit for the given descriptor. + /// FindCompileUnit - Get the compile unit for the given descriptor. /// - CompileUnit *FindCompileUnit(CompileUnitDesc *UnitDesc) { - CompileUnit *Unit = DescToUnitMap[UnitDesc]; - assert(Unit && "Missing compile unit."); - return Unit; - } - - /// FindCompileUnit - Get the compile unit for the given descriptor. - /// CompileUnit *FindCompileUnit(DICompileUnit Unit) { - CompileUnit *DW_Unit = DW_CUs[Unit.getGV()]; + CompileUnit *DW_Unit = CompileUnitMap[Unit.getGV()]; assert(DW_Unit && "Missing compile unit."); return DW_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; - } - - /// NewScopeVariable - Create a new scope variable. + /// NewDbgScopeVariable - Create a new scope variable. /// DIE *NewDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { // Get the descriptor. - DIVariable *VD = DV->getVariable(); + const DIVariable &VD = DV->getVariable(); // Translate tag to proper Dwarf tag. The result variable is dropped for // now. unsigned Tag; - switch (VD->getTag()) { + 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 @@ -2521,190 +1956,75 @@ private: // Define variable debug information entry. DIE *VariableDie = new DIE(Tag); - AddString(VariableDie, DW_AT_name, DW_FORM_string, VD->getName()); + std::string Name; + VD.getName(Name); + AddString(VariableDie, DW_AT_name, DW_FORM_string, Name); // Add source line info if available. - AddSourceLine(VariableDie, VD); - - // Add variable type. - AddType(Unit, VariableDie, VD->getType()); - - // Add variable address. - MachineLocation Location; - Location.set(RI->getFrameRegister(*MF), - RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); - AddAddress(VariableDie, DW_AT_location, Location); - - return VariableDie; - } - - /// getOrCreateScope - Returns the scope associated with the given descriptor. - /// - DbgScope *getOrCreateScope(GlobalVariable *V) { - DbgScope *&Slot = DbgScopeMap[V]; - if (!Slot) { - // FIXME - breaks down when the context is an inlined function. - DIDescriptor ParentDesc; - DIDescriptor *DB = new DIDescriptor(V); - if (DIBlock *Block = dyn_cast(DB)) { - ParentDesc = Block->getContext(); - } - DbgScope *Parent = ParentDesc.isNull() ? - NULL : getOrCreateScope(ParentDesc.getGV()); - Slot = new DbgScope(Parent, DB); - if (Parent) { - Parent->AddScope(Slot); - } else if (RootDbgScope) { - // FIXME - Add inlined function scopes to the root so we can delete - // them later. Long term, handle inlined functions properly. - RootDbgScope->AddScope(Slot); - } else { - // First function is top level function. - RootDbgScope = Slot; - } - } - return Slot; - } - - /// ConstructDbgScope - Construct the components of a scope. - /// - void ConstructDbgScope(DbgScope *ParentScope, - unsigned ParentStartID, unsigned ParentEndID, - DIE *ParentDie, CompileUnit *Unit) { - // Add variables to scope. - SmallVector &Variables = ParentScope->getVariables(); - for (unsigned i = 0, N = Variables.size(); i < N; ++i) { - DIE *VariableDie = NewDbgScopeVariable(Variables[i], Unit); - if (VariableDie) ParentDie->AddChild(VariableDie); - } - - // Add nested scopes. - SmallVector &Scopes = ParentScope->getScopes(); - for (unsigned j = 0, M = Scopes.size(); j < M; ++j) { - // Define the Scope debug information entry. - DbgScope *Scope = Scopes[j]; - // FIXME - Ignore inlined functions for the time being. - if (!Scope->getParent()) continue; + AddSourceLine(VariableDie, &VD); - 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. - ConstructDbgScope(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) { - AddLabel(ScopeDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("label", EndID)); - } else { - AddLabel(ScopeDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); - } - - // Add the scope contents. - ConstructDbgScope(Scope, StartID, EndID, ScopeDie, Unit); - ParentDie->AddChild(ScopeDie); - } - } - } - - /// ConstructRootDbgScope - Construct the scope for the subprogram. - /// - void ConstructRootDbgScope(DbgScope *RootScope) { - // Exit if there is no root scope. - if (!RootScope) return; - if (!RootScope->getDesc()->isNull()) return; - - // Get the subprogram debug information entry. - DISubprogram SPD(RootScope->getDesc()->getGV()); - - // Get the compile unit context. - CompileUnit *Unit = FindCompileUnit(SPD.getCompileUnit()); - - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); - assert(SPDie && "Missing subprogram descriptor"); - - // Add the function bounds. - AddLabel(SPDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - AddLabel(SPDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); - MachineLocation Location(RI->getFrameRegister(*MF)); - AddAddress(SPDie, DW_AT_frame_base, Location); + // Add variable type. + AddType(Unit, VariableDie, VD.getType()); - ConstructDbgScope(RootScope, 0, 0, SPDie, Unit); + // Add variable address. + MachineLocation Location; + Location.set(RI->getFrameRegister(*MF), + RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); + AddAddress(VariableDie, DW_AT_location, Location); + + return VariableDie; } - /// ConstructDefaultDbgScope - Construct a default scope for the subprogram. + /// getOrCreateScope - Returns the scope associated with the given descriptor. /// - void ConstructDefaultDbgScope(MachineFunction *MF) { - // Find the correct subprogram descriptor. - std::string SPName = "llvm.dbg.subprograms"; - std::vector Result; - getGlobalVariablesUsing(*M, SPName, Result); - for (std::vector::iterator I = Result.begin(), - E = Result.end(); I != E; ++I) { - - DISubprogram *SPD = new DISubprogram(*I); + DbgScope *getOrCreateScope(GlobalVariable *V) { + DbgScope *&Slot = DbgScopeMap[V]; + if (Slot) return Slot; - if (SPD->getName() == MF->getFunction()->getName()) { - // Get the compile unit context. - CompileUnit *Unit = FindCompileUnit(SPD->getCompileUnit()); + // FIXME - breaks down when the context is an inlined function. + DIDescriptor ParentDesc; + DIDescriptor Desc(V); - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD->getGV()); - assert(SPDie && "Missing subprogram descriptor"); + if (Desc.getTag() == dwarf::DW_TAG_lexical_block) { + DIBlock Block(V); + ParentDesc = Block.getContext(); + } - // Add the function bounds. - AddLabel(SPDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - AddLabel(SPDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); + DbgScope *Parent = ParentDesc.isNull() ? + NULL : getOrCreateScope(ParentDesc.getGV()); + Slot = new DbgScope(Parent, Desc); - MachineLocation Location(RI->getFrameRegister(*MF)); - AddAddress(SPDie, DW_AT_frame_base, Location); - return; - } + if (Parent) { + Parent->AddScope(Slot); + } else if (RootDbgScope) { + // FIXME - Add inlined function scopes to the root so we can delete them + // later. Long term, handle inlined functions properly. + RootDbgScope->AddScope(Slot); + } else { + // First function is top level function. + RootDbgScope = Slot; } -#if 0 - // FIXME: This is causing an abort because C++ mangled names are compared - // with their unmangled counterparts. See PR2885. Don't do this assert. - assert(0 && "Couldn't find DIE for machine function!"); -#endif + + return Slot; } - /// ConstructScope - Construct the components of a scope. + /// ConstructDbgScope - Construct the components of a scope. /// - void ConstructScope(DebugScope *ParentScope, - unsigned ParentStartID, unsigned ParentEndID, - DIE *ParentDie, CompileUnit *Unit) { + void ConstructDbgScope(DbgScope *ParentScope, + unsigned ParentStartID, unsigned ParentEndID, + DIE *ParentDie, CompileUnit *Unit) { // Add variables to scope. - std::vector &Variables = ParentScope->getVariables(); + SmallVector &Variables = ParentScope->getVariables(); for (unsigned i = 0, N = Variables.size(); i < N; ++i) { - DIE *VariableDie = NewScopeVariable(Variables[i], Unit); + DIE *VariableDie = NewDbgScopeVariable(Variables[i], Unit); if (VariableDie) ParentDie->AddChild(VariableDie); } // Add nested scopes. - std::vector &Scopes = ParentScope->getScopes(); + SmallVector &Scopes = ParentScope->getScopes(); for (unsigned j = 0, M = Scopes.size(); j < M; ++j) { // Define the Scope debug information entry. - DebugScope *Scope = Scopes[j]; + DbgScope *Scope = Scopes[j]; // FIXME - Ignore inlined functions for the time being. if (!Scope->getParent()) continue; @@ -2717,7 +2037,7 @@ private: if (StartID == ParentStartID && EndID == ParentEndID) { // Just add stuff to the parent scope. - ConstructScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit); + ConstructDbgScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit); } else { DIE *ScopeDie = new DIE(DW_TAG_lexical_block); @@ -2738,26 +2058,31 @@ private: } // Add the scope contents. - ConstructScope(Scope, StartID, EndID, ScopeDie, Unit); + ConstructDbgScope(Scope, StartID, EndID, ScopeDie, Unit); ParentDie->AddChild(ScopeDie); } } } - /// ConstructRootScope - Construct the scope for the subprogram. + /// ConstructRootDbgScope - Construct the scope for the subprogram. /// - void ConstructRootScope(DebugScope *RootScope) { + void ConstructRootDbgScope(DbgScope *RootScope) { // Exit if there is no root scope. if (!RootScope) return; + DIDescriptor Desc = RootScope->getDesc(); + if (Desc.isNull()) + return; // Get the subprogram debug information entry. - SubprogramDesc *SPD = cast(RootScope->getDesc()); + DISubprogram SPD(Desc.getGV()); // Get the compile unit context. - CompileUnit *Unit = GetBaseCompileUnit(); + CompileUnit *Unit = MainCU; + if (!Unit) + Unit = FindCompileUnit(SPD.getCompileUnit()); // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD); + DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); assert(SPDie && "Missing subprogram descriptor"); // Add the function bounds. @@ -2768,26 +2093,18 @@ private: MachineLocation Location(RI->getFrameRegister(*MF)); AddAddress(SPDie, DW_AT_frame_base, Location); - ConstructScope(RootScope, 0, 0, SPDie, Unit); + ConstructDbgScope(RootScope, 0, 0, SPDie, Unit); } - /// ConstructDefaultScope - Construct a default scope for the subprogram. + /// ConstructDefaultDbgScope - Construct a default scope for the subprogram. /// - void ConstructDefaultScope(MachineFunction *MF) { - // Find the correct subprogram descriptor. - std::vector Subprograms; - MMI->getAnchoredDescriptors(*M, Subprograms); - - for (unsigned i = 0, N = Subprograms.size(); i < N; ++i) { - SubprogramDesc *SPD = Subprograms[i]; - - if (SPD->getName() == MF->getFunction()->getName()) { - // Get the compile unit context. - CompileUnit *Unit = GetBaseCompileUnit(); - - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD); - assert(SPDie && "Missing subprogram descriptor"); + void ConstructDefaultDbgScope(MachineFunction *MF) { + const char *FnName = MF->getFunction()->getNameStart(); + if (MainCU) { + std::map &Globals = MainCU->getGlobals(); + std::map::iterator GI = Globals.find(FnName); + if (GI != Globals.end()) { + DIE *SPDie = GI->second; // Add the function bounds. AddLabel(SPDie, DW_AT_low_pc, DW_FORM_addr, @@ -2799,12 +2116,33 @@ private: AddAddress(SPDie, DW_AT_frame_base, Location); return; } + } else { + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) { + CompileUnit *Unit = CompileUnits[i]; + std::map &Globals = Unit->getGlobals(); + std::map::iterator GI = Globals.find(FnName); + if (GI != Globals.end()) { + DIE *SPDie = GI->second; + + // Add the function bounds. + AddLabel(SPDie, DW_AT_low_pc, DW_FORM_addr, + DWLabel("func_begin", SubprogramCount)); + AddLabel(SPDie, DW_AT_high_pc, DW_FORM_addr, + DWLabel("func_end", SubprogramCount)); + + MachineLocation Location(RI->getFrameRegister(*MF)); + AddAddress(SPDie, DW_AT_frame_base, Location); + return; + } + } } + #if 0 // FIXME: This is causing an abort because C++ mangled names are compared // with their unmangled counterparts. See PR2885. Don't do this assert. assert(0 && "Couldn't find DIE for machine function!"); #endif + return; } /// EmitInitial - Emit initial Dwarf declarations. This is necessary for cc @@ -2825,8 +2163,10 @@ private: EmitLabel("section_abbrev", 0); Asm->SwitchToDataSection(TAI->getDwarfARangesSection()); EmitLabel("section_aranges", 0); - Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection()); - EmitLabel("section_macinfo", 0); + if (TAI->doesSupportMacInfoSection()) { + Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection()); + EmitLabel("section_macinfo", 0); + } Asm->SwitchToDataSection(TAI->getDwarfLineSection()); EmitLabel("section_line", 0); Asm->SwitchToDataSection(TAI->getDwarfLocSection()); @@ -2953,9 +2293,17 @@ private: /// void SizeAndOffsets() { // Process base compile unit. - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; + if (MainCU) { + // Compute size of compile unit header + unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + SizeAndOffsetDie(MainCU->getDie(), Offset, true); + return; + } + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) { + CompileUnit *Unit = CompileUnits[i]; // Compute size of compile unit header unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info sizeof(int16_t) + // DWARF version number @@ -2965,41 +2313,47 @@ private: } } - /// EmitDebugInfo - Emit the debug info section. + /// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section. /// + void EmitDebugInfoPerCU(CompileUnit *Unit) { + DIE *Die = Unit->getDie(); + // Emit the compile units header. + EmitLabel("info_begin", Unit->getID()); + // Emit size of content not including length itself + unsigned ContentSize = Die->getSize() + + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int32_t); // FIXME - extra pad for gdb bug. + + Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info"); + Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF version number"); + EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); + Asm->EOL("Offset Into Abbrev. Section"); + Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + + EmitDIE(Die); + // FIXME - extra padding for gdb bug. + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + EmitLabel("info_end", Unit->getID()); + + Asm->EOL(); + } + void EmitDebugInfo() { // Start debug info section. Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; - DIE *Die = Unit->getDie(); - // Emit the compile units header. - EmitLabel("info_begin", Unit->getID()); - // Emit size of content not including length itself - unsigned ContentSize = Die->getSize() + - sizeof(int16_t) + // DWARF version number - sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t) + // Pointer Size (in bytes) - sizeof(int32_t); // FIXME - extra pad for gdb bug. - - Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info"); - Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF version number"); - EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); - Asm->EOL("Offset Into Abbrev. Section"); - Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); - - EmitDIE(Die); - // FIXME - extra padding for gdb bug. - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - EmitLabel("info_end", Unit->getID()); - - Asm->EOL(); + if (MainCU) { + EmitDebugInfoPerCU(MainCU); + return; } + + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) + EmitDebugInfoPerCU(CompileUnits[i]); } /// EmitAbbreviations - Emit the abbreviation section. @@ -3102,19 +2456,19 @@ private: Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count"); // Emit directories. - for (unsigned DirectoryID = 1, NDID = Directories.size(); - DirectoryID <= NDID; ++DirectoryID) { - Asm->EmitString(Directories[DirectoryID]); Asm->EOL("Directory"); + for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { + Asm->EmitString(getSourceDirectoryName(DI)); + Asm->EOL("Directory"); } Asm->EmitInt8(0); Asm->EOL("End of directories"); // Emit files. - for (unsigned SourceID = 1, NSID = SrcFiles.size(); - SourceID <= NSID; ++SourceID) { - const SrcFileInfo &SourceFile = SrcFiles[SourceID]; - Asm->EmitString(SourceFile.getName()); + for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) { + // Remember source id starts at 1. + std::pair Id = getSourceDirectoryAndFileIds(SI); + Asm->EmitString(getSourceFileName(Id.second)); Asm->EOL("Source"); - Asm->EmitULEB128Bytes(SourceFile.getDirectoryID()); + Asm->EmitULEB128Bytes(Id.first); Asm->EOL("Directory #"); Asm->EmitULEB128Bytes(0); Asm->EOL("Mod date"); @@ -3134,7 +2488,8 @@ private: if (VerboseAsm) { const Section* S = SectionMap[j + 1]; - Asm->EOL(std::string("Section ") + S->getName()); + O << '\t' << TAI->getCommentString() << " Section" + << S->getName() << '\n'; } else Asm->EOL(); @@ -3148,16 +2503,16 @@ private: unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID()); if (!LabelID) continue; - unsigned SourceID = LineInfo.getSourceID(); - const SrcFileInfo &SourceFile = SrcFiles[SourceID]; - unsigned DirectoryID = SourceFile.getDirectoryID(); - if (VerboseAsm) - Asm->EOL(Directories[DirectoryID] - + SourceFile.getName() - + ":" - + utostr_32(LineInfo.getLine())); - else + if (!VerboseAsm) Asm->EOL(); + else { + std::pair SourceID = + getSourceDirectoryAndFileIds(LineInfo.getSourceID()); + O << '\t' << TAI->getCommentString() << ' ' + << getSourceDirectoryName(SourceID.first) << ' ' + << getSourceFileName(SourceID.second) + <<" :" << utostr_32(LineInfo.getLine()) << '\n'; + } // Define the line address. Asm->EmitInt8(0); Asm->EOL("Extended Op"); @@ -3280,7 +2635,8 @@ private: "func_begin", DebugFrameInfo.Number); Asm->EOL("FDE address range"); - EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, false); + EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, + false); Asm->EmitAlignment(2, 0, 0, false); EmitLabel("debug_frame_end", DebugFrameInfo.Number); @@ -3288,48 +2644,52 @@ private: Asm->EOL(); } - /// EmitDebugPubNames - Emit visible names into a debug pubnames section. - /// - void EmitDebugPubNames() { - // Start the dwarf pubnames section. - Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); - - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; - - EmitDifference("pubnames_end", Unit->getID(), - "pubnames_begin", Unit->getID(), true); - Asm->EOL("Length of Public Names Info"); - - EmitLabel("pubnames_begin", Unit->getID()); + void EmitDebugPubNamesPerCU(CompileUnit *Unit) { + EmitDifference("pubnames_end", Unit->getID(), + "pubnames_begin", Unit->getID(), true); + Asm->EOL("Length of Public Names Info"); - Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF Version"); + EmitLabel("pubnames_begin", Unit->getID()); - EmitSectionOffset("info_begin", "section_info", - Unit->getID(), 0, true, false); - Asm->EOL("Offset of Compilation Unit Info"); + Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF Version"); - EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),true); - Asm->EOL("Compilation Unit Length"); + EmitSectionOffset("info_begin", "section_info", + Unit->getID(), 0, true, false); + Asm->EOL("Offset of Compilation Unit Info"); - std::map &Globals = Unit->getGlobals(); + EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(), + true); + Asm->EOL("Compilation Unit Length"); - for (std::map::iterator GI = Globals.begin(), - GE = Globals.end(); - GI != GE; ++GI) { - const std::string &Name = GI->first; - DIE * Entity = GI->second; + std::map &Globals = Unit->getGlobals(); + for (std::map::iterator GI = Globals.begin(), + GE = Globals.end(); GI != GE; ++GI) { + const std::string &Name = GI->first; + DIE * Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); - Asm->EmitString(Name); Asm->EOL("External Name"); - } + Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); + Asm->EmitString(Name); Asm->EOL("External Name"); + } - Asm->EmitInt32(0); Asm->EOL("End Mark"); - EmitLabel("pubnames_end", Unit->getID()); + Asm->EmitInt32(0); Asm->EOL("End Mark"); + EmitLabel("pubnames_end", Unit->getID()); - Asm->EOL(); + Asm->EOL(); + } + + /// EmitDebugPubNames - Emit visible names into a debug pubnames section. + /// + void EmitDebugPubNames() { + // Start the dwarf pubnames section. + Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); + + if (MainCU) { + EmitDebugPubNamesPerCU(MainCU); + return; } + + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) + EmitDebugPubNamesPerCU(CompileUnits[i]); } /// EmitDebugStr - Emit visible names into a debug str section. @@ -3411,158 +2771,210 @@ private: /// EmitDebugMacInfo - Emit visible names into a debug macinfo section. /// void EmitDebugMacInfo() { - // Start the dwarf macinfo section. - Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection()); + if (TAI->doesSupportMacInfoSection()) { + // Start the dwarf macinfo section. + Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection()); - Asm->EOL(); + Asm->EOL(); + } } - /// ConstructCompileUnits - Create a compile unit DIEs. - void ConstructCompileUnits() { - std::string CUName = "llvm.dbg.compile_units"; - std::vector Result; - getGlobalVariablesUsing(*M, CUName, Result); - for (std::vector::iterator RI = Result.begin(), - RE = Result.end(); RI != RE; ++RI) { - DICompileUnit *DIUnit = new DICompileUnit(*RI); - unsigned ID = RecordSource(DIUnit->getDirectory(), - DIUnit->getFilename()); - - 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, DIUnit->getProducer()); - AddUInt(Die, DW_AT_language, DW_FORM_data1, DIUnit->getLanguage()); - AddString(Die, DW_AT_name, DW_FORM_string, DIUnit->getFilename()); - if (!DIUnit->getDirectory().empty()) - AddString(Die, DW_AT_comp_dir, DW_FORM_string, DIUnit->getDirectory()); - - CompileUnit *Unit = new CompileUnit(ID, Die); - DW_CUs[DIUnit->getGV()] = Unit; + /// GetOrCreateSourceID - Look up the source id with the given directory and + /// source file names. If none currently exists, create a new id and insert it + /// in the SourceIds map. This can update DirectoryNames and SourceFileNames maps + /// as well. + unsigned GetOrCreateSourceID(const std::string &DirName, + const std::string &FileName) { + unsigned DId; + StringMap::iterator DI = DirectoryIdMap.find(DirName); + if (DI != DirectoryIdMap.end()) { + DId = DI->getValue(); + } else { + DId = DirectoryNames.size() + 1; + DirectoryIdMap[DirName] = DId; + DirectoryNames.push_back(DirName); + } + + unsigned FId; + StringMap::iterator FI = SourceFileIdMap.find(FileName); + if (FI != SourceFileIdMap.end()) { + FId = FI->getValue(); + } else { + FId = SourceFileNames.size() + 1; + SourceFileIdMap[FileName] = FId; + SourceFileNames.push_back(FileName); } + + DenseMap, unsigned>::iterator SI = + SourceIdMap.find(std::make_pair(DId, FId)); + if (SI != SourceIdMap.end()) + return SI->second; + + unsigned SrcId = SourceIds.size() + 1; // DW_AT_decl_file cannot be 0. + SourceIdMap[std::make_pair(DId, FId)] = SrcId; + SourceIds.push_back(std::make_pair(DId, FId)); + + return SrcId; } - /// ConstructCompileUnitDIEs - Create a compile unit DIE for each source and - /// header file. - void ConstructCompileUnitDIEs() { - const UniqueVector CUW = MMI->getCompileUnits(); + void ConstructCompileUnit(GlobalVariable *GV) { + DICompileUnit DIUnit(GV); + std::string Dir, FN, Prod; + unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir), + DIUnit.getFilename(FN)); - for (unsigned i = 1, N = CUW.size(); i <= N; ++i) { - unsigned ID = MMI->RecordSource(CUW[i]); - CompileUnit *Unit = NewCompileUnit(CUW[i], ID); - CompileUnits.push_back(Unit); + 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, DIUnit.getProducer(Prod)); + AddUInt(Die, DW_AT_language, DW_FORM_data1, DIUnit.getLanguage()); + AddString(Die, DW_AT_name, DW_FORM_string, FN); + if (!Dir.empty()) + AddString(Die, DW_AT_comp_dir, DW_FORM_string, Dir); + if (DIUnit.isOptimized()) + AddUInt(Die, DW_AT_APPLE_optimized, DW_FORM_flag, 1); + std::string Flags; + DIUnit.getFlags(Flags); + if (!Flags.empty()) + AddString(Die, DW_AT_APPLE_flags, DW_FORM_string, Flags); + unsigned RVer = DIUnit.getRunTimeVersion(); + if (RVer) + AddUInt(Die, DW_AT_APPLE_major_runtime_vers, DW_FORM_data1, RVer); + + CompileUnit *Unit = new CompileUnit(ID, Die); + if (DIUnit.isMain()) { + assert(!MainCU && "Multiple main compile units are found!"); + MainCU = Unit; } + CompileUnitMap[DIUnit.getGV()] = Unit; + CompileUnits.push_back(Unit); } - /// ConstructGlobalVariableDIEs - Create DIEs for each of the externally - /// visible global variables. - void ConstructGlobalVariableDIEs() { - std::string GVName = "llvm.dbg.global_variables"; - std::vector Result; - getGlobalVariablesUsing(*M, GVName, Result); - for (std::vector::iterator GVI = Result.begin(), - GVE = Result.end(); GVI != GVE; ++GVI) { - DIGlobalVariable *DI_GV = new DIGlobalVariable(*GVI); - CompileUnit *DW_Unit = FindCompileUnit(DI_GV->getCompileUnit()); - - // Check for pre-existence. - DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV->getGV()); - if (Slot) continue; - - DIE *VariableDie = new DIE(DW_TAG_variable); - AddString(VariableDie, DW_AT_name, DW_FORM_string, DI_GV->getName()); - const std::string &LinkageName = DI_GV->getLinkageName(); - if (!LinkageName.empty()) - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - AddType(DW_Unit, VariableDie, DI_GV->getType()); - - if (!DI_GV->isLocalToUnit()) - AddUInt(VariableDie, DW_AT_external, DW_FORM_flag, 1); - - // Add source line info, if available. - AddSourceLine(VariableDie, DI_GV); - - // Add address. - DIEBlock *Block = new DIEBlock(); - AddUInt(Block, 0, DW_FORM_data1, DW_OP_addr); - AddObjectLabel(Block, 0, DW_FORM_udata, - Asm->getGlobalLinkName(DI_GV->getGV())); - AddBlock(VariableDie, DW_AT_location, 0, Block); - - //Add to map. - Slot = VariableDie; - - //Add to context owner. - DW_Unit->getDie()->AddChild(VariableDie); - - //Expose as global. FIXME - need to check external flag. - DW_Unit->AddGlobal(DI_GV->getName(), VariableDie); - } + /// ConstructCompileUnits - Create a compile unit DIEs. + void ConstructCompileUnits() { + GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.compile_units"); + if (!Root) + return; + assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() && + "Malformed compile unit descriptor anchor type"); + Constant *RootC = cast(*Root->use_begin()); + assert(RootC->hasNUsesOrMore(1) && + "Malformed compile unit descriptor anchor type"); + for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); + UI != UE; ++UI) + for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); + UUI != UUE; ++UUI) { + GlobalVariable *GV = cast(*UUI); + ConstructCompileUnit(GV); + } } - /// ConstructGlobalDIEs - Create DIEs for each of the externally visible - /// global variables. - void ConstructGlobalDIEs() { - std::vector GlobalVariables; - MMI->getAnchoredDescriptors(*M, GlobalVariables); + bool ConstructGlobalVariableDIE(GlobalVariable *GV) { + DIGlobalVariable DI_GV(GV); + CompileUnit *DW_Unit = MainCU; + if (!DW_Unit) + DW_Unit = FindCompileUnit(DI_GV.getCompileUnit()); - for (unsigned i = 0, N = GlobalVariables.size(); i < N; ++i) { - GlobalVariableDesc *GVD = GlobalVariables[i]; - NewGlobalVariable(GVD); - } + // Check for pre-existence. + DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV()); + if (Slot) + return false; + + DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV); + + // Add address. + DIEBlock *Block = new DIEBlock(); + AddUInt(Block, 0, DW_FORM_data1, DW_OP_addr); + AddObjectLabel(Block, 0, DW_FORM_udata, + Asm->getGlobalLinkName(DI_GV.getGlobal())); + AddBlock(VariableDie, DW_AT_location, 0, Block); + + // Add to map. + Slot = VariableDie; + // Add to context owner. + DW_Unit->getDie()->AddChild(VariableDie); + // Expose as global. FIXME - need to check external flag. + std::string Name; + DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie); + return true; } - /// ConstructSubprograms - Create DIEs for each of the externally visible - /// subprograms. - void ConstructSubprograms() { - - std::string SPName = "llvm.dbg.subprograms"; - std::vector Result; - getGlobalVariablesUsing(*M, SPName, Result); - for (std::vector::iterator RI = Result.begin(), - RE = Result.end(); RI != RE; ++RI) { - - DISubprogram *SP = new DISubprogram(*RI); - CompileUnit *Unit = FindCompileUnit(SP->getCompileUnit()); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(SP->getGV()); - if (Slot) continue; - - DIE *SubprogramDie = new DIE(DW_TAG_subprogram); - AddString(SubprogramDie, DW_AT_name, DW_FORM_string, SP->getName()); - const std::string &LinkageName = SP->getLinkageName(); - if (!LinkageName.empty()) - AddString(SubprogramDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - DIType SPTy = SP->getType(); - AddType(Unit, SubprogramDie, SPTy); - if (!SP->isLocalToUnit()) - AddUInt(SubprogramDie, DW_AT_external, DW_FORM_flag, 1); - AddUInt(SubprogramDie, DW_AT_prototyped, DW_FORM_flag, 1); - - AddSourceLine(SubprogramDie, SP); - //Add to map. - Slot = SubprogramDie; - //Add to context owner. - Unit->getDie()->AddChild(SubprogramDie); - //Expose as global. - Unit->AddGlobal(SP->getName(), SubprogramDie); - } + /// ConstructGlobalVariableDIEs - Create DIEs for each of the externally + /// visible global variables. Return true if at least one global DIE is + /// created. + bool ConstructGlobalVariableDIEs() { + GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables"); + if (!Root) + return false; + + assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() && + "Malformed global variable descriptor anchor type"); + Constant *RootC = cast(*Root->use_begin()); + assert(RootC->hasNUsesOrMore(1) && + "Malformed global variable descriptor anchor type"); + + bool Result = false; + for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); + UI != UE; ++UI) + for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); + UUI != UUE; ++UUI) { + GlobalVariable *GV = cast(*UUI); + Result |= ConstructGlobalVariableDIE(GV); + } + return Result; } - /// ConstructSubprogramDIEs - Create DIEs for each of the externally visible - /// subprograms. - void ConstructSubprogramDIEs() { - std::vector Subprograms; - MMI->getAnchoredDescriptors(*M, Subprograms); + bool ConstructSubprogram(GlobalVariable *GV) { + DISubprogram SP(GV); + CompileUnit *Unit = MainCU; + if (!Unit) + Unit = FindCompileUnit(SP.getCompileUnit()); - for (unsigned i = 0, N = Subprograms.size(); i < N; ++i) { - SubprogramDesc *SPD = Subprograms[i]; - NewSubprogram(SPD); - } + // Check for pre-existence. + DIE *&Slot = Unit->getDieMapSlotFor(GV); + if (Slot) + return false; + + if (!SP.isDefinition()) + // This is a method declaration which will be handled while + // constructing class type. + return false; + + DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP); + + // Add to map. + Slot = SubprogramDie; + // Add to context owner. + Unit->getDie()->AddChild(SubprogramDie); + // Expose as global. + std::string Name; + Unit->AddGlobal(SP.getName(Name), SubprogramDie); + return true; + } + + /// ConstructSubprograms - Create DIEs for each of the externally visible + /// subprograms. Return true if at least one subprogram DIE is created. + bool ConstructSubprograms() { + GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms"); + if (!Root) + return false; + + assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() && + "Malformed subprogram descriptor anchor type"); + Constant *RootC = cast(*Root->use_begin()); + assert(RootC->hasNUsesOrMore(1) && + "Malformed subprogram descriptor anchor type"); + + bool Result = false; + for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); + UI != UE; ++UI) + for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); + UUI != UUE; ++UUI) { + GlobalVariable *GV = cast(*UUI); + Result |= ConstructSubprogram(GV); + } + return Result; } public: @@ -3570,107 +2982,85 @@ public: // Main entry points. // DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) - : Dwarf(OS, A, T, "dbg") - , CompileUnits() - , AbbreviationsSet(InitAbbreviationsSetSize) - , Abbreviations() - , ValuesSet(InitValuesSetSize) - , Values() - , StringPool() - , DescToUnitMap() - , SectionMap() - , SectionSourceLines() - , didInitial(false) - , shouldEmit(false) - , RootDbgScope(NULL) - { + : Dwarf(OS, A, T, "dbg"), MainCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), + ValuesSet(InitValuesSetSize), Values(), StringPool(), SectionMap(), + SectionSourceLines(), didInitial(false), shouldEmit(false), + RootDbgScope(0), DebugTimer(0) { + if (TimePassesIsEnabled) + DebugTimer = new Timer("Dwarf Debug Writer", + getDwarfTimerGroup()); } virtual ~DwarfDebug() { - for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) - delete CompileUnits[i]; for (unsigned j = 0, M = Values.size(); j < M; ++j) delete Values[j]; + + delete DebugTimer; } + /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should + /// be emitted. + bool ShouldEmitDwarfDebug() const { return shouldEmit; } + /// SetDebugInfo - Create global DIEs and emit initial debug info sections. /// This is inovked by the target AsmPrinter. void SetDebugInfo(MachineModuleInfo *mmi) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); - // Create all the compile unit DIEs. - ConstructCompileUnits(); + // Create all the compile unit DIEs. + ConstructCompileUnits(); - if (DW_CUs.empty()) - return; + if (CompileUnits.empty()) { + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); - MMI = mmi; - shouldEmit = true; - MMI->setDebugInfoAvailability(true); - - // Create DIEs for each of the externally visible global variables. - ConstructGlobalVariableDIEs(); + return; + } - // Create DIEs for each of the externally visible subprograms. - ConstructSubprograms(); + // Create DIEs for each of the externally visible global variables. + bool globalDIEs = ConstructGlobalVariableDIEs(); - // Prime section data. - SectionMap.insert(TAI->getTextSection()); + // Create DIEs for each of the externally visible subprograms. + bool subprogramDIEs = ConstructSubprograms(); - // Print out .file directives to specify files for .loc directives. These - // are printed out early so that they precede any .loc directives. - if (TAI->hasDotLocAndDotFile()) { - for (unsigned i = 1, e = SrcFiles.size(); i <= e; ++i) { - sys::Path FullPath(Directories[SrcFiles[i].getDirectoryID()]); - bool AppendOk = FullPath.appendComponent(SrcFiles[i].getName()); - assert(AppendOk && "Could not append filename to directory!"); - AppendOk = false; - Asm->EmitFile(i, FullPath.toString()); - Asm->EOL(); - } - } + // If there is not any debug info available for any global variables + // and any subprograms then there is not any debug info to emit. + if (!globalDIEs && !subprogramDIEs) { + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); - // Emit initial sections - EmitInitial(); - } + return; + } - /// SetModuleInfo - Set machine module information when it's known that pass - /// manager has created it. Set by the target AsmPrinter. - void SetModuleInfo(MachineModuleInfo *mmi) { - assert (0 && "Who is this?"); - // Make sure initial declarations are made. - if (!MMI && mmi->hasDebugInfo()) { - MMI = mmi; - shouldEmit = true; - - // Create all the compile unit DIEs. - ConstructCompileUnitDIEs(); - - // Create DIEs for each of the externally visible global variables. - ConstructGlobalDIEs(); - - // Create DIEs for each of the externally visible subprograms. - ConstructSubprogramDIEs(); - - // Prime section data. - SectionMap.insert(TAI->getTextSection()); - - // Print out .file directives to specify files for .loc directives. These - // are printed out early so that they precede any .loc directives. - if (TAI->hasDotLocAndDotFile()) { - const UniqueVector &SourceFiles = MMI->getSourceFiles(); - const UniqueVector &Directories = MMI->getDirectories(); - for (unsigned i = 1, e = SourceFiles.size(); i <= e; ++i) { - sys::Path FullPath(Directories[SourceFiles[i].getDirectoryID()]); - bool AppendOk = FullPath.appendComponent(SourceFiles[i].getName()); - assert(AppendOk && "Could not append filename to directory!"); - AppendOk = false; - Asm->EmitFile(i, FullPath.toString()); - Asm->EOL(); - } + MMI = mmi; + shouldEmit = true; + MMI->setDebugInfoAvailability(true); + + // Prime section data. + SectionMap.insert(TAI->getTextSection()); + + // Print out .file directives to specify files for .loc directives. These + // are printed out early so that they precede any .loc directives. + if (TAI->hasDotLocAndDotFile()) { + for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { + // Remember source id starts at 1. + std::pair Id = getSourceDirectoryAndFileIds(i); + sys::Path FullPath(getSourceDirectoryName(Id.first)); + bool AppendOk = + FullPath.appendComponent(getSourceFileName(Id.second)); + assert(AppendOk && "Could not append filename to directory!"); + AppendOk = false; + Asm->EmitFile(i, FullPath.toString()); + Asm->EOL(); } - - // Emit initial sections - EmitInitial(); } + + // Emit initial sections + EmitInitial(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// BeginModule - Emit all Dwarf sections that should come prior to the @@ -3682,7 +3072,11 @@ public: /// EndModule - Emit all Dwarf sections that should come after the content. /// void EndModule() { - if (!ShouldEmitDwarf()) return; + if (!ShouldEmitDwarfDebug()) + return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); // Standard sections final addresses. Asm->SwitchToSection(TAI->getTextSection()); @@ -3733,6 +3127,9 @@ public: // Emit info into a debug macinfo section. EmitDebugMacInfo(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// BeginFunction - Gather pre-function debug information. Assumes being @@ -3740,7 +3137,10 @@ public: void BeginFunction(MachineFunction *MF) { this->MF = MF; - if (!ShouldEmitDwarf()) return; + if (!ShouldEmitDwarfDebug()) return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); // Begin accumulating function debug information. MMI->BeginFunction(MF); @@ -3754,12 +3154,18 @@ public: const SrcLineInfo &LineInfo = Lines[0]; Asm->printLabel(LineInfo.getLabelID()); } + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// EndFunction - Gather and emit post-function debug information. /// void EndFunction(MachineFunction *MF) { - if (!ShouldEmitDwarf()) return; + if (!ShouldEmitDwarfDebug()) return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); // Define end label for subprogram. EmitLabel("func_end", SubprogramCount); @@ -3798,19 +3204,78 @@ public: DbgScopeMap.clear(); RootDbgScope = NULL; } + Lines.clear(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } -public: + /// ValidDebugInfo - Return true if V represents valid debug info value. + bool ValidDebugInfo(Value *V) { + if (!V) + return false; + + if (!shouldEmit) + return false; + + GlobalVariable *GV = getGlobalVariable(V); + if (!GV) + return false; + + if (!GV->hasInternalLinkage () && !GV->hasLinkOnceLinkage()) + return false; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + DIDescriptor DI(GV); + + // Check current version. Allow Version6 for now. + unsigned Version = DI.getVersion(); + if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) { + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return false; + } + + unsigned Tag = DI.getTag(); + switch (Tag) { + case DW_TAG_variable: + assert(DIVariable(GV).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_compile_unit: + assert(DICompileUnit(GV).Verify() && "Invalid DebugInfo value"); + break; + case DW_TAG_subprogram: + assert(DISubprogram(GV).Verify() && "Invalid DebugInfo value"); + break; + default: + break; + } + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return true; + } /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. unsigned RecordSourceLine(Value *V, unsigned Line, unsigned Col) { - CompileUnit *Unit = DW_CUs[V]; - assert (Unit && "Unable to find CompileUnit"); + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + CompileUnit *Unit = CompileUnitMap[V]; + assert(Unit && "Unable to find CompileUnit"); unsigned ID = MMI->NextLabelID(); Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID)); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } @@ -3818,48 +3283,96 @@ public: /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. unsigned RecordSourceLine(unsigned Line, unsigned Col, unsigned Src) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + unsigned ID = MMI->NextLabelID(); Lines.push_back(SrcLineInfo(Line, Col, Src, ID)); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } - unsigned getRecordSourceLineCount() { + /// getRecordSourceLineCount - Return the number of source lines in the debug + /// info. + unsigned getRecordSourceLineCount() const { return Lines.size(); } - /// RecordSource - Register a source file with debug info. Returns an source - /// ID. - unsigned RecordSource(const std::string &Directory, - const std::string &File) { - unsigned DID = Directories.insert(Directory); - return SrcFiles.insert(SrcFileInfo(DID,File)); + /// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be + /// timed. Look up the source id with the given directory and source file + /// names. If none currently exists, create a new id and insert it in the + /// SourceIds map. This can update DirectoryNames and SourceFileNames maps as + /// well. + unsigned getOrCreateSourceID(const std::string &DirName, + const std::string &FileName) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + unsigned SrcId = GetOrCreateSourceID(DirName, FileName); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return SrcId; } /// RecordRegionStart - Indicate the start of a region. - /// unsigned RecordRegionStart(GlobalVariable *V) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + DbgScope *Scope = getOrCreateScope(V); unsigned ID = MMI->NextLabelID(); if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } /// RecordRegionEnd - Indicate the end of a region. - /// unsigned RecordRegionEnd(GlobalVariable *V) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + DbgScope *Scope = getOrCreateScope(V); unsigned ID = MMI->NextLabelID(); Scope->setEndLabelID(ID); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } /// RecordVariable - Indicate the declaration of a local variable. - /// void RecordVariable(GlobalVariable *GV, unsigned FrameIndex) { - DbgScope *Scope = getOrCreateScope(GV); - DIVariable *VD = new DIVariable(GV); - DbgVariable *DV = new DbgVariable(VD, FrameIndex); + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + DIDescriptor Desc(GV); + DbgScope *Scope = NULL; + + if (Desc.getTag() == DW_TAG_variable) { + // GV is a global variable. + DIGlobalVariable DG(GV); + Scope = getOrCreateScope(DG.getContext().getGV()); + } else { + // or GV is a local variable. + DIVariable DV(GV); + Scope = getOrCreateScope(DV.getContext().getGV()); + } + + assert(Scope && "Unable to find variable' scope"); + DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex); Scope->AddVariable(DV); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } }; @@ -3867,8 +3380,6 @@ public: /// DwarfException - Emits Dwarf exception handling directives. /// class DwarfException : public Dwarf { - -private: struct FunctionEHFrameInfo { std::string FnName; unsigned Number; @@ -3904,6 +3415,9 @@ private: /// should be emitted. bool shouldEmitMovesModule; + /// ExceptionTimer - Timer for the Dwarf exception writer. + Timer *ExceptionTimer; + /// EmitCommonEHFrame - Emit the common eh unwind frame. /// void EmitCommonEHFrame(const Function *Personality, unsigned Index) { @@ -4008,14 +3522,17 @@ private: // Externally visible entry into the functions eh frame info. // If the corresponding function is static, this should not be // externally visible. - if (linkage != Function::InternalLinkage) { + if (linkage != Function::InternalLinkage && + linkage != Function::PrivateLinkage) { if (const char *GlobalEHDirective = TAI->getGlobalEHDirective()) O << GlobalEHDirective << EHFrameInfo.FnName << "\n"; } // If corresponding function is weak definition, this should be too. - if ((linkage == Function::WeakLinkage || - linkage == Function::LinkOnceLinkage) && + if ((linkage == Function::WeakAnyLinkage || + linkage == Function::WeakODRLinkage || + linkage == Function::LinkOnceAnyLinkage || + linkage == Function::LinkOnceODRLinkage) && TAI->getWeakDefDirective()) O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; @@ -4026,8 +3543,10 @@ private: // unwind info is to be available for non-EH uses. if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && - ((linkage != Function::WeakLinkage && - linkage != Function::LinkOnceLinkage) || + ((linkage != Function::WeakAnyLinkage && + linkage != Function::WeakODRLinkage && + linkage != Function::LinkOnceAnyLinkage && + linkage != Function::LinkOnceODRLinkage) || !TAI->getWeakDefDirective() || TAI->getSupportsWeakOmittedEHFrame())) { @@ -4085,7 +3604,8 @@ private: // Indicate locations of function specific callee saved registers in // frame. - EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, true); + EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, + true); // On Darwin the linker honors the alignment of eh_frame, which means it // must be 8-byte on 64-bit targets to match what gcc does. Otherwise @@ -4510,14 +4030,17 @@ public: // Main entry points. // DwarfException(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) - : Dwarf(OS, A, T, "eh") - , shouldEmitTable(false) - , shouldEmitMoves(false) - , shouldEmitTableModule(false) - , shouldEmitMovesModule(false) - {} + : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), + shouldEmitTableModule(false), shouldEmitMovesModule(false), + ExceptionTimer(0) { + if (TimePassesIsEnabled) + ExceptionTimer = new Timer("Dwarf Exception Writer", + getDwarfTimerGroup()); + } - virtual ~DwarfException() {} + virtual ~DwarfException() { + delete ExceptionTimer; + } /// SetModuleInfo - Set machine module information when it's known that pass /// manager has created it. Set by the target AsmPrinter. @@ -4534,26 +4057,36 @@ public: /// EndModule - Emit all exception information that should come after the /// content. void EndModule() { + if (TimePassesIsEnabled) + ExceptionTimer->startTimer(); + if (shouldEmitMovesModule || shouldEmitTableModule) { const std::vector Personalities = MMI->getPersonalities(); - for (unsigned i =0; i < Personalities.size(); ++i) + for (unsigned i = 0; i < Personalities.size(); ++i) EmitCommonEHFrame(Personalities[i], i); for (std::vector::iterator I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) EmitEHFrame(*I); } + + if (TimePassesIsEnabled) + ExceptionTimer->stopTimer(); } /// BeginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. void BeginFunction(MachineFunction *MF) { + if (TimePassesIsEnabled) + ExceptionTimer->startTimer(); + this->MF = MF; shouldEmitTable = shouldEmitMoves = false; - if (MMI && TAI->doesSupportExceptionHandling()) { + if (MMI && TAI->doesSupportExceptionHandling()) { // Map all labels and get rid of any dead landing pads. MMI->TidyLandingPads(); + // If any landing pads survive, we need an EH table. if (MMI->getLandingPads().size()) shouldEmitTable = true; @@ -4566,13 +4099,20 @@ public: // Assumes in correct section after the entry point. EmitLabel("eh_func_begin", ++SubprogramCount); } + shouldEmitTableModule |= shouldEmitTable; shouldEmitMovesModule |= shouldEmitMoves; + + if (TimePassesIsEnabled) + ExceptionTimer->stopTimer(); } /// EndFunction - Gather and emit post-function exception information. /// void EndFunction() { + if (TimePassesIsEnabled) + ExceptionTimer->startTimer(); + if (shouldEmitMoves || shouldEmitTable) { EmitLabel("eh_func_end", SubprogramCount); EmitExceptionTable(); @@ -4580,13 +4120,16 @@ public: // Save EH frame information EHFrames. push_back(FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), - SubprogramCount, - MMI->getPersonalityIndex(), - MF->getFrameInfo()->hasCalls(), - !MMI->getLandingPads().empty(), - MMI->getFrameMoves(), - MF->getFunction())); - } + SubprogramCount, + MMI->getPersonalityIndex(), + MF->getFrameInfo()->hasCalls(), + !MMI->getLandingPads().empty(), + MMI->getFrameMoves(), + MF->getFunction())); + } + + if (TimePassesIsEnabled) + ExceptionTimer->stopTimer(); } }; @@ -4698,7 +4241,7 @@ unsigned DIEInteger::SizeOf(const DwarfDebug &DD, unsigned Form) const { /// EmitValue - Emit string value. /// void DIEString::EmitValue(DwarfDebug &DD, unsigned Form) { - DD.getAsm()->EmitString(String); + DD.getAsm()->EmitString(Str); } //===----------------------------------------------------------------------===// @@ -4909,8 +4452,8 @@ void DIE::dump() { /// DwarfWriter Implementation /// -DwarfWriter::DwarfWriter() : ImmutablePass(&ID), DD(NULL), DE(NULL) { -} +DwarfWriter::DwarfWriter() + : ImmutablePass(&ID), DD(0), DE(0) {} DwarfWriter::~DwarfWriter() { delete DE; @@ -4956,6 +4499,11 @@ void DwarfWriter::EndFunction(MachineFunction *MF) { MMI->EndFunction(); } +/// ValidDebugInfo - Return true if V represents valid debug info value. +bool DwarfWriter::ValidDebugInfo(Value *V) { + return DD && DD->ValidDebugInfo(V); +} + /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. @@ -4964,11 +4512,13 @@ unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, return DD->RecordSourceLine(Line, Col, Src); } -/// RecordSource - Register a source file with debug info. Returns an source -/// ID. -unsigned DwarfWriter::RecordSource(const std::string &Dir, - const std::string &File) { - return DD->RecordSource(Dir, File); +/// getOrCreateSourceID - Look up the source id with the given directory and +/// source file names. If none currently exists, create a new id and insert it +/// in the SourceIds map. This can update DirectoryNames and SourceFileNames maps +/// as well. +unsigned DwarfWriter::getOrCreateSourceID(const std::string &DirName, + const std::string &FileName) { + return DD->getOrCreateSourceID(DirName, FileName); } /// RecordRegionStart - Indicate the start of a region. @@ -4991,3 +4541,9 @@ unsigned DwarfWriter::getRecordSourceLineCount() { void DwarfWriter::RecordVariable(GlobalVariable *GV, unsigned FrameIndex) { DD->RecordVariable(GV, FrameIndex); } + +/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should +/// be emitted. +bool DwarfWriter::ShouldEmitDwarfDebug() const { + return DD->ShouldEmitDwarfDebug(); +}