X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfWriter.cpp;h=4120d9f917105721e3490c31557a796218456ff1;hb=b169426272b85ce28a9a56d13154e61b158fc47a;hp=3176c38141db6c9db09f52c6f1d27595cea65120;hpb=c69bf2c832386140d6606eef3febf2d3aa7a64f0;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 3176c38141d..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/Type.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,20 +35,33 @@ #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; using namespace llvm::dwarf; +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. @@ -59,6 +69,28 @@ static const unsigned InitValuesSetSize = 9; // 512 class DIE; class DIEValue; +//===----------------------------------------------------------------------===// +/// Utility routines. +/// +/// 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)); + } + } + return NULL; +} + //===----------------------------------------------------------------------===// /// DWLabel - Labels are used to track locations in the assembler file. /// Labels appear in the form @verbatim @endverbatim, @@ -77,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); } @@ -96,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; @@ -104,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; } @@ -143,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; } @@ -225,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. @@ -308,9 +324,7 @@ public: /// unsigned Type; - explicit DIEValue(unsigned T) - : Type(T) - {} + explicit DIEValue(unsigned T) : Type(T) {} virtual ~DIEValue() {} // Accessors @@ -397,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; } @@ -413,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 }; @@ -435,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. @@ -469,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) {} @@ -498,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) { @@ -511,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; } @@ -561,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; } @@ -605,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; } @@ -651,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; } @@ -687,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) { @@ -707,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; @@ -720,13 +717,13 @@ private: /// DIE *Die; - /// DescToDieMap - Tracks the mapping of unit level debug informaton - /// descriptors to debug information entries. - std::map DescToDieMap; + /// 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; + std::map GVToDIEntryMap; /// Globals - A map of globally visible named entities for this unit. /// @@ -735,32 +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(CompileUnitDesc *CUD, unsigned I, DIE *D) - : Desc(CUD) - , ID(I) - , Die(D) - , DescToDieMap() - , DescToDIEntryMap() - , Globals() - , DiesSet(InitDiesSetSize) - , Dies() + CompileUnit(unsigned I, DIE *D) + : 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; } @@ -778,15 +760,15 @@ 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]; } /// AddDie - Adds or interns the DIE to the compile unit. @@ -812,9 +794,7 @@ public: /// Dwarf - Emits general Dwarf directives. /// class Dwarf { - protected: - //===--------------------------------------------------------------------===// // Core attributes used by the Dwarf writer. // @@ -875,7 +855,6 @@ protected: } public: - //===--------------------------------------------------------------------===// // Accessors. // @@ -1113,19 +1092,97 @@ public: }; +//===----------------------------------------------------------------------===// +/// SrcLineInfo - This class is used to record source line correspondence. +/// +class SrcLineInfo { + unsigned Line; // Source line number. + unsigned Column; // Source column. + unsigned SourceID; // Source ID number. + 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) {} + + // Accessors + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + unsigned getSourceID() const { return SourceID; } + unsigned getLabelID() const { return LabelID; } +}; + +//===----------------------------------------------------------------------===// +/// DbgVariable - This class is used to track local variable information. +/// +class DbgVariable { + DIVariable Var; // Variable Descriptor. + unsigned FrameIndex; // Variable frame index. +public: + DbgVariable(DIVariable V, unsigned I) : Var(V), FrameIndex(I) {} + + // Accessors. + DIVariable getVariable() const { return Var; } + unsigned getFrameIndex() const { return FrameIndex; } +}; + +//===----------------------------------------------------------------------===// +/// DbgScope - This class is used to track scope information. +/// +class DbgScope { + DbgScope *Parent; // Parent to this 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 Variables;// Variables declared in scope. +public: + DbgScope(DbgScope *P, DIDescriptor D) + : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0), Scopes(), Variables() + {} + ~DbgScope() { + for (unsigned i = 0, N = Scopes.size(); i < N; ++i) delete Scopes[i]; + for (unsigned j = 0, M = Variables.size(); j < M; ++j) delete Variables[j]; + } + + // Accessors. + DbgScope *getParent() const { return Parent; } + DIDescriptor getDesc() const { return Desc; } + unsigned getStartLabelID() const { return StartLabelID; } + unsigned getEndLabelID() const { return EndLabelID; } + SmallVector &getScopes() { return Scopes; } + SmallVector &getVariables() { return Variables; } + void setStartLabelID(unsigned S) { StartLabelID = S; } + void setEndLabelID(unsigned E) { EndLabelID = E; } + + /// AddScope - Add a scope to the scope. + /// + void AddScope(DbgScope *S) { Scopes.push_back(S); } + + /// AddVariable - Add a variable to the scope. + /// + void AddVariable(DbgVariable *V) { Variables.push_back(V); } +}; + //===----------------------------------------------------------------------===// /// 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; + /// 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. /// @@ -1135,6 +1192,31 @@ private: /// std::vector Abbreviations; + /// 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. + /// + StringMap SourceFileIdMap; + + /// SourceFileNames - A list of source file names. + SmallVector SourceFileNames; + + /// 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. + std::vector Lines; + /// ValuesSet - Used to uniquely define values. /// FoldingSet ValuesSet; @@ -1147,17 +1229,13 @@ private: /// UniqueVector StringPool; - /// UnitMap - Map debug information descriptor to compile unit. - /// - std::map DescToUnitMap; - /// SectionMap - Provides a unique id per text section. /// UniqueVector SectionMap; /// SectionSourceLines - Tracks line numbers per text section. /// - std::vector > SectionSourceLines; + std::vector > SectionSourceLines; /// didInitial - Flag to indicate if initial emission has been done. /// @@ -1167,6 +1245,16 @@ private: /// bool shouldEmit; + // RootDbgScope - Top level scope for the current function. + // + DbgScope *RootDbgScope; + + /// DbgScopeMap - Tracks the scopes in the current function. + DenseMap DbgScopeMap; + + /// DebugTimer - Timer for the Dwarf debug writer. + Timer *DebugTimer; + struct FunctionDebugFrameInfo { unsigned Number; std::vector Moves; @@ -1177,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. /// @@ -1238,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); @@ -1280,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) { @@ -1393,17 +1506,41 @@ public: Die->AddValue(Attribute, Block->BestForm(), Value); } -private: + /// AddSourceLine - Add location information to specified debug information + /// entry. + void AddSourceLine(DIE *Die, const DIVariable *V) { + unsigned FileID = 0; + unsigned Line = V->getLineNumber(); + 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, 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); - } + void AddSourceLine(DIE *Die, const DIGlobal *G) { + unsigned FileID = 0; + unsigned Line = G->getLineNumber(); + 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, const DIType *Ty) { + unsigned FileID = 0; + 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); } /// AddAddress - Add an address attribute to a die based on the location @@ -1433,103 +1570,90 @@ 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; - } + void AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { + if (Ty.isNull()) + 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(); + // Check for pre-existence. + DIEntry *&Slot = DW_Unit->getDIEntrySlotFor(Ty.getGV()); + // If it exists then use the existing value. + if (Slot) { + Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); + return; + } - // Construct type. - DIE Buffer(DW_TAG_base_type); - ConstructType(Buffer, TyDesc, Unit); + // Set up proxy. + Slot = NewDIEntry(); - // 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); - } + // Construct type. + DIE Buffer(DW_TAG_base_type); + 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); } - /// ConstructType - Construct basic type die from DIBasicType. - void ConstructType(CompileUnit *DW_Unit, DIE &Buffer, - DIBasicType *BTy) { + /// ConstructTypeDIE - Construct basic type die from DIBasicType. + void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + 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); } - /// ConstructType - Construct derived type die from DIDerivedType. - void ConstructType(CompileUnit *DW_Unit, DIE &Buffer, - DIDerivedType *DTy) { + /// ConstructTypeDIE - Construct derived type die from DIDerivedType. + void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + 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(); - // FIXME - Enable this. AddType(&Buffer, FromTy, DW_Unit); + 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) @@ -1537,20 +1661,123 @@ 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); } - // ConstructSubrangeDIE - Construct subrange DIE from DISubrange. - void ConstructSubrangeDIE (DIE &Buffer, DISubrange *SR, DIE *IndexTy) { - int64_t L = SR->getLo(); - int64_t H = SR->getHi(); + /// ConstructTypeDIE - Construct type DIE from DICompositeType. + void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, + DICompositeType CTy) { + // Get core information. + std::string Name; + CTy.getName(Name); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); + + switch (Tag) { + case DW_TAG_vector_type: + case DW_TAG_array_type: + 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; + case DW_TAG_subroutine_type: + { + // Add prototype flag. + AddUInt(&Buffer, DW_AT_prototyped, DW_FORM_flag, 1); + DIArray Elements = CTy.getTypeArray(); + // Add return type. + DIDescriptor RTy = 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); + AddType(DW_Unit, Arg, DIType(Ty.getGV())); + Buffer.AddChild(Arg); + } + } + break; + case DW_TAG_structure_type: + case DW_TAG_union_type: + { + // Add elements to structure type. + 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); + 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: + break; + } + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); + + 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); + } + } + + /// 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); } @@ -1562,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(&Buffer, CTy->getTypeDerivedFrom(), DW_Unit); // Construct an anonymous type for index type. DIE IdxBuffer(DW_TAG_base_type); @@ -1574,453 +1801,153 @@ private: // Add subranges to array type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DISubrange Element = Elements.getElement(i); - ConstructSubrangeDIE(Buffer, &Element, IndexTy); + DIDescriptor Element = Elements.getElement(i); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + ConstructSubrangeDIE(Buffer, DISubrange(Element.getGV()), IndexTy); } } - /// ConstructEnumTypeDIE - Construct enum type DIE from - /// DIEnumerator. - void ConstructEnumType(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; } - /// 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); - } - } + /// 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(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); - // Add flags. - if (!MethodDesc->isStatic()) - AddUInt(Method, DW_AT_external, DW_FORM_flag, 1); - AddUInt(Method, DW_AT_declaration, DW_FORM_flag, 1); + AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom()); - 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); - } + AddSourceLine(MemberDie, &DT); - 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); + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); - // Add arguments. - for (unsigned i = 1, N = Elements.size(); i < N; ++i) { - DIE *Arg = new DIE(DW_TAG_formal_parameter); - AddType(Arg, cast(Elements[i]), Unit); - Buffer.AddChild(Arg); - } + if (Size != FieldSize) { + // Handle bitfield. + AddUInt(MemberDie, DW_AT_byte_size, 0, DT.getOriginalTypeSize() >> 3); + AddUInt(MemberDie, DW_AT_bit_size, 0, DT.getSizeInBits()); - break; - } - default: break; - } + 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); } - - // 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); + DIEBlock *Block = new DIEBlock(); + AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst); + AddUInt(Block, 0, DW_FORM_udata, DT.getOffsetInBits() >> 3); + AddBlock(MemberDie, DW_AT_data_member_location, 0, Block); + + 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); + + return MemberDie; + } + + /// 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); + + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + + // Add Return Type. + if (!IsConstructor) { + if (Args.isNull()) + AddType(DW_Unit, SPDie, SPTy); 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; - } - - /// GetBaseCompileUnit - Get the main compile unit. - /// - CompileUnit *GetBaseCompileUnit() const { - CompileUnit *Unit = CompileUnits[0]; - assert(Unit && "Missing compile unit."); - return Unit; - } - - /// FindCompileUnit - Get the compile unit for the given descriptor. - /// - CompileUnit *FindCompileUnit(CompileUnitDesc *UnitDesc) { - CompileUnit *Unit = DescToUnitMap[UnitDesc]; - assert(Unit && "Missing compile unit."); - return Unit; - } - - /// NewGlobalVariable - Add a new global variable DIE. - /// - DIE *NewGlobalVariable(GlobalVariableDesc *GVD) { - // Get the compile unit context. - CompileUnitDesc *UnitDesc = - static_cast(GVD->getContext()); - CompileUnit *Unit = GetBaseCompileUnit(); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(GVD); - if (Slot) return Slot; - - // Get the global variable itself. - GlobalVariable *GV = GVD->getGlobalVariable(); - - const std::string &Name = GVD->getName(); - const std::string &FullName = GVD->getFullName(); - const std::string &LinkageName = GVD->getLinkageName(); - // Create the global's variable DIE. - DIE *VariableDie = new DIE(DW_TAG_variable); - AddString(VariableDie, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); + AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getGV())); } - 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 (!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(DW_Unit, Arg, DIType(Args.getElement(i).getGV())); + AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); // ??? + SPDie->AddChild(Arg); + } } - 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); + 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); + + if (!SP.isLocalToUnit()) + AddUInt(SPDie, DW_AT_external, DW_FORM_flag, 1); + return SPDie; + } - return SubprogramDie; + /// FindCompileUnit - Get the compile unit for the given descriptor. + /// + CompileUnit *FindCompileUnit(DICompileUnit Unit) { + CompileUnit *DW_Unit = CompileUnitMap[Unit.getGV()]; + assert(DW_Unit && "Missing compile unit."); + return DW_Unit; } - /// NewScopeVariable - Create a new scope variable. + /// NewDbgScopeVariable - Create a new scope variable. /// - DIE *NewScopeVariable(DebugVariable *DV, CompileUnit *Unit) { + DIE *NewDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { // Get the descriptor. - VariableDesc *VD = DV->getDesc(); + 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 @@ -2029,13 +1956,15 @@ 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->getFile(), VD->getLine()); + AddSourceLine(VariableDie, &VD); // Add variable type. - AddType(VariableDie, VD->getType(), Unit); + AddType(Unit, VariableDie, VD.getType()); // Add variable address. MachineLocation Location; @@ -2046,23 +1975,56 @@ private: return VariableDie; } - /// ConstructScope - Construct the components of a scope. + /// getOrCreateScope - Returns the scope associated with the given descriptor. + /// + DbgScope *getOrCreateScope(GlobalVariable *V) { + DbgScope *&Slot = DbgScopeMap[V]; + if (Slot) return Slot; + + // FIXME - breaks down when the context is an inlined function. + DIDescriptor ParentDesc; + DIDescriptor Desc(V); + + if (Desc.getTag() == dwarf::DW_TAG_lexical_block) { + DIBlock Block(V); + ParentDesc = Block.getContext(); + } + + DbgScope *Parent = ParentDesc.isNull() ? + NULL : getOrCreateScope(ParentDesc.getGV()); + Slot = new DbgScope(Parent, Desc); + + 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 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; @@ -2075,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); @@ -2096,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. @@ -2126,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, @@ -2157,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 @@ -2183,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()); @@ -2311,38 +2293,45 @@ private: /// void SizeAndOffsets() { // Process base compile unit. - CompileUnit *Unit = GetBaseCompileUnit(); - // 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(Unit->getDie(), Offset, true); + 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 + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + SizeAndOffsetDie(Unit->getDie(), Offset, true); + } } - /// EmitDebugInfo - Emit the debug info section. + /// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section. /// - void EmitDebugInfo() { - // Start debug info section. - Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); - - CompileUnit *Unit = GetBaseCompileUnit(); + 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. - + 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"); @@ -2350,10 +2339,23 @@ private: 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()); + + if (MainCU) { + EmitDebugInfoPerCU(MainCU); + return; + } + + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) + EmitDebugInfoPerCU(CompileUnits[i]); + } + /// EmitAbbreviations - Emit the abbreviation section. /// void EmitAbbreviations() const { @@ -2453,23 +2455,20 @@ private: Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count"); Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count"); - const UniqueVector &Directories = MMI->getDirectories(); - const UniqueVector &SourceFiles = MMI->getSourceFiles(); - // 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 = SourceFiles.size(); - SourceID <= NSID; ++SourceID) { - const SourceFileInfo &SourceFile = SourceFiles[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"); @@ -2485,11 +2484,12 @@ private: for (unsigned j = 0; j < SecSrcLinesSize; ++j) { // Isolate current sections line info. - const std::vector &LineInfos = SectionSourceLines[j]; + const std::vector &LineInfos = SectionSourceLines[j]; 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(); @@ -2499,20 +2499,20 @@ private: // Construct rows of the address, source, line, column matrix. for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) { - const SourceLineInfo &LineInfo = LineInfos[i]; + const SrcLineInfo &LineInfo = LineInfos[i]; unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID()); if (!LabelID) continue; - unsigned SourceID = LineInfo.getSourceID(); - const SourceFileInfo &SourceFile = SourceFiles[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"); @@ -2635,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); @@ -2643,47 +2644,54 @@ private: Asm->EOL(); } - /// EmitDebugPubNames - Emit visible names into a debug pubnames section. - /// - void EmitDebugPubNames() { - // Start the dwarf pubnames section. - Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); - - CompileUnit *Unit = GetBaseCompileUnit(); - + void EmitDebugPubNamesPerCU(CompileUnit *Unit) { EmitDifference("pubnames_end", Unit->getID(), "pubnames_begin", Unit->getID(), true); Asm->EOL("Length of Public Names Info"); - + EmitLabel("pubnames_begin", Unit->getID()); - + Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF Version"); - + EmitSectionOffset("info_begin", "section_info", Unit->getID(), 0, true, false); Asm->EOL("Offset of Compilation Unit Info"); - - EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),true); + + EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(), + true); Asm->EOL("Compilation Unit Length"); - + std::map &Globals = Unit->getGlobals(); - for (std::map::iterator GI = Globals.begin(), - GE = Globals.end(); - GI != GE; ++GI) { + 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(0); Asm->EOL("End Mark"); EmitLabel("pubnames_end", Unit->getID()); - + 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. /// void EmitDebugStr() { @@ -2763,46 +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(); + } } - /// ConstructCompileUnitDIEs - Create a compile unit DIE for each source and - /// header file. - void ConstructCompileUnitDIEs() { - const UniqueVector CUW = MMI->getCompileUnits(); - - 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); + /// 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; } - /// ConstructGlobalDIEs - Create DIEs for each of the externally visible - /// global variables. - void ConstructGlobalDIEs() { - std::vector GlobalVariables; - MMI->getAnchoredDescriptors(*M, GlobalVariables); + void ConstructCompileUnit(GlobalVariable *GV) { + DICompileUnit DIUnit(GV); + std::string Dir, FN, Prod; + unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir), + DIUnit.getFilename(FN)); - for (unsigned i = 0, N = GlobalVariables.size(); i < N; ++i) { - GlobalVariableDesc *GVD = GlobalVariables[i]; - NewGlobalVariable(GVD); + 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); + } + + /// 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); + } } - /// ConstructSubprogramDIEs - Create DIEs for each of the externally visible - /// subprograms. - void ConstructSubprogramDIEs() { - std::vector Subprograms; - MMI->getAnchoredDescriptors(*M, Subprograms); + 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 = Subprograms.size(); i < N; ++i) { - SubprogramDesc *SPD = Subprograms[i]; - NewSubprogram(SPD); - } + // 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; + } + + /// 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; + } + + bool ConstructSubprogram(GlobalVariable *GV) { + DISubprogram SP(GV); + CompileUnit *Unit = MainCU; + if (!Unit) + Unit = FindCompileUnit(SP.getCompileUnit()); + + // 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: @@ -2810,65 +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) - { + : 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; } - /// SetModuleInfo - Set machine module information when it's known that pass - /// manager has created it. Set by the target AsmPrinter. - void SetModuleInfo(MachineModuleInfo *mmi) { - // 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(); - } - } + /// 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(); + + if (CompileUnits.empty()) { + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return; + } + + // Create DIEs for each of the externally visible global variables. + bool globalDIEs = ConstructGlobalVariableDIEs(); - // Emit initial sections - EmitInitial(); + // Create DIEs for each of the externally visible subprograms. + bool subprogramDIEs = ConstructSubprograms(); + + // 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(); + + return; + } + + 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(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// BeginModule - Emit all Dwarf sections that should come prior to the @@ -2880,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()); @@ -2931,6 +3127,9 @@ public: // Emit info into a debug macinfo section. EmitDebugMacInfo(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// BeginFunction - Gather pre-function debug information. Assumes being @@ -2938,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); @@ -2948,37 +3150,40 @@ public: // Emit label for the implicitly defined dbg.stoppoint at the start of // the function. - const std::vector &LineInfos = MMI->getSourceLines(); - if (!LineInfos.empty()) { - const SourceLineInfo &LineInfo = LineInfos[0]; + if (!Lines.empty()) { + 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); // Get function line info. - const std::vector &LineInfos = MMI->getSourceLines(); - - if (!LineInfos.empty()) { + if (!Lines.empty()) { // Get section line info. unsigned ID = SectionMap.insert(Asm->CurrentSection_); if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID); - std::vector &SectionLineInfos = SectionSourceLines[ID-1]; + std::vector &SectionLineInfos = SectionSourceLines[ID-1]; // Append the function info to section info. SectionLineInfos.insert(SectionLineInfos.end(), - LineInfos.begin(), LineInfos.end()); + Lines.begin(), Lines.end()); } // Construct scopes for subprogram. - if (MMI->getRootScope()) - ConstructRootScope(MMI->getRootScope()); + if (RootDbgScope) + ConstructRootDbgScope(RootDbgScope); else // FIXME: This is wrong. We are essentially getting past a problem with // debug information not being able to handle unreachable blocks that have @@ -2988,10 +3193,186 @@ public: // scope, i.e., one that encompasses the whole function. This isn't // desirable. And a better way of handling this (and all of the debugging // information) needs to be explored. - ConstructDefaultScope(MF); + ConstructDefaultDbgScope(MF); DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount, MMI->getFrameMoves())); + + // Clear debug info + if (RootDbgScope) { + delete RootDbgScope; + DbgScopeMap.clear(); + RootDbgScope = NULL; + } + + Lines.clear(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + } + + /// 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) { + 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; + } + + /// 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(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; + } + + /// getRecordSourceLineCount - Return the number of source lines in the debug + /// info. + unsigned getRecordSourceLineCount() const { + return Lines.size(); + } + + /// 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) { + 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(); } }; @@ -2999,8 +3380,6 @@ public: /// DwarfException - Emits Dwarf exception handling directives. /// class DwarfException : public Dwarf { - -private: struct FunctionEHFrameInfo { std::string FnName; unsigned Number; @@ -3036,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) { @@ -3105,24 +3487,14 @@ private: Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); Asm->EOL("LSDA Encoding (pcrel sdata4)"); - if (TAI->doesFDEEncodingRequireSData4()) { - Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); - Asm->EOL("FDE Encoding (pcrel sdata4)"); - } else { - Asm->EmitInt8(DW_EH_PE_pcrel); - Asm->EOL("FDE Encoding (pcrel)"); - } + Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); + Asm->EOL("FDE Encoding (pcrel sdata4)"); } else { Asm->EmitULEB128Bytes(1); Asm->EOL("Augmentation Size"); - if (TAI->doesFDEEncodingRequireSData4()) { - Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); - Asm->EOL("FDE Encoding (pcrel sdata4)"); - } else { - Asm->EmitInt8(DW_EH_PE_pcrel); - Asm->EOL("FDE Encoding (pcrel)"); - } + Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); + Asm->EOL("FDE Encoding (pcrel sdata4)"); } // Indicate locations of general callee saved registers in frame. @@ -3150,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"; @@ -3168,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())) { @@ -3203,12 +3580,10 @@ private: Asm->EOL("FDE CIE offset"); - EmitReference("eh_func_begin", EHFrameInfo.Number, true, - TAI->doesRequire32BitFDEReference()); + EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); Asm->EOL("FDE initial location"); EmitDifference("eh_func_end", EHFrameInfo.Number, - "eh_func_begin", EHFrameInfo.Number, - TAI->doesRequire32BitFDEReference()); + "eh_func_begin", EHFrameInfo.Number, true); Asm->EOL("FDE address range"); // If there is a personality and landing pads then point to the language @@ -3229,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 @@ -3654,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. @@ -3678,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; @@ -3710,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(); @@ -3724,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(); } }; @@ -3842,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); } //===----------------------------------------------------------------------===// @@ -4053,29 +4452,26 @@ void DIE::dump() { /// DwarfWriter Implementation /// -DwarfWriter::DwarfWriter(raw_ostream &OS, AsmPrinter *A, - const TargetAsmInfo *T) { - DE = new DwarfException(OS, A, T); - DD = new DwarfDebug(OS, A, T); -} +DwarfWriter::DwarfWriter() + : ImmutablePass(&ID), DD(0), DE(0) {} DwarfWriter::~DwarfWriter() { delete DE; delete DD; } -/// SetModuleInfo - Set machine module info when it's known that pass manager -/// has created it. Set by the target AsmPrinter. -void DwarfWriter::SetModuleInfo(MachineModuleInfo *MMI) { - DD->SetModuleInfo(MMI); - DE->SetModuleInfo(MMI); -} - /// BeginModule - Emit all Dwarf sections that should come prior to the /// content. -void DwarfWriter::BeginModule(Module *M) { +void DwarfWriter::BeginModule(Module *M, + MachineModuleInfo *MMI, + raw_ostream &OS, AsmPrinter *A, + const TargetAsmInfo *T) { + DE = new DwarfException(OS, A, T); + DD = new DwarfDebug(OS, A, T); DE->BeginModule(M); DD->BeginModule(M); + DD->SetDebugInfo(MMI); + DE->SetModuleInfo(MMI); } /// EndModule - Emit all Dwarf sections that should come after the content. @@ -4102,3 +4498,52 @@ void DwarfWriter::EndFunction(MachineFunction *MF) { // Clear function debug information. 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. +unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, + unsigned Src) { + return DD->RecordSourceLine(Line, Col, Src); +} + +/// 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. +unsigned DwarfWriter::RecordRegionStart(GlobalVariable *V) { + return DD->RecordRegionStart(V); +} + +/// RecordRegionEnd - Indicate the end of a region. +unsigned DwarfWriter::RecordRegionEnd(GlobalVariable *V) { + return DD->RecordRegionEnd(V); +} + +/// getRecordSourceLineCount - Count source lines. +unsigned DwarfWriter::getRecordSourceLineCount() { + return DD->getRecordSourceLineCount(); +} + +/// RecordVariable - Indicate the declaration of a local variable. +/// +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(); +}