X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfWriter.cpp;h=4120d9f917105721e3490c31557a796218456ff1;hb=b169426272b85ce28a9a56d13154e61b158fc47a;hp=63fb68b5ec75470cc6f86f4a0b4ca1c2523309a9;hpb=7009d24e8157dbe3689f7f44b64cedf6e1371b84;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 63fb68b5ec7..4120d9f9171 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -12,11 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/DwarfWriter.h" - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/UniqueVector.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" @@ -30,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" @@ -39,6 +35,10 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include #include using namespace llvm; @@ -48,15 +48,20 @@ static RegisterPass X("dwarfwriter", "DWARF Information Writer"); char DwarfWriter::ID = 0; +static TimerGroup &getDwarfTimerGroup() { + static TimerGroup DwarfTimerGroup("Dwarf Exception and Debugging"); + return DwarfTimerGroup; +} + namespace llvm { //===----------------------------------------------------------------------===// /// Configuration values for initial hash set sizes (log2). /// -static const unsigned InitDiesSetSize = 9; // 512 -static const unsigned InitAbbreviationsSetSize = 9; // 512 -static const unsigned InitValuesSetSize = 9; // 512 +static const unsigned InitDiesSetSize = 9; // log2(512) +static const unsigned InitAbbreviationsSetSize = 9; // log2(512) +static const unsigned InitValuesSetSize = 9; // log2(512) //===----------------------------------------------------------------------===// /// Forward declarations. @@ -67,40 +72,6 @@ class DIEValue; //===----------------------------------------------------------------------===// /// Utility routines. /// -/// getGlobalVariablesUsing - Return all of the GlobalVariables which have the -/// specified value in their initializer somewhere. -static void -getGlobalVariablesUsing(Value *V, std::vector &Result) { - // Scan though value users. - for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { - if (GlobalVariable *GV = dyn_cast(*I)) { - // If the user is a GlobalVariable then add to result. - Result.push_back(GV); - } else if (Constant *C = dyn_cast(*I)) { - // If the user is a constant variable then scan its users. - getGlobalVariablesUsing(C, Result); - } - } -} - -/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the -/// named GlobalVariable. -static void -getGlobalVariablesUsing(Module &M, const std::string &RootName, - std::vector &Result) { - std::vector FieldTypes; - FieldTypes.push_back(Type::Int32Ty); - FieldTypes.push_back(Type::Int32Ty); - - // Get the GlobalVariable root. - GlobalVariable *UseRoot = M.getGlobalVariable(RootName, - StructType::get(FieldTypes)); - - // If present and linkonce then scan for users. - if (UseRoot && UseRoot->hasLinkOnceLinkage()) - getGlobalVariablesUsing(UseRoot, Result); -} - /// getGlobalVariable - Return either a direct or cast Global value. /// static GlobalVariable *getGlobalVariable(Value *V) { @@ -138,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); } @@ -157,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; @@ -165,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; } @@ -204,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; } @@ -286,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. @@ -369,9 +324,7 @@ public: /// unsigned Type; - explicit DIEValue(unsigned T) - : Type(T) - {} + explicit DIEValue(unsigned T) : Type(T) {} virtual ~DIEValue() {} // Accessors @@ -458,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; } @@ -474,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 }; @@ -496,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. @@ -530,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) {} @@ -559,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) { @@ -572,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; } @@ -622,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; } @@ -666,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; } @@ -712,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; } @@ -748,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) { @@ -768,7 +709,6 @@ public: /// CompileUnit - This dwarf writer support class manages information associate /// with a source file. class CompileUnit { -private: /// ID - File identifier for source. /// unsigned ID; @@ -792,7 +732,6 @@ private: /// DiesSet - Used to uniquely define dies within the compile unit. /// FoldingSet DiesSet; - public: CompileUnit(unsigned I, DIE *D) : ID(I), Die(D), GVToDieMap(), @@ -855,9 +794,7 @@ public: /// Dwarf - Emits general Dwarf directives. /// class Dwarf { - protected: - //===--------------------------------------------------------------------===// // Core attributes used by the Dwarf writer. // @@ -918,7 +855,6 @@ protected: } public: - //===--------------------------------------------------------------------===// // Accessors. // @@ -1166,7 +1102,7 @@ class SrcLineInfo { unsigned LabelID; // Label in code ID number. public: SrcLineInfo(unsigned L, unsigned C, unsigned S, unsigned I) - : Line(L), Column(C), SourceID(S), LabelID(I) {} + : Line(L), Column(C), SourceID(S), LabelID(I) {} // Accessors unsigned getLine() const { return Line; } @@ -1175,42 +1111,12 @@ public: unsigned getLabelID() const { return LabelID; } }; - -//===----------------------------------------------------------------------===// -/// SrcFileInfo - This class is used to track source information. -/// -class SrcFileInfo { - unsigned DirectoryID; // Directory ID number. - std::string Name; // File name (not including directory.) -public: - SrcFileInfo(unsigned D, const std::string &N) : DirectoryID(D), Name(N) {} - - // Accessors - unsigned getDirectoryID() const { return DirectoryID; } - const std::string &getName() const { return Name; } - - /// operator== - Used by UniqueVector to locate entry. - /// - bool operator==(const SrcFileInfo &SI) const { - return getDirectoryID() == SI.getDirectoryID() && getName() == SI.getName(); - } - - /// operator< - Used by UniqueVector to locate entry. - /// - bool operator<(const SrcFileInfo &SI) const { - return getDirectoryID() < SI.getDirectoryID() || - (getDirectoryID() == SI.getDirectoryID() && getName() < SI.getName()); - } -}; - //===----------------------------------------------------------------------===// /// DbgVariable - This class is used to track local variable information. /// class DbgVariable { -private: DIVariable Var; // Variable Descriptor. unsigned FrameIndex; // Variable frame index. - public: DbgVariable(DIVariable V, unsigned I) : Var(V), FrameIndex(I) {} @@ -1223,7 +1129,6 @@ public: /// DbgScope - This class is used to track scope information. /// class DbgScope { -private: DbgScope *Parent; // Parent to this scope. DIDescriptor Desc; // Debug info descriptor for scope. // Either subprogram or block. @@ -1231,7 +1136,6 @@ private: 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() @@ -1264,15 +1168,21 @@ public: /// DwarfDebug - Emits Dwarf debug directives. /// class DwarfDebug : public Dwarf { - -private: //===--------------------------------------------------------------------===// // Attributes used to construct specific Dwarf sections. // - /// DW_CUs - All the compile units involved in this build. The index - /// of each entry in this vector corresponds to the sources in MMI. - DenseMap DW_CUs; + /// CompileUnitMap - A map of global variables representing compile units to + /// compile units. + DenseMap CompileUnitMap; + + /// CompileUnits - All the compile units in this module. + /// + SmallVector CompileUnits; + + /// MainCU - Some platform prefers one compile unit per .o file. In such + /// cases, all dies are inserted in MainCU. + CompileUnit *MainCU; /// AbbreviationsSet - Used to uniquely define abbreviations. /// @@ -1282,11 +1192,27 @@ private: /// std::vector Abbreviations; - /// Directories - Uniquing vector for directories. - UniqueVector Directories; + /// 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; - /// SourceFiles - Uniquing vector for source files. - UniqueVector SrcFiles; + /// SourceIdMap - Source id map, i.e. pair of directory id and source file + /// id mapped to a unique id. + DenseMap, unsigned> SourceIdMap; + + /// SourceIds - Reverse map from source id to directory id + file id pair. + /// + SmallVector, 8> SourceIds; /// Lines - List of of source line correspondence. std::vector Lines; @@ -1323,8 +1249,11 @@ private: // DbgScope *RootDbgScope; - // DbgScopeMap - Tracks the scopes in the current function. + /// DbgScopeMap - Tracks the scopes in the current function. DenseMap DbgScopeMap; + + /// DebugTimer - Timer for the Dwarf debug writer. + Timer *DebugTimer; struct FunctionDebugFrameInfo { unsigned Number; @@ -1336,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. /// @@ -1397,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); @@ -1439,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) { @@ -1552,23 +1506,14 @@ 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(); - if (V->getVersion() <= LLVMDebugVersion6) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(V->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIVariable - // directly. - unsigned DID = Directories.idFor(V->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, V->getFilename())); - } + CompileUnit *Unit = FindCompileUnit(V->getCompileUnit()); + FileID = Unit->getID(); + assert (FileID && "Invalid file id"); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } @@ -1578,16 +1523,9 @@ private: void AddSourceLine(DIE *Die, const DIGlobal *G) { unsigned FileID = 0; unsigned Line = G->getLineNumber(); - if (G->getVersion() <= LLVMDebugVersion6) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIGlobal - // directly. - unsigned DID = Directories.idFor(G->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, G->getFilename())); - } + CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); + FileID = Unit->getID(); + assert (FileID && "Invalid file id"); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } @@ -1595,16 +1533,12 @@ private: void AddSourceLine(DIE *Die, const DIType *Ty) { unsigned FileID = 0; unsigned Line = Ty->getLineNumber(); - if (Ty->getVersion() <= LLVMDebugVersion6) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(Ty->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIType - // directly. - unsigned DID = Directories.idFor(Ty->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, Ty->getFilename())); - } + 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); } @@ -1636,30 +1570,6 @@ 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(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { if (Ty.isNull()) @@ -1683,7 +1593,7 @@ private: else if (Ty.isDerivedType(Ty.getTag())) ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getGV())); else { - assert (Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType"); + assert(Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType"); ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getGV())); } @@ -1698,8 +1608,7 @@ private: Die->AddChild(Child); Buffer.Detach(); SetDIEntry(Slot, Child); - } - else { + } else { Die = DW_Unit->AddDie(Buffer); SetDIEntry(Slot, Die); } @@ -1712,7 +1621,8 @@ private: 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()); // Add name if not anonymous or intermediate type. @@ -1727,19 +1637,23 @@ private: DIDerivedType DTy) { // Get core information. - const std::string &Name = DTy.getName(); + 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(); 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) @@ -1754,12 +1668,14 @@ private: /// ConstructTypeDIE - Construct type DIE from DICompositeType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, DICompositeType CTy) { - // Get core information. - const std::string &Name = CTy.getName(); + 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: @@ -1820,6 +1736,9 @@ private: 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: @@ -1827,7 +1746,8 @@ private: } // Add name if not anonymous or intermediate type. - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); + if (!Name.empty()) + AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); if (Tag == DW_TAG_enumeration_type || Tag == DW_TAG_structure_type || Tag == DW_TAG_union_type) { @@ -1848,8 +1768,8 @@ private: } } - // ConstructSubrangeDIE - Construct subrange DIE from DISubrange. - void ConstructSubrangeDIE (DIE &Buffer, DISubrange SR, DIE *IndexTy) { + /// 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); @@ -1869,6 +1789,8 @@ 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(); // Construct an anonymous type for index type. @@ -1885,23 +1807,27 @@ private: } } - /// ConstructEnumTypeDIE - Construct enum type DIE from - /// DIEnumerator. + /// 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); return Enumerator; } /// CreateGlobalVariableDIE - Create new DIE using GV. - DIE *CreateGlobalVariableDIE(CompileUnit *DW_Unit, const DIGlobalVariable &GV) + DIE *CreateGlobalVariableDIE(CompileUnit *DW_Unit, const DIGlobalVariable &GV) { DIE *GVDie = new DIE(DW_TAG_variable); - AddString(GVDie, DW_AT_name, DW_FORM_string, GV.getName()); - const std::string &LinkageName = GV.getLinkageName(); + 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()); @@ -1914,7 +1840,8 @@ private: /// CreateMemberDIE - Create new member DIE. DIE *CreateMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT) { DIE *MemberDie = new DIE(DT.getTag()); - std::string Name = DT.getName(); + std::string Name; + DT.getName(Name); if (!Name.empty()) AddString(MemberDie, DW_AT_name, DW_FORM_string, Name); @@ -1922,7 +1849,24 @@ private: AddSourceLine(MemberDie, &DT); - // FIXME _ Handle bitfields + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); + + if (Size != FieldSize) { + // Handle bitfield. + AddUInt(MemberDie, DW_AT_byte_size, 0, DT.getOriginalTypeSize() >> 3); + AddUInt(MemberDie, DW_AT_bit_size, 0, DT.getSizeInBits()); + + uint64_t Offset = DT.getOffsetInBits(); + uint64_t FieldOffset = Offset; + uint64_t AlignMask = ~(DT.getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + // Maybe we need to work from the other end. + if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); + AddUInt(MemberDie, DW_AT_bit_offset, 0, Offset); + } DIEBlock *Block = new DIEBlock(); AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst); AddUInt(Block, 0, DW_FORM_udata, DT.getOffsetInBits() >> 3); @@ -1941,8 +1885,11 @@ private: const DISubprogram &SP, bool IsConstructor = false) { DIE *SPDie = new DIE(DW_TAG_subprogram); - AddString(SPDie, DW_AT_name, DW_FORM_string, SP.getName()); - const std::string &LinkageName = SP.getLinkageName(); + 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); @@ -1952,27 +1899,41 @@ private: DIArray Args = SPTy.getTypeArray(); // Add Return Type. - if (!IsConstructor) - AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getGV())); - - // Add arguments. - 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 (!IsConstructor) { + if (Args.isNull()) + AddType(DW_Unit, SPDie, SPTy); + else + AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getGV())); + } + + 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); + } + } + + 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); + AddUInt(SPDie, DW_AT_external, DW_FORM_flag, 1); return SPDie; } /// FindCompileUnit - Get the compile unit for the given descriptor. /// CompileUnit *FindCompileUnit(DICompileUnit Unit) { - CompileUnit *DW_Unit = DW_CUs[Unit.getGV()]; + CompileUnit *DW_Unit = CompileUnitMap[Unit.getGV()]; assert(DW_Unit && "Missing compile unit."); return DW_Unit; } @@ -1995,7 +1956,9 @@ 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); @@ -2016,28 +1979,32 @@ private: /// DbgScope *getOrCreateScope(GlobalVariable *V) { DbgScope *&Slot = DbgScopeMap[V]; - if (!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; - } + 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; } @@ -2110,7 +2077,9 @@ private: DISubprogram SPD(Desc.getGV()); // Get the compile unit context. - CompileUnit *Unit = FindCompileUnit(SPD.getCompileUnit()); + CompileUnit *Unit = MainCU; + if (!Unit) + Unit = FindCompileUnit(SPD.getCompileUnit()); // Get the subprogram die. DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); @@ -2130,22 +2099,12 @@ private: /// ConstructDefaultDbgScope - Construct a default scope for the subprogram. /// void ConstructDefaultDbgScope(MachineFunction *MF) { - // Find the correct subprogram descriptor. - std::string SPName = "llvm.dbg.subprograms"; - std::vector Result; - getGlobalVariablesUsing(*M, SPName, Result); - for (std::vector::iterator I = Result.begin(), - E = Result.end(); I != E; ++I) { - - DISubprogram SPD(*I); - - if (SPD.getName() == MF->getFunction()->getName()) { - // Get the compile unit context. - CompileUnit *Unit = FindCompileUnit(SPD.getCompileUnit()); - - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); - assert(SPDie && "Missing subprogram descriptor"); + 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 @@ -2313,9 +2293,17 @@ private: /// void SizeAndOffsets() { // Process base compile unit. - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; + if (MainCU) { + // Compute size of compile unit header + unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + SizeAndOffsetDie(MainCU->getDie(), Offset, true); + return; + } + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) { + CompileUnit *Unit = CompileUnits[i]; // Compute size of compile unit header unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info sizeof(int16_t) + // DWARF version number @@ -2325,41 +2313,47 @@ private: } } - /// EmitDebugInfo - Emit the debug info section. + /// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section. /// + void EmitDebugInfoPerCU(CompileUnit *Unit) { + DIE *Die = Unit->getDie(); + // Emit the compile units header. + EmitLabel("info_begin", Unit->getID()); + // Emit size of content not including length itself + unsigned ContentSize = Die->getSize() + + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int32_t); // FIXME - extra pad for gdb bug. + + Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info"); + Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF version number"); + EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); + Asm->EOL("Offset Into Abbrev. Section"); + Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + + EmitDIE(Die); + // FIXME - extra padding for gdb bug. + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); + EmitLabel("info_end", Unit->getID()); + + Asm->EOL(); + } + void EmitDebugInfo() { // Start debug info section. Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; - DIE *Die = Unit->getDie(); - // Emit the compile units header. - EmitLabel("info_begin", Unit->getID()); - // Emit size of content not including length itself - unsigned ContentSize = Die->getSize() + - sizeof(int16_t) + // DWARF version number - sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t) + // Pointer Size (in bytes) - sizeof(int32_t); // FIXME - extra pad for gdb bug. - - Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info"); - Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF version number"); - EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false); - Asm->EOL("Offset Into Abbrev. Section"); - Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); - - EmitDIE(Die); - // FIXME - extra padding for gdb bug. - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB"); - EmitLabel("info_end", Unit->getID()); - - Asm->EOL(); + if (MainCU) { + EmitDebugInfoPerCU(MainCU); + return; } + + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) + EmitDebugInfoPerCU(CompileUnits[i]); } /// EmitAbbreviations - Emit the abbreviation section. @@ -2462,19 +2456,19 @@ private: Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count"); // Emit directories. - for (unsigned DirectoryID = 1, NDID = Directories.size(); - DirectoryID <= NDID; ++DirectoryID) { - Asm->EmitString(Directories[DirectoryID]); Asm->EOL("Directory"); + for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) { + Asm->EmitString(getSourceDirectoryName(DI)); + Asm->EOL("Directory"); } Asm->EmitInt8(0); Asm->EOL("End of directories"); // Emit files. - for (unsigned SourceID = 1, NSID = SrcFiles.size(); - SourceID <= NSID; ++SourceID) { - const SrcFileInfo &SourceFile = SrcFiles[SourceID]; - Asm->EmitString(SourceFile.getName()); + for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) { + // Remember source id starts at 1. + std::pair Id = getSourceDirectoryAndFileIds(SI); + Asm->EmitString(getSourceFileName(Id.second)); Asm->EOL("Source"); - Asm->EmitULEB128Bytes(SourceFile.getDirectoryID()); + Asm->EmitULEB128Bytes(Id.first); Asm->EOL("Directory #"); Asm->EmitULEB128Bytes(0); Asm->EOL("Mod date"); @@ -2494,7 +2488,8 @@ private: if (VerboseAsm) { const Section* S = SectionMap[j + 1]; - Asm->EOL(std::string("Section ") + S->getName()); + O << '\t' << TAI->getCommentString() << " Section" + << S->getName() << '\n'; } else Asm->EOL(); @@ -2508,16 +2503,16 @@ private: unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID()); if (!LabelID) continue; - unsigned SourceID = LineInfo.getSourceID(); - const SrcFileInfo &SourceFile = SrcFiles[SourceID]; - unsigned DirectoryID = SourceFile.getDirectoryID(); - if (VerboseAsm) - Asm->EOL(Directories[DirectoryID] - + SourceFile.getName() - + ":" - + utostr_32(LineInfo.getLine())); - else + if (!VerboseAsm) Asm->EOL(); + else { + std::pair SourceID = + getSourceDirectoryAndFileIds(LineInfo.getSourceID()); + O << '\t' << TAI->getCommentString() << ' ' + << getSourceDirectoryName(SourceID.first) << ' ' + << getSourceFileName(SourceID.second) + <<" :" << utostr_32(LineInfo.getLine()) << '\n'; + } // Define the line address. Asm->EmitInt8(0); Asm->EOL("Extended Op"); @@ -2649,49 +2644,52 @@ private: Asm->EOL(); } - /// EmitDebugPubNames - Emit visible names into a debug pubnames section. - /// - void EmitDebugPubNames() { - // Start the dwarf pubnames section. - Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); - - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; - - EmitDifference("pubnames_end", Unit->getID(), - "pubnames_begin", Unit->getID(), true); - Asm->EOL("Length of Public Names Info"); + 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()); + EmitLabel("pubnames_begin", Unit->getID()); - Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF Version"); + 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); - Asm->EOL("Compilation Unit Length"); + EmitSectionOffset("info_begin", "section_info", + Unit->getID(), 0, true, false); + Asm->EOL("Offset of Compilation Unit Info"); - std::map &Globals = Unit->getGlobals(); + EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(), + true); + Asm->EOL("Compilation Unit Length"); - for (std::map::iterator GI = Globals.begin(), - GE = Globals.end(); - GI != GE; ++GI) { - const std::string &Name = GI->first; - DIE * Entity = GI->second; + std::map &Globals = Unit->getGlobals(); + for (std::map::iterator GI = Globals.begin(), + GE = Globals.end(); GI != GE; ++GI) { + const std::string &Name = GI->first; + DIE * Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); - Asm->EmitString(Name); Asm->EOL("External Name"); - } + Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset"); + Asm->EmitString(Name); Asm->EOL("External Name"); + } - Asm->EmitInt32(0); Asm->EOL("End Mark"); - EmitLabel("pubnames_end", Unit->getID()); + Asm->EmitInt32(0); Asm->EOL("End Mark"); + EmitLabel("pubnames_end", Unit->getID()); - Asm->EOL(); + Asm->EOL(); + } + + /// EmitDebugPubNames - Emit visible names into a debug pubnames section. + /// + void EmitDebugPubNames() { + // Start the dwarf pubnames section. + Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); + + if (MainCU) { + EmitDebugPubNamesPerCU(MainCU); + return; } + + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) + EmitDebugPubNamesPerCU(CompileUnits[i]); } /// EmitDebugStr - Emit visible names into a debug str section. @@ -2781,98 +2779,202 @@ private: } } + /// 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; + } + + void ConstructCompileUnit(GlobalVariable *GV) { + DICompileUnit DIUnit(GV); + std::string Dir, FN, Prod; + unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir), + DIUnit.getFilename(FN)); + + 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() { - std::string CUName = "llvm.dbg.compile_units"; - std::vector Result; - getGlobalVariablesUsing(*M, CUName, Result); - for (std::vector::iterator RI = Result.begin(), - RE = Result.end(); RI != RE; ++RI) { - DICompileUnit DIUnit(*RI); - unsigned ID = RecordSource(DIUnit.getDirectory(), - DIUnit.getFilename()); - - DIE *Die = new DIE(DW_TAG_compile_unit); - AddSectionOffset(Die, DW_AT_stmt_list, DW_FORM_data4, - DWLabel("section_line", 0), DWLabel("section_line", 0), - false); - AddString(Die, DW_AT_producer, DW_FORM_string, DIUnit.getProducer()); - AddUInt(Die, DW_AT_language, DW_FORM_data1, DIUnit.getLanguage()); - AddString(Die, DW_AT_name, DW_FORM_string, DIUnit.getFilename()); - if (!DIUnit.getDirectory().empty()) - AddString(Die, DW_AT_comp_dir, DW_FORM_string, DIUnit.getDirectory()); - if (DIUnit.isOptimized()) - AddUInt(Die, DW_AT_APPLE_optimized, DW_FORM_flag, 1); - const std::string &Flags = DIUnit.getFlags(); - if (!Flags.empty()) - AddString(Die, DW_AT_APPLE_flags, DW_FORM_string, Flags); - - CompileUnit *Unit = new CompileUnit(ID, Die); - DW_CUs[DIUnit.getGV()] = Unit; - } + 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); + } + } + + bool ConstructGlobalVariableDIE(GlobalVariable *GV) { + DIGlobalVariable DI_GV(GV); + CompileUnit *DW_Unit = MainCU; + if (!DW_Unit) + DW_Unit = FindCompileUnit(DI_GV.getCompileUnit()); + + // 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. - void ConstructGlobalVariableDIEs() { - std::string GVName = "llvm.dbg.global_variables"; - std::vector Result; - getGlobalVariablesUsing(*M, GVName, Result); - for (std::vector::iterator GVI = Result.begin(), - GVE = Result.end(); GVI != GVE; ++GVI) { - DIGlobalVariable DI_GV(*GVI); - CompileUnit *DW_Unit = FindCompileUnit(DI_GV.getCompileUnit()); - - // Check for pre-existence. - DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV()); - if (Slot) continue; - - DIE *VariableDie = 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. - DW_Unit->AddGlobal(DI_GV.getName(), VariableDie); - } + /// 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. - void ConstructSubprograms() { - - std::string SPName = "llvm.dbg.subprograms"; - std::vector Result; - getGlobalVariablesUsing(*M, SPName, Result); - for (std::vector::iterator RI = Result.begin(), - RE = Result.end(); RI != RE; ++RI) { - - DISubprogram SP(*RI); - CompileUnit *Unit = FindCompileUnit(SP.getCompileUnit()); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(SP.getGV()); - if (Slot) continue; - - DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP); - - //Add to map. - Slot = SubprogramDie; - //Add to context owner. - Unit->getDie()->AddChild(SubprogramDie); - //Expose as global. - Unit->AddGlobal(SP.getName(), SubprogramDie); - } + /// 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: @@ -2880,62 +2982,85 @@ public: // Main entry points. // DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) - : Dwarf(OS, A, T, "dbg") - , AbbreviationsSet(InitAbbreviationsSetSize) - , Abbreviations() - , ValuesSet(InitValuesSetSize) - , Values() - , StringPool() - , SectionMap() - , SectionSourceLines() - , didInitial(false) - , shouldEmit(false) - , RootDbgScope(NULL) - { + : Dwarf(OS, A, T, "dbg"), MainCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), + ValuesSet(InitValuesSetSize), Values(), StringPool(), SectionMap(), + SectionSourceLines(), didInitial(false), shouldEmit(false), + RootDbgScope(0), DebugTimer(0) { + if (TimePassesIsEnabled) + DebugTimer = new Timer("Dwarf Debug Writer", + getDwarfTimerGroup()); } virtual ~DwarfDebug() { for (unsigned j = 0, M = Values.size(); j < M; ++j) delete Values[j]; + + delete DebugTimer; } + /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should + /// be emitted. + bool ShouldEmitDwarfDebug() const { return shouldEmit; } + /// SetDebugInfo - Create global DIEs and emit initial debug info sections. /// This is inovked by the target AsmPrinter. void SetDebugInfo(MachineModuleInfo *mmi) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); - // Create all the compile unit DIEs. - ConstructCompileUnits(); + // Create all the compile unit DIEs. + ConstructCompileUnits(); - if (DW_CUs.empty()) - return; + if (CompileUnits.empty()) { + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); - MMI = mmi; - shouldEmit = true; - MMI->setDebugInfoAvailability(true); + return; + } - // Create DIEs for each of the externally visible global variables. - ConstructGlobalVariableDIEs(); + // Create DIEs for each of the externally visible global variables. + bool globalDIEs = ConstructGlobalVariableDIEs(); - // Create DIEs for each of the externally visible subprograms. - ConstructSubprograms(); + // Create DIEs for each of the externally visible subprograms. + bool subprogramDIEs = ConstructSubprograms(); - // Prime section data. - SectionMap.insert(TAI->getTextSection()); + // 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(); - // Print out .file directives to specify files for .loc directives. These - // are printed out early so that they precede any .loc directives. - if (TAI->hasDotLocAndDotFile()) { - for (unsigned i = 1, e = SrcFiles.size(); i <= e; ++i) { - sys::Path FullPath(Directories[SrcFiles[i].getDirectoryID()]); - bool AppendOk = FullPath.appendComponent(SrcFiles[i].getName()); - assert(AppendOk && "Could not append filename to directory!"); - AppendOk = false; - Asm->EmitFile(i, FullPath.toString()); - Asm->EOL(); - } + 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(); - // Emit initial sections - EmitInitial(); + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// BeginModule - Emit all Dwarf sections that should come prior to the @@ -2947,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()); @@ -2998,6 +3127,9 @@ public: // Emit info into a debug macinfo section. EmitDebugMacInfo(); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// BeginFunction - Gather pre-function debug information. Assumes being @@ -3005,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); @@ -3019,12 +3154,18 @@ public: const SrcLineInfo &LineInfo = Lines[0]; Asm->printLabel(LineInfo.getLabelID()); } + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } /// EndFunction - Gather and emit post-function debug information. /// void EndFunction(MachineFunction *MF) { - if (!ShouldEmitDwarf()) return; + if (!ShouldEmitDwarfDebug()) return; + + if (TimePassesIsEnabled) + DebugTimer->startTimer(); // Define end label for subprogram. EmitLabel("func_end", SubprogramCount); @@ -3063,14 +3204,15 @@ public: DbgScopeMap.clear(); RootDbgScope = NULL; } + Lines.clear(); - } -public: + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + } /// ValidDebugInfo - Return true if V represents valid debug info value. bool ValidDebugInfo(Value *V) { - if (!V) return false; @@ -3080,32 +3222,42 @@ public: GlobalVariable *GV = getGlobalVariable(V); if (!GV) return false; - - if (GV->getLinkage() != GlobalValue::InternalLinkage - && GV->getLinkage() != GlobalValue::LinkOnceLinkage) + + 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 (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"); + assert(DIVariable(GV).Verify() && "Invalid DebugInfo value"); break; case DW_TAG_compile_unit: - assert (DICompileUnit(GV).Verify() && "Invalid DebugInfo value"); + assert(DICompileUnit(GV).Verify() && "Invalid DebugInfo value"); break; case DW_TAG_subprogram: - assert (DISubprogram(GV).Verify() && "Invalid DebugInfo value"); + assert(DISubprogram(GV).Verify() && "Invalid DebugInfo value"); break; default: break; } + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return true; } @@ -3113,10 +3265,17 @@ public: /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. unsigned RecordSourceLine(Value *V, unsigned Line, unsigned Col) { - CompileUnit *Unit = DW_CUs[V]; - assert (Unit && "Unable to find CompileUnit"); + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + CompileUnit *Unit = CompileUnitMap[V]; + assert(Unit && "Unable to find CompileUnit"); unsigned ID = MMI->NextLabelID(); Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID)); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } @@ -3124,46 +3283,80 @@ public: /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. unsigned RecordSourceLine(unsigned Line, unsigned Col, unsigned Src) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + unsigned ID = MMI->NextLabelID(); Lines.push_back(SrcLineInfo(Line, Col, Src, ID)); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } - unsigned getRecordSourceLineCount() { + /// getRecordSourceLineCount - Return the number of source lines in the debug + /// info. + unsigned getRecordSourceLineCount() const { return Lines.size(); } - /// RecordSource - Register a source file with debug info. Returns an source - /// ID. - unsigned RecordSource(const std::string &Directory, - const std::string &File) { - unsigned DID = Directories.insert(Directory); - return SrcFiles.insert(SrcFileInfo(DID,File)); + /// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be + /// timed. Look up the source id with the given directory and source file + /// names. If none currently exists, create a new id and insert it in the + /// SourceIds map. This can update DirectoryNames and SourceFileNames maps as + /// well. + unsigned getOrCreateSourceID(const std::string &DirName, + const std::string &FileName) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + unsigned SrcId = GetOrCreateSourceID(DirName, FileName); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return SrcId; } /// RecordRegionStart - Indicate the start of a region. - /// unsigned RecordRegionStart(GlobalVariable *V) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + DbgScope *Scope = getOrCreateScope(V); unsigned ID = MMI->NextLabelID(); if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } /// RecordRegionEnd - Indicate the end of a region. - /// unsigned RecordRegionEnd(GlobalVariable *V) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + DbgScope *Scope = getOrCreateScope(V); unsigned ID = MMI->NextLabelID(); Scope->setEndLabelID(ID); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + return ID; } /// RecordVariable - Indicate the declaration of a local variable. - /// void RecordVariable(GlobalVariable *GV, unsigned FrameIndex) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + DIDescriptor Desc(GV); DbgScope *Scope = NULL; + if (Desc.getTag() == DW_TAG_variable) { // GV is a global variable. DIGlobalVariable DG(GV); @@ -3173,9 +3366,13 @@ public: DIVariable DV(GV); Scope = getOrCreateScope(DV.getContext().getGV()); } - assert (Scope && "Unable to find variable' scope"); + + assert(Scope && "Unable to find variable' scope"); DbgVariable *DV = new DbgVariable(DIVariable(GV), FrameIndex); Scope->AddVariable(DV); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); } }; @@ -3183,8 +3380,6 @@ public: /// DwarfException - Emits Dwarf exception handling directives. /// class DwarfException : public Dwarf { - -private: struct FunctionEHFrameInfo { std::string FnName; unsigned Number; @@ -3220,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) { @@ -3331,8 +3529,10 @@ private: } // 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"; @@ -3343,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())) { @@ -3828,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. @@ -3852,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; @@ -3884,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(); @@ -3898,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(); } }; @@ -4016,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); } //===----------------------------------------------------------------------===// @@ -4227,8 +4452,8 @@ void DIE::dump() { /// DwarfWriter Implementation /// -DwarfWriter::DwarfWriter() : ImmutablePass(&ID), DD(NULL), DE(NULL) { -} +DwarfWriter::DwarfWriter() + : ImmutablePass(&ID), DD(0), DE(0) {} DwarfWriter::~DwarfWriter() { delete DE; @@ -4287,11 +4512,13 @@ unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col, return DD->RecordSourceLine(Line, Col, Src); } -/// RecordSource - Register a source file with debug info. Returns an source -/// ID. -unsigned DwarfWriter::RecordSource(const std::string &Dir, - const std::string &File) { - return DD->RecordSource(Dir, File); +/// getOrCreateSourceID - Look up the source id with the given directory and +/// source file names. If none currently exists, create a new id and insert it +/// in the SourceIds map. This can update DirectoryNames and SourceFileNames maps +/// as well. +unsigned DwarfWriter::getOrCreateSourceID(const std::string &DirName, + const std::string &FileName) { + return DD->getOrCreateSourceID(DirName, FileName); } /// RecordRegionStart - Indicate the start of a region. @@ -4315,3 +4542,8 @@ 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(); +}