X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfWriter.cpp;h=c0b0672f02991b5dc44e98d97a378d02ffb6940d;hb=b9dcef2a00f1ac35442393c951c21272527c8625;hp=9f94a2b79efeb9553613f74a2ec92ced96a16946;hpb=f3ee51441909cf1accfcce4c9b5b9f851e2c07b6;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 9f94a2b79ef..c0b0672f029 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/UniqueVector.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -53,9 +54,9 @@ namespace llvm { /// Configuration values for initial hash set sizes (log2). /// -static const unsigned InitDiesSetSize = 9; // 512 -static const unsigned InitAbbreviationsSetSize = 9; // 512 -static const unsigned InitValuesSetSize = 9; // 512 +static const unsigned InitDiesSetSize = 9; // log2(512) +static const unsigned InitAbbreviationsSetSize = 9; // log2(512) +static const unsigned InitValuesSetSize = 9; // log2(512) //===----------------------------------------------------------------------===// /// Forward declarations. @@ -66,24 +67,24 @@ class DIEValue; //===----------------------------------------------------------------------===// /// Utility routines. /// -/// getGlobalVariablesUsing - Return all of the GlobalVariables which have the -/// specified value in their initializer somewhere. +/// 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. + // 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. + // 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 + // 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. +/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the +/// named GlobalVariable. static void getGlobalVariablesUsing(Module &M, const std::string &RootName, std::vector &Result) { @@ -91,15 +92,34 @@ getGlobalVariablesUsing(Module &M, const std::string &RootName, FieldTypes.push_back(Type::Int32Ty); FieldTypes.push_back(Type::Int32Ty); - // Get the GlobalVariable root. + // Get the GlobalVariable root. GlobalVariable *UseRoot = M.getGlobalVariable(RootName, StructType::get(FieldTypes)); - // If present and linkonce then scan for users. + // 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) { + 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, @@ -749,10 +769,6 @@ public: /// with a source file. class CompileUnit { private: - /// Desc - Compile unit debug descriptor. - /// - CompileUnitDesc *Desc; - /// ID - File identifier for source. /// unsigned ID; @@ -761,15 +777,13 @@ private: /// DIE *Die; - /// DescToDieMap - Tracks the mapping of unit level debug informaton - /// descriptors to debug information entries. - std::map DescToDieMap; - DenseMap GVToDieMap; + /// GVToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + std::map GVToDieMap; - /// DescToDIEntryMap - Tracks the mapping of unit level debug informaton + /// GVToDIEntryMap - Tracks the mapping of unit level debug informaton /// descriptors to debug information entries using a DIEntry proxy. - std::map DescToDIEntryMap; - DenseMap GVToDIEntryMap; + std::map GVToDIEntryMap; /// Globals - A map of globally visible named entities for this unit. /// @@ -779,38 +793,17 @@ private: /// FoldingSet DiesSet; - /// Dies - List of all dies in the compile unit. - /// - std::vector Dies; - public: CompileUnit(unsigned I, DIE *D) - : ID(I), Die(D), DescToDieMap(), GVToDieMap(), DescToDIEntryMap(), - GVToDIEntryMap(), Globals(), DiesSet(InitDiesSetSize), Dies() - {} - - CompileUnit(CompileUnitDesc *CUD, unsigned I, DIE *D) - : Desc(CUD) - , ID(I) - , Die(D) - , DescToDieMap() - , GVToDieMap() - , DescToDIEntryMap() - , GVToDIEntryMap() - , Globals() - , DiesSet(InitDiesSetSize) - , Dies() + : ID(I), Die(D), GVToDieMap(), + GVToDIEntryMap(), Globals(), DiesSet(InitDiesSetSize) {} ~CompileUnit() { delete Die; - - for (unsigned i = 0, N = Dies.size(); i < N; ++i) - delete Dies[i]; } // Accessors. - CompileUnitDesc *getDesc() const { return Desc; } unsigned getID() const { return ID; } DIE* getDie() const { return Die; } std::map &getGlobals() { return Globals; } @@ -828,19 +821,13 @@ public: } /// getDieMapSlotFor - Returns the debug information entry map slot for the - /// specified debug descriptor. - DIE *&getDieMapSlotFor(DebugInfoDesc *DID) { - return DescToDieMap[DID]; - } + /// specified debug variable. DIE *&getDieMapSlotFor(GlobalVariable *GV) { return GVToDieMap[GV]; } /// getDIEntrySlotFor - Returns the debug information entry proxy slot for the - /// specified debug descriptor. - DIEntry *&getDIEntrySlotFor(DebugInfoDesc *DID) { - return DescToDIEntryMap[DID]; - } + /// specified debug variable. DIEntry *&getDIEntrySlotFor(GlobalVariable *GV) { return GVToDIEntryMap[GV]; } @@ -868,9 +855,7 @@ public: /// Dwarf - Emits general Dwarf directives. /// class Dwarf { - protected: - //===--------------------------------------------------------------------===// // Core attributes used by the Dwarf writer. // @@ -931,7 +916,6 @@ protected: } public: - //===--------------------------------------------------------------------===// // Accessors. // @@ -1179,7 +1163,7 @@ class SrcLineInfo { unsigned LabelID; // Label in code ID number. public: SrcLineInfo(unsigned L, unsigned C, unsigned S, unsigned I) - : Line(L), Column(C), SourceID(S), LabelID(I) {} + : Line(L), Column(C), SourceID(S), LabelID(I) {} // Accessors unsigned getLine() const { return Line; } @@ -1188,7 +1172,6 @@ public: unsigned getLabelID() const { return LabelID; } }; - //===----------------------------------------------------------------------===// /// SrcFileInfo - This class is used to track source information. /// @@ -1204,7 +1187,7 @@ public: /// operator== - Used by UniqueVector to locate entry. /// - bool operator==(const SourceFileInfo &SI) const { + bool operator==(const SrcFileInfo &SI) const { return getDirectoryID() == SI.getDirectoryID() && getName() == SI.getName(); } @@ -1220,15 +1203,13 @@ public: /// DbgVariable - This class is used to track local variable information. /// class DbgVariable { -private: - DIVariable *Var; // Variable Descriptor. + DIVariable Var; // Variable Descriptor. unsigned FrameIndex; // Variable frame index. - public: - DbgVariable(DIVariable *V, unsigned I) : Var(V), FrameIndex(I) {} + DbgVariable(DIVariable V, unsigned I) : Var(V), FrameIndex(I) {} // Accessors. - DIVariable *getVariable() const { return Var; } + DIVariable getVariable() const { return Var; } unsigned getFrameIndex() const { return FrameIndex; } }; @@ -1236,17 +1217,15 @@ public: /// DbgScope - This class is used to track scope information. /// class DbgScope { -private: DbgScope *Parent; // Parent to this scope. - DIDescriptor *Desc; // Debug info descriptor for scope. + DIDescriptor Desc; // Debug info descriptor for scope. // Either subprogram or block. unsigned StartLabelID; // Label ID of the beginning of scope. unsigned EndLabelID; // Label ID of the end of scope. - SmallVector Scopes; // Scopes defined in scope. + SmallVector Scopes; // Scopes defined in scope. SmallVector Variables;// Variables declared in scope. - public: - DbgScope(DbgScope *P, DIDescriptor *D) + DbgScope(DbgScope *P, DIDescriptor D) : Parent(P), Desc(D), StartLabelID(0), EndLabelID(0), Scopes(), Variables() {} ~DbgScope() { @@ -1255,8 +1234,8 @@ public: } // Accessors. - DbgScope *getParent() const { return Parent; } - DIDescriptor *getDesc() const { return Desc; } + DbgScope *getParent() const { return Parent; } + DIDescriptor getDesc() const { return Desc; } unsigned getStartLabelID() const { return StartLabelID; } unsigned getEndLabelID() const { return EndLabelID; } SmallVector &getScopes() { return Scopes; } @@ -1277,17 +1256,17 @@ public: /// DwarfDebug - Emits Dwarf debug directives. /// class DwarfDebug : public Dwarf { - -private: //===--------------------------------------------------------------------===// // Attributes used to construct specific Dwarf sections. // - /// CompileUnits - All the compile units involved in this build. The index + /// DW_CUs - All the compile units involved in this build. The index /// of each entry in this vector corresponds to the sources in MMI. - std::vector CompileUnits; DenseMap DW_CUs; + /// 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. /// FoldingSet AbbreviationsSet; @@ -1296,17 +1275,17 @@ private: /// std::vector Abbreviations; - /// ValuesSet - Used to uniquely define values. - /// - // Directories - Uniquing vector for directories. + /// Directories - Uniquing vector for directories. UniqueVector Directories; - // SourceFiles - Uniquing vector for source files. + /// SourceFiles - Uniquing vector for source files. UniqueVector SrcFiles; - // Lines - List of of source line correspondence. + /// Lines - List of of source line correspondence. std::vector Lines; + /// ValuesSet - Used to uniquely define values. + /// FoldingSet ValuesSet; /// Values - A list of all the unique values in use. @@ -1317,10 +1296,6 @@ private: /// UniqueVector StringPool; - /// UnitMap - Map debug information descriptor to compile unit. - /// - std::map DescToUnitMap; - /// SectionMap - Provides a unique id per text section. /// UniqueVector SectionMap; @@ -1337,7 +1312,7 @@ private: /// bool shouldEmit; - // RootScope - Top level scope for the current function. + // RootDbgScope - Top level scope for the current function. // DbgScope *RootDbgScope; @@ -1574,66 +1549,34 @@ private: /// AddSourceLine - Add location information to specified debug information /// entry. - void AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line) { - if (File && Line) { - CompileUnit *FileUnit = FindCompileUnit(File); - unsigned FileID = FileUnit->getID(); - AddUInt(Die, DW_AT_decl_file, 0, FileID); - AddUInt(Die, DW_AT_decl_line, 0, Line); - } - } - - /// AddSourceLine - Add location information to specified debug information - /// entry. - void AddSourceLine(DIE *Die, DIVariable *V) { + void AddSourceLine(DIE *Die, const DIVariable *V) { unsigned FileID = 0; unsigned Line = V->getLineNumber(); - if (V->getVersion() < DIDescriptor::Version7) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(V->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIVariable - // directly. - unsigned DID = Directories.idFor(V->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, V->getFilename())); - } + CompileUnit *Unit = FindCompileUnit(V->getCompileUnit()); + FileID = Unit->getID(); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } /// AddSourceLine - Add location information to specified debug information /// entry. - void AddSourceLine(DIE *Die, DIGlobal *G) { + void AddSourceLine(DIE *Die, const DIGlobal *G) { unsigned FileID = 0; unsigned Line = G->getLineNumber(); - if (G->getVersion() < DIDescriptor::Version7) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIGlobal - // directly. - unsigned DID = Directories.idFor(G->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, G->getFilename())); - } + CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); + FileID = Unit->getID(); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } - void AddSourceLine(DIE *Die, DIType *G) { + void AddSourceLine(DIE *Die, const DIType *Ty) { unsigned FileID = 0; - unsigned Line = G->getLineNumber(); - if (G->getVersion() < DIDescriptor::Version7) { - // Version6 or earlier. Use compile unit info to get file id. - CompileUnit *Unit = FindCompileUnit(G->getCompileUnit()); - FileID = Unit->getID(); - } else { - // Version7 or newer, use filename and directory info from DIGlobal - // directly. - unsigned DID = Directories.idFor(G->getDirectory()); - FileID = SrcFiles.idFor(SrcFileInfo(DID, G->getFilename())); - } + unsigned Line = Ty->getLineNumber(); + DICompileUnit CU = Ty->getCompileUnit(); + if (CU.isNull()) + return; + CompileUnit *Unit = FindCompileUnit(CU); + FileID = Unit->getID(); AddUInt(Die, DW_AT_decl_file, 0, FileID); AddUInt(Die, DW_AT_decl_line, 0, Line); } @@ -1665,76 +1608,10 @@ private: AddBlock(Die, Attribute, 0, Block); } - /// AddBasicType - Add a new basic type attribute to the specified entity. - /// - void AddBasicType(DIE *Entity, CompileUnit *Unit, - const std::string &Name, - unsigned Encoding, unsigned Size) { - - DIE Buffer(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_byte_size, 0, Size); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, Encoding); - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - DIE *BasicTypeDie = Unit->AddDie(Buffer); - AddDIEntry(Entity, DW_AT_type, DW_FORM_ref4, BasicTypeDie); - } - - /// AddPointerType - Add a new pointer type attribute to the specified entity. - /// - void AddPointerType(DIE *Entity, CompileUnit *Unit, const std::string &Name) { - DIE Buffer(DW_TAG_pointer_type); - AddUInt(&Buffer, DW_AT_byte_size, 0, TD->getPointerSize()); - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - DIE *PointerTypeDie = Unit->AddDie(Buffer); - AddDIEntry(Entity, DW_AT_type, DW_FORM_ref4, PointerTypeDie); - } - - /// AddType - Add a new type attribute to the specified entity. - /// - void AddType(DIE *Entity, TypeDesc *TyDesc, CompileUnit *Unit) { - if (!TyDesc) { - AddBasicType(Entity, Unit, "", DW_ATE_signed, sizeof(int32_t)); - } else { - // Check for pre-existence. - DIEntry *&Slot = Unit->getDIEntrySlotFor(TyDesc); - - // If it exists then use the existing value. - if (Slot) { - Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); - return; - } - - if (SubprogramDesc *SubprogramTy = dyn_cast(TyDesc)) { - // FIXME - Not sure why programs and variables are coming through here. - // Short cut for handling subprogram types (not really a TyDesc.) - AddPointerType(Entity, Unit, SubprogramTy->getName()); - } else if (GlobalVariableDesc *GlobalTy = - dyn_cast(TyDesc)) { - // FIXME - Not sure why programs and variables are coming through here. - // Short cut for handling global variable types (not really a TyDesc.) - AddPointerType(Entity, Unit, GlobalTy->getName()); - } else { - // Set up proxy. - Slot = NewDIEntry(); - - // Construct type. - DIE Buffer(DW_TAG_base_type); - ConstructType(Buffer, TyDesc, Unit); - - // Add debug information entry to entity and unit. - DIE *Die = Unit->AddDie(Buffer); - SetDIEntry(Slot, Die); - Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); - } - } - } - /// AddType - Add a new type attribute to the specified entity. void AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { - if (Ty.isNull()) { - AddBasicType(Entity, DW_Unit, "", DW_ATE_signed, sizeof(int32_t)); + if (Ty.isNull()) return; - } // Check for pre-existence. DIEntry *&Slot = DW_Unit->getDIEntrySlotFor(Ty.getGV()); @@ -1749,48 +1626,63 @@ private: // Construct type. DIE Buffer(DW_TAG_base_type); - if (DIBasicType *BT = dyn_cast(&Ty)) - ConstructTypeDIE(DW_Unit, Buffer, BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - ConstructTypeDIE(DW_Unit, Buffer, DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - ConstructTypeDIE(DW_Unit, Buffer, CT); - - // Add debug information entry to entity and unit. - DIE *Die = DW_Unit->AddDie(Buffer); - SetDIEntry(Slot, Die); + if (Ty.isBasicType(Ty.getTag())) + ConstructTypeDIE(DW_Unit, Buffer, DIBasicType(Ty.getGV())); + else if (Ty.isDerivedType(Ty.getTag())) + ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getGV())); + else { + assert(Ty.isCompositeType(Ty.getTag()) && "Unknown kind of DIType"); + ConstructTypeDIE(DW_Unit, Buffer, DICompositeType(Ty.getGV())); + } + + // Add debug information entry to entity and appropriate context. + DIE *Die = NULL; + DIDescriptor Context = Ty.getContext(); + if (!Context.isNull()) + Die = DW_Unit->getDieMapSlotFor(Context.getGV()); + + if (Die) { + DIE *Child = new DIE(Buffer); + Die->AddChild(Child); + Buffer.Detach(); + SetDIEntry(Slot, Child); + } else { + Die = DW_Unit->AddDie(Buffer); + SetDIEntry(Slot, Die); + } + Entity->AddValue(DW_AT_type, DW_FORM_ref4, Slot); } /// ConstructTypeDIE - Construct basic type die from DIBasicType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DIBasicType *BTy) { + DIBasicType BTy) { // Get core information. - const std::string &Name = BTy->getName(); + const std::string &Name = BTy.getName(); Buffer.setTag(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BTy->getEncoding()); + AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BTy.getEncoding()); // Add name if not anonymous or intermediate type. if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - uint64_t Size = BTy->getSizeInBits() >> 3; + uint64_t Size = BTy.getSizeInBits() >> 3; AddUInt(&Buffer, DW_AT_byte_size, 0, Size); } /// ConstructTypeDIE - Construct derived type die from DIDerivedType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DIDerivedType *DTy) { + DIDerivedType DTy) { // Get core information. - const std::string &Name = DTy->getName(); - uint64_t Size = DTy->getSizeInBits() >> 3; - unsigned Tag = DTy->getTag(); + const std::string &Name = DTy.getName(); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); // FIXME - Workaround for templates. if (Tag == DW_TAG_inheritance) Tag = DW_TAG_reference_type; Buffer.setTag(Tag); // Map to main type, void will not have a type. - DIType FromTy = DTy->getTypeDerivedFrom(); + DIType FromTy = DTy.getTypeDerivedFrom(); AddType(DW_Unit, &Buffer, FromTy); // Add name if not anonymous or intermediate type. @@ -1802,55 +1694,50 @@ private: // Add source line info if available and TyDesc is not a forward // declaration. - // FIXME - Enable this. if (!DTy->isForwardDecl()) - // FIXME - Enable this. AddSourceLine(&Buffer, *DTy); + if (!DTy.isForwardDecl()) + AddSourceLine(&Buffer, &DTy); } /// ConstructTypeDIE - Construct type DIE from DICompositeType. void ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DICompositeType *CTy) { + DICompositeType CTy) { - // Get core information. - const std::string &Name = CTy->getName(); - uint64_t Size = CTy->getSizeInBits() >> 3; - unsigned Tag = CTy->getTag(); + // Get core information. + const std::string &Name = CTy.getName(); + 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); + ConstructArrayTypeDIE(DW_Unit, Buffer, &CTy); + break; + case DW_TAG_enumeration_type: + { + DIArray Elements = CTy.getTypeArray(); + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIEnumerator Enum(Elements.getElement(i).getGV()); + ElemDie = ConstructEnumTypeDIE(DW_Unit, &Enum); + Buffer.AddChild(ElemDie); + } + } break; - //FIXME - Enable this. - // case DW_TAG_enumeration_type: - // DIArray Elements = CTy->getTypeArray(); - // // Add enumerators to enumeration type. - // for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) - // ConstructEnumTypeDIE(Buffer, &Elements.getElement(i)); - // break; case DW_TAG_subroutine_type: { // Add prototype flag. AddUInt(&Buffer, DW_AT_prototyped, DW_FORM_flag, 1); - DIArray Elements = CTy->getTypeArray(); + DIArray Elements = CTy.getTypeArray(); // Add return type. DIDescriptor RTy = Elements.getElement(0); - if (DIBasicType *BT = dyn_cast(&RTy)) - AddType(DW_Unit, &Buffer, *BT); - else if (DIDerivedType *DT = dyn_cast(&RTy)) - AddType(DW_Unit, &Buffer, *DT); - else if (DICompositeType *CT = dyn_cast(&RTy)) - AddType(DW_Unit, &Buffer, *CT); - - //AddType(DW_Unit, &Buffer, Elements.getElement(0)); + AddType(DW_Unit, &Buffer, DIType(RTy.getGV())); + // Add arguments. for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(DW_TAG_formal_parameter); DIDescriptor Ty = Elements.getElement(i); - if (DIBasicType *BT = dyn_cast(&Ty)) - AddType(DW_Unit, &Buffer, *BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - AddType(DW_Unit, &Buffer, *DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - AddType(DW_Unit, &Buffer, *CT); + AddType(DW_Unit, Arg, DIType(Ty.getGV())); Buffer.AddChild(Arg); } } @@ -1859,16 +1746,26 @@ private: case DW_TAG_union_type: { // Add elements to structure type. - DIArray Elements = CTy->getTypeArray(); + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + if (Elements.isNull()) + break; + // Add elements to structure type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); - if (DISubprogram *SP = dyn_cast(&Element)) - ConstructFieldTypeDIE(DW_Unit, Buffer, SP); - else if (DIDerivedType *DT = dyn_cast(&Element)) - ConstructFieldTypeDIE(DW_Unit, Buffer, DT); - else if (DIGlobalVariable *GV = dyn_cast(&Element)) - ConstructFieldTypeDIE(DW_Unit, Buffer, GV); + DIE *ElemDie = NULL; + if (Element.getTag() == dwarf::DW_TAG_subprogram) + ElemDie = CreateSubprogramDIE(DW_Unit, + DISubprogram(Element.getGV())); + else if (Element.getTag() == dwarf::DW_TAG_variable) // ??? + ElemDie = CreateGlobalVariableDIE(DW_Unit, + DIGlobalVariable(Element.getGV())); + else + ElemDie = CreateMemberDIE(DW_Unit, + DIDerivedType(Element.getGV())); + Buffer.AddChild(ElemDie); } } break; @@ -1879,35 +1776,35 @@ private: // 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 { - // Add zero size even if it is not a forward declaration. - // FIXME - Enable this. - // if (!CTy->isDefinition()) - // AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1); - // else - // AddUInt(&Buffer, DW_AT_byte_size, 0, 0); + if (Tag == DW_TAG_enumeration_type || Tag == DW_TAG_structure_type + || Tag == DW_TAG_union_type) { + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + AddUInt(&Buffer, DW_AT_byte_size, 0, Size); + else { + // Add zero size if it is not a forward declaration. + if (CTy.isForwardDecl()) + AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1); + else + AddUInt(&Buffer, DW_AT_byte_size, 0, 0); + } + + // Add source line info if available. + if (!CTy.isForwardDecl()) + AddSourceLine(&Buffer, &CTy); } - - // Add source line info if available and TyDesc is not a forward - // declaration. - // FIXME - Enable this. - // if (CTy->isForwardDecl()) - // AddSourceLine(&Buffer, *CTy); } - // ConstructSubrangeDIE - Construct subrange DIE from DISubrange. - void ConstructSubrangeDIE (DIE &Buffer, DISubrange *SR, DIE *IndexTy) { - int64_t L = SR->getLo(); - int64_t H = SR->getHi(); + /// ConstructSubrangeDIE - Construct subrange DIE from DISubrange. + void ConstructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { + int64_t L = SR.getLo(); + int64_t H = SR.getHi(); DIE *DW_Subrange = new DIE(DW_TAG_subrange_type); if (L != H) { AddDIEntry(DW_Subrange, DW_AT_type, DW_FORM_ref4, IndexTy); if (L) - AddSInt(DW_Subrange, DW_AT_lower_bound, 0, L); - AddSInt(DW_Subrange, DW_AT_upper_bound, 0, H); + AddSInt(DW_Subrange, DW_AT_lower_bound, 0, L); + AddSInt(DW_Subrange, DW_AT_upper_bound, 0, H); } Buffer.AddChild(DW_Subrange); } @@ -1919,9 +1816,9 @@ private: if (CTy->getTag() == DW_TAG_vector_type) AddUInt(&Buffer, DW_AT_GNU_vector, DW_FORM_flag, 1); + // Emit derived type. + AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom()); DIArray Elements = CTy->getTypeArray(); - // FIXME - Enable this. - AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom()); // Construct an anonymous type for index type. DIE IdxBuffer(DW_TAG_base_type); @@ -1932,587 +1829,117 @@ private: // Add subranges to array type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); - if (DISubrange *SR = dyn_cast(&Element)) - ConstructSubrangeDIE(Buffer, SR, IndexTy); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + ConstructSubrangeDIE(Buffer, DISubrange(Element.getGV()), IndexTy); } } - /// ConstructEnumTypeDIE - Construct enum type DIE from - /// DIEnumerator. - void ConstructEnumTypeDIE(CompileUnit *DW_Unit, - DIE &Buffer, DIEnumerator *ETy) { + /// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator. + DIE *ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { DIE *Enumerator = new DIE(DW_TAG_enumerator); AddString(Enumerator, DW_AT_name, DW_FORM_string, ETy->getName()); int64_t Value = ETy->getEnumValue(); AddSInt(Enumerator, DW_AT_const_value, DW_FORM_sdata, Value); - Buffer.AddChild(Enumerator); + return Enumerator; } - /// ConstructFieldTypeDIE - Construct variable DIE for a struct field. - void ConstructFieldTypeDIE(CompileUnit *DW_Unit, - DIE &Buffer, DIGlobalVariable *V) { - - DIE *VariableDie = new DIE(DW_TAG_variable); - const std::string &LinkageName = V->getLinkageName(); - if (!LinkageName.empty()) - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - // FIXME - Enable this. AddSourceLine(VariableDie, V); - AddType(DW_Unit, VariableDie, V->getType()); - if (!V->isLocalToUnit()) - AddUInt(VariableDie, DW_AT_external, DW_FORM_flag, 1); - AddUInt(VariableDie, DW_AT_declaration, DW_FORM_flag, 1); - Buffer.AddChild(VariableDie); - } - - /// ConstructFieldTypeDIE - Construct subprogram DIE for a struct field. - void ConstructFieldTypeDIE(CompileUnit *DW_Unit, - DIE &Buffer, DISubprogram *SP, - bool IsConstructor = false) { - DIE *Method = new DIE(DW_TAG_subprogram); - AddString(Method, DW_AT_name, DW_FORM_string, SP->getName()); - const std::string &LinkageName = SP->getLinkageName(); + /// CreateGlobalVariableDIE - Create new DIE using GV. + DIE *CreateGlobalVariableDIE(CompileUnit *DW_Unit, const DIGlobalVariable &GV) + { + DIE *GVDie = new DIE(DW_TAG_variable); + AddString(GVDie, DW_AT_name, DW_FORM_string, GV.getName()); + const std::string &LinkageName = GV.getLinkageName(); if (!LinkageName.empty()) - AddString(Method, DW_AT_MIPS_linkage_name, DW_FORM_string, LinkageName); - // FIXME - Enable this. AddSourceLine(Method, SP); - - DICompositeType MTy = SP->getType(); - DIArray Args = MTy.getTypeArray(); - - // Add Return Type. - if (!IsConstructor) { - DIDescriptor Ty = Args.getElement(0); - if (DIBasicType *BT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *CT); - } - - // Add arguments. - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(DW_TAG_formal_parameter); - DIDescriptor Ty = Args.getElement(i); - if (DIBasicType *BT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *BT); - else if (DIDerivedType *DT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *DT); - else if (DICompositeType *CT = dyn_cast(&Ty)) - AddType(DW_Unit, Method, *CT); - AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); // ??? - Method->AddChild(Arg); - } - - if (!SP->isLocalToUnit()) - AddUInt(Method, DW_AT_external, DW_FORM_flag, 1); - Buffer.AddChild(Method); - } - - /// COnstructFieldTypeDIE - Construct derived type DIE for a struct field. - void ConstructFieldTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, - DIDerivedType *DTy) { - unsigned Tag = DTy->getTag(); - DIE *MemberDie = new DIE(Tag); - if (!DTy->getName().empty()) - AddString(MemberDie, DW_AT_name, DW_FORM_string, DTy->getName()); - // FIXME - Enable this. AddSourceLine(MemberDie, DTy); - - DIType FromTy = DTy->getTypeDerivedFrom(); - AddType(DW_Unit, MemberDie, FromTy); + 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(); + if (!Name.empty()) + AddString(MemberDie, DW_AT_name, DW_FORM_string, Name); - uint64_t Size = DTy->getSizeInBits(); - uint64_t Offset = DTy->getOffsetInBits(); + AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom()); - // FIXME Handle bitfields + AddSourceLine(MemberDie, &DT); - // Add size. - AddUInt(MemberDie, DW_AT_bit_size, 0, Size); - // Add computation for offset. + // FIXME _ Handle bitfields DIEBlock *Block = new DIEBlock(); AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst); - AddUInt(Block, 0, DW_FORM_udata, Offset >> 3); + AddUInt(Block, 0, DW_FORM_udata, DT.getOffsetInBits() >> 3); AddBlock(MemberDie, DW_AT_data_member_location, 0, Block); - // FIXME Handle DW_AT_accessibility. + if (DT.isProtected()) + AddUInt(MemberDie, DW_AT_accessibility, 0, DW_ACCESS_protected); + else if (DT.isPrivate()) + AddUInt(MemberDie, DW_AT_accessibility, 0, DW_ACCESS_private); - Buffer.AddChild(MemberDie); + return MemberDie; } - /// ConstructType - Adds all the required attributes to the type. - /// - void ConstructType(DIE &Buffer, TypeDesc *TyDesc, CompileUnit *Unit) { - // Get core information. - const std::string &Name = TyDesc->getName(); - uint64_t Size = TyDesc->getSize() >> 3; - - if (BasicTypeDesc *BasicTy = dyn_cast(TyDesc)) { - // Fundamental types like int, float, bool - Buffer.setTag(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BasicTy->getEncoding()); - } else if (DerivedTypeDesc *DerivedTy = dyn_cast(TyDesc)) { - // Fetch tag. - unsigned Tag = DerivedTy->getTag(); - // FIXME - Workaround for templates. - if (Tag == DW_TAG_inheritance) Tag = DW_TAG_reference_type; - // Pointers, typedefs et al. - Buffer.setTag(Tag); - // Map to main type, void will not have a type. - if (TypeDesc *FromTy = DerivedTy->getFromType()) - AddType(&Buffer, FromTy, Unit); - } else if (CompositeTypeDesc *CompTy = dyn_cast(TyDesc)){ - // Fetch tag. - unsigned Tag = CompTy->getTag(); - - // Set tag accordingly. - if (Tag == DW_TAG_vector_type) - Buffer.setTag(DW_TAG_array_type); - else - Buffer.setTag(Tag); - - std::vector &Elements = CompTy->getElements(); - - switch (Tag) { - case DW_TAG_vector_type: - AddUInt(&Buffer, DW_AT_GNU_vector, DW_FORM_flag, 1); - // Fall thru - case DW_TAG_array_type: { - // Add element type. - if (TypeDesc *FromTy = CompTy->getFromType()) - AddType(&Buffer, FromTy, Unit); - - // Don't emit size attribute. - Size = 0; - - // Construct an anonymous type for index type. - DIE Buffer(DW_TAG_base_type); - AddUInt(&Buffer, DW_AT_byte_size, 0, sizeof(int32_t)); - AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, DW_ATE_signed); - DIE *IndexTy = Unit->AddDie(Buffer); - - // Add subranges to array type. - for (unsigned i = 0, N = Elements.size(); i < N; ++i) { - SubrangeDesc *SRD = cast(Elements[i]); - int64_t Lo = SRD->getLo(); - int64_t Hi = SRD->getHi(); - DIE *Subrange = new DIE(DW_TAG_subrange_type); - - // If a range is available. - if (Lo != Hi) { - AddDIEntry(Subrange, DW_AT_type, DW_FORM_ref4, IndexTy); - // Only add low if non-zero. - if (Lo) AddSInt(Subrange, DW_AT_lower_bound, 0, Lo); - AddSInt(Subrange, DW_AT_upper_bound, 0, Hi); - } - - Buffer.AddChild(Subrange); - } - break; - } - case DW_TAG_structure_type: - case DW_TAG_union_type: { - // Add elements to structure type. - for (unsigned i = 0, N = Elements.size(); i < N; ++i) { - DebugInfoDesc *Element = Elements[i]; - - if (DerivedTypeDesc *MemberDesc = dyn_cast(Element)){ - // Add field or base class. - unsigned Tag = MemberDesc->getTag(); - - // Extract the basic information. - const std::string &Name = MemberDesc->getName(); - uint64_t Size = MemberDesc->getSize(); - uint64_t Align = MemberDesc->getAlign(); - uint64_t Offset = MemberDesc->getOffset(); - - // Construct member debug information entry. - DIE *Member = new DIE(Tag); - - // Add name if not "". - if (!Name.empty()) - AddString(Member, DW_AT_name, DW_FORM_string, Name); - - // Add location if available. - AddSourceLine(Member, MemberDesc->getFile(), MemberDesc->getLine()); - - // Most of the time the field info is the same as the members. - uint64_t FieldSize = Size; - uint64_t FieldAlign = Align; - uint64_t FieldOffset = Offset; - - // Set the member type. - TypeDesc *FromTy = MemberDesc->getFromType(); - AddType(Member, FromTy, Unit); - - // Walk up typedefs until a real size is found. - while (FromTy) { - if (FromTy->getTag() != DW_TAG_typedef) { - FieldSize = FromTy->getSize(); - FieldAlign = FromTy->getAlign(); - break; - } - - FromTy = cast(FromTy)->getFromType(); - } - - // Unless we have a bit field. - if (Tag == DW_TAG_member && FieldSize != Size) { - // Construct the alignment mask. - uint64_t AlignMask = ~(FieldAlign - 1); - // Determine the high bit + 1 of the declared size. - uint64_t HiMark = (Offset + FieldSize) & AlignMask; - // Work backwards to determine the base offset of the field. - FieldOffset = HiMark - FieldSize; - // Now normalize offset to the field. - Offset -= FieldOffset; - - // Maybe we need to work from the other end. - if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size); - - // Add size and offset. - AddUInt(Member, DW_AT_byte_size, 0, FieldSize >> 3); - AddUInt(Member, DW_AT_bit_size, 0, Size); - AddUInt(Member, DW_AT_bit_offset, 0, Offset); - } - - // Add computation for offset. - DIEBlock *Block = new DIEBlock(); - AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst); - AddUInt(Block, 0, DW_FORM_udata, FieldOffset >> 3); - AddBlock(Member, DW_AT_data_member_location, 0, Block); - - // Add accessibility (public default unless is base class. - if (MemberDesc->isProtected()) { - AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_protected); - } else if (MemberDesc->isPrivate()) { - AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_private); - } else if (Tag == DW_TAG_inheritance) { - AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_public); - } - - Buffer.AddChild(Member); - } else if (GlobalVariableDesc *StaticDesc = - dyn_cast(Element)) { - // Add static member. - - // Construct member debug information entry. - DIE *Static = new DIE(DW_TAG_variable); - - // Add name and mangled name. - const std::string &Name = StaticDesc->getName(); - const std::string &LinkageName = StaticDesc->getLinkageName(); - AddString(Static, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(Static, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - - // Add location. - AddSourceLine(Static, StaticDesc->getFile(), StaticDesc->getLine()); - - // Add type. - if (TypeDesc *StaticTy = StaticDesc->getType()) - AddType(Static, StaticTy, Unit); - - // Add flags. - if (!StaticDesc->isStatic()) - AddUInt(Static, DW_AT_external, DW_FORM_flag, 1); - AddUInt(Static, DW_AT_declaration, DW_FORM_flag, 1); - - Buffer.AddChild(Static); - } else if (SubprogramDesc *MethodDesc = - dyn_cast(Element)) { - // Add member function. - - // Construct member debug information entry. - DIE *Method = new DIE(DW_TAG_subprogram); - - // Add name and mangled name. - const std::string &Name = MethodDesc->getName(); - const std::string &LinkageName = MethodDesc->getLinkageName(); - - AddString(Method, DW_AT_name, DW_FORM_string, Name); - bool IsCTor = TyDesc->getName() == Name; - - if (!LinkageName.empty()) { - AddString(Method, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - - // Add location. - AddSourceLine(Method, MethodDesc->getFile(), MethodDesc->getLine()); - - // Add type. - if (CompositeTypeDesc *MethodTy = - dyn_cast_or_null(MethodDesc->getType())) { - // Get argument information. - std::vector &Args = MethodTy->getElements(); - - // If not a ctor. - if (!IsCTor) { - // Add return type. - AddType(Method, dyn_cast(Args[0]), Unit); - } - - // Add arguments. - for (unsigned i = 1, N = Args.size(); i < N; ++i) { - DIE *Arg = new DIE(DW_TAG_formal_parameter); - AddType(Arg, cast(Args[i]), Unit); - AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); - Method->AddChild(Arg); - } - } - - // Add flags. - if (!MethodDesc->isStatic()) - AddUInt(Method, DW_AT_external, DW_FORM_flag, 1); - AddUInt(Method, DW_AT_declaration, DW_FORM_flag, 1); - - Buffer.AddChild(Method); - } - } - break; - } - case DW_TAG_enumeration_type: { - // Add enumerators to enumeration type. - for (unsigned i = 0, N = Elements.size(); i < N; ++i) { - EnumeratorDesc *ED = cast(Elements[i]); - const std::string &Name = ED->getName(); - int64_t Value = ED->getValue(); - DIE *Enumerator = new DIE(DW_TAG_enumerator); - AddString(Enumerator, DW_AT_name, DW_FORM_string, Name); - AddSInt(Enumerator, DW_AT_const_value, DW_FORM_sdata, Value); - Buffer.AddChild(Enumerator); - } - - 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); + /// CreateSubprogramDIE - Create new DIE using SP. + DIE *CreateSubprogramDIE(CompileUnit *DW_Unit, + 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(); + if (!LinkageName.empty()) + AddString(SPDie, DW_AT_MIPS_linkage_name, DW_FORM_string, + LinkageName); + AddSourceLine(SPDie, &SP); - // Add arguments. - for (unsigned i = 1, N = Elements.size(); i < N; ++i) { + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + + // Add Return Type. + if (!IsConstructor) + 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(Arg, cast(Elements[i]), Unit); - Buffer.AddChild(Arg); + AddType(DW_Unit, Arg, DIType(Args.getElement(i).getGV())); + AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1); // ??? + SPDie->AddChild(Arg); } - - break; - } - default: break; - } - } - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name); - - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - AddUInt(&Buffer, DW_AT_byte_size, 0, Size); - else if (isa(TyDesc)) { - // If TyDesc is a composite type, then add size even if it's zero unless - // it's a forward declaration. - if (TyDesc->isForwardDecl()) - AddUInt(&Buffer, DW_AT_declaration, DW_FORM_flag, 1); - else - AddUInt(&Buffer, DW_AT_byte_size, 0, 0); } - // Add source line info if available and TyDesc is not a forward - // declaration. - if (!TyDesc->isForwardDecl()) - AddSourceLine(&Buffer, TyDesc->getFile(), TyDesc->getLine()); + if (!SP.isLocalToUnit()) + AddUInt(SPDie, DW_AT_external, DW_FORM_flag, 1); + return SPDie; } - /// NewCompileUnit - Create new compile unit and it's debug information entry. + /// FindCompileUnit - Get the compile unit for the given descriptor. /// - 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; - } - - /// FindCompileUnit - Get the compile unit for the given descriptor. - /// CompileUnit *FindCompileUnit(DICompileUnit Unit) { CompileUnit *DW_Unit = DW_CUs[Unit.getGV()]; assert(DW_Unit && "Missing compile unit."); return DW_Unit; } - /// NewGlobalVariable - Add a new global variable DIE. - /// - DIE *NewGlobalVariable(GlobalVariableDesc *GVD) { - // Get the compile unit context. - CompileUnitDesc *UnitDesc = - static_cast(GVD->getContext()); - CompileUnit *Unit = GetBaseCompileUnit(); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(GVD); - if (Slot) return Slot; - - // Get the global variable itself. - GlobalVariable *GV = GVD->getGlobalVariable(); - - const std::string &Name = GVD->getName(); - const std::string &FullName = GVD->getFullName(); - const std::string &LinkageName = GVD->getLinkageName(); - // Create the global's variable DIE. - DIE *VariableDie = new DIE(DW_TAG_variable); - AddString(VariableDie, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - AddType(VariableDie, GVD->getType(), Unit); - if (!GVD->isStatic()) - AddUInt(VariableDie, DW_AT_external, DW_FORM_flag, 1); - - // Add source line info if available. - AddSourceLine(VariableDie, UnitDesc, GVD->getLine()); - - // Add address. - DIEBlock *Block = new DIEBlock(); - AddUInt(Block, 0, DW_FORM_data1, DW_OP_addr); - AddObjectLabel(Block, 0, DW_FORM_udata, Asm->getGlobalLinkName(GV)); - AddBlock(VariableDie, DW_AT_location, 0, Block); - - // Add to map. - Slot = VariableDie; - - // Add to context owner. - Unit->getDie()->AddChild(VariableDie); - - // Expose as global. - // FIXME - need to check external flag. - Unit->AddGlobal(FullName, VariableDie); - - return VariableDie; - } - - /// NewSubprogram - Add a new subprogram DIE. - /// - DIE *NewSubprogram(SubprogramDesc *SPD) { - // Get the compile unit context. - CompileUnitDesc *UnitDesc = - static_cast(SPD->getContext()); - CompileUnit *Unit = GetBaseCompileUnit(); - - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(SPD); - if (Slot) return Slot; - - // Gather the details (simplify add attribute code.) - const std::string &Name = SPD->getName(); - const std::string &FullName = SPD->getFullName(); - const std::string &LinkageName = SPD->getLinkageName(); - - DIE *SubprogramDie = new DIE(DW_TAG_subprogram); - AddString(SubprogramDie, DW_AT_name, DW_FORM_string, Name); - if (!LinkageName.empty()) { - AddString(SubprogramDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - } - if (SPD->getType()) AddType(SubprogramDie, SPD->getType(), Unit); - if (!SPD->isStatic()) - AddUInt(SubprogramDie, DW_AT_external, DW_FORM_flag, 1); - AddUInt(SubprogramDie, DW_AT_prototyped, DW_FORM_flag, 1); - - // Add source line info if available. - AddSourceLine(SubprogramDie, UnitDesc, SPD->getLine()); - - // Add to map. - Slot = SubprogramDie; - - // Add to context owner. - Unit->getDie()->AddChild(SubprogramDie); - - // Expose as global. - Unit->AddGlobal(FullName, SubprogramDie); - - return SubprogramDie; - } - - /// NewScopeVariable - Create a new scope variable. - /// - DIE *NewScopeVariable(DebugVariable *DV, CompileUnit *Unit) { - // Get the descriptor. - VariableDesc *VD = DV->getDesc(); - - // Translate tag to proper Dwarf tag. The result variable is dropped for - // now. - unsigned Tag; - switch (VD->getTag()) { - case DW_TAG_return_variable: return NULL; - case DW_TAG_arg_variable: Tag = DW_TAG_formal_parameter; break; - case DW_TAG_auto_variable: // fall thru - default: Tag = DW_TAG_variable; break; - } - - // Define variable debug information entry. - DIE *VariableDie = new DIE(Tag); - AddString(VariableDie, DW_AT_name, DW_FORM_string, VD->getName()); - - // Add source line info if available. - AddSourceLine(VariableDie, VD->getFile(), VD->getLine()); - - // Add variable type. - AddType(VariableDie, VD->getType(), Unit); - - // Add variable address. - MachineLocation Location; - Location.set(RI->getFrameRegister(*MF), - RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); - AddAddress(VariableDie, DW_AT_location, Location); - - return VariableDie; - } - - /// NewScopeVariable - Create a new scope variable. + /// NewDbgScopeVariable - Create a new scope variable. /// DIE *NewDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { // Get the descriptor. - DIVariable *VD = DV->getVariable(); + const DIVariable &VD = DV->getVariable(); // Translate tag to proper Dwarf tag. The result variable is dropped for // now. unsigned Tag; - switch (VD->getTag()) { + switch (VD.getTag()) { case DW_TAG_return_variable: return NULL; case DW_TAG_arg_variable: Tag = DW_TAG_formal_parameter; break; case DW_TAG_auto_variable: // fall thru @@ -2521,13 +1948,13 @@ private: // Define variable debug information entry. DIE *VariableDie = new DIE(Tag); - AddString(VariableDie, DW_AT_name, DW_FORM_string, VD->getName()); + AddString(VariableDie, DW_AT_name, DW_FORM_string, VD.getName()); // Add source line info if available. - AddSourceLine(VariableDie, VD); + AddSourceLine(VariableDie, &VD); // Add variable type. - AddType(Unit, VariableDie, VD->getType()); + AddType(Unit, VariableDie, VD.getType()); // Add variable address. MachineLocation Location; @@ -2545,13 +1972,14 @@ private: if (!Slot) { // FIXME - breaks down when the context is an inlined function. DIDescriptor ParentDesc; - DIDescriptor *DB = new DIBlock(V); - if (DIBlock *Block = dyn_cast(DB)) { - ParentDesc = Block->getContext(); + 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, DB); + Slot = new DbgScope(Parent, Desc); if (Parent) { Parent->AddScope(Slot); } else if (RootDbgScope) { @@ -2627,15 +2055,20 @@ private: 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. - DISubprogram *SPD = cast(RootScope->getDesc()); + 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()); + DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); assert(SPDie && "Missing subprogram descriptor"); // Add the function bounds. @@ -2656,136 +2089,19 @@ private: 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); - DISubprogram *SPD = new DISubprogram(*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"); - - // 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 - } - - /// ConstructScope - Construct the components of a scope. - /// - void ConstructScope(DebugScope *ParentScope, - unsigned ParentStartID, unsigned ParentEndID, - DIE *ParentDie, CompileUnit *Unit) { - // Add variables to scope. - std::vector &Variables = ParentScope->getVariables(); - for (unsigned i = 0, N = Variables.size(); i < N; ++i) { - DIE *VariableDie = NewScopeVariable(Variables[i], Unit); - if (VariableDie) ParentDie->AddChild(VariableDie); - } - - // Add nested scopes. - std::vector &Scopes = ParentScope->getScopes(); - for (unsigned j = 0, M = Scopes.size(); j < M; ++j) { - // Define the Scope debug information entry. - DebugScope *Scope = Scopes[j]; - // FIXME - Ignore inlined functions for the time being. - if (!Scope->getParent()) continue; - - unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); - unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); - - // Ignore empty scopes. - if (StartID == EndID && StartID != 0) continue; - if (Scope->getScopes().empty() && Scope->getVariables().empty()) continue; - - if (StartID == ParentStartID && EndID == ParentEndID) { - // Just add stuff to the parent scope. - ConstructScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit); - } else { - DIE *ScopeDie = new DIE(DW_TAG_lexical_block); - - // Add the scope bounds. - if (StartID) { - AddLabel(ScopeDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("label", StartID)); - } else { - AddLabel(ScopeDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - } - if (EndID) { - AddLabel(ScopeDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("label", EndID)); - } else { - AddLabel(ScopeDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); - } - - // Add the scope contents. - ConstructScope(Scope, StartID, EndID, ScopeDie, Unit); - ParentDie->AddChild(ScopeDie); - } - } - } - - /// ConstructRootScope - Construct the scope for the subprogram. - /// - void ConstructRootScope(DebugScope *RootScope) { - // Exit if there is no root scope. - if (!RootScope) return; - - // Get the subprogram debug information entry. - SubprogramDesc *SPD = cast(RootScope->getDesc()); - - // Get the compile unit context. - CompileUnit *Unit = GetBaseCompileUnit(); - - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD); - assert(SPDie && "Missing subprogram descriptor"); - - // Add the function bounds. - AddLabel(SPDie, DW_AT_low_pc, DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - AddLabel(SPDie, DW_AT_high_pc, DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); - MachineLocation Location(RI->getFrameRegister(*MF)); - AddAddress(SPDie, DW_AT_frame_base, Location); - - ConstructScope(RootScope, 0, 0, SPDie, Unit); - } - - /// ConstructDefaultScope - 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()) { + if (SPD.getName() == MF->getFunction()->getName()) { // 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. @@ -2824,8 +2140,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()); @@ -2952,13 +2270,25 @@ 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 (DenseMap::iterator CI = DW_CUs.begin(), + CE = DW_CUs.end(); CI != CE; ++CI) { + CompileUnit *Unit = CI->second; + // 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. @@ -2967,32 +2297,39 @@ private: // Start debug info section. Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); - CompileUnit *Unit = GetBaseCompileUnit(); - 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(); + for (DenseMap::iterator CI = DW_CUs.begin(), + CE = DW_CUs.end(); CI != CE; ++CI) { + CompileUnit *Unit = CI->second; + if (MainCU) + Unit = MainCU; + 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) + return; + } } /// EmitAbbreviations - Emit the abbreviation section. @@ -3094,9 +2431,6 @@ 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) { @@ -3105,9 +2439,9 @@ private: Asm->EmitInt8(0); Asm->EOL("End of directories"); // Emit files. - for (unsigned SourceID = 1, NSID = SourceFiles.size(); + for (unsigned SourceID = 1, NSID = SrcFiles.size(); SourceID <= NSID; ++SourceID) { - const SourceFileInfo &SourceFile = SourceFiles[SourceID]; + const SrcFileInfo &SourceFile = SrcFiles[SourceID]; Asm->EmitString(SourceFile.getName()); Asm->EOL("Source"); Asm->EmitULEB128Bytes(SourceFile.getDirectoryID()); @@ -3145,7 +2479,7 @@ private: if (!LabelID) continue; unsigned SourceID = LineInfo.getSourceID(); - const SourceFileInfo &SourceFile = SourceFiles[SourceID]; + const SrcFileInfo &SourceFile = SrcFiles[SourceID]; unsigned DirectoryID = SourceFile.getDirectoryID(); if (VerboseAsm) Asm->EOL(Directories[DirectoryID] @@ -3276,7 +2610,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); @@ -3290,39 +2625,47 @@ private: // Start the dwarf pubnames section. Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); - CompileUnit *Unit = GetBaseCompileUnit(); - - 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); - Asm->EOL("Compilation Unit Length"); - - 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"); + for (DenseMap::iterator CI = DW_CUs.begin(), + CE = DW_CUs.end(); CI != CE; ++CI) { + CompileUnit *Unit = CI->second; + if (MainCU) + Unit = MainCU; + + 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); + Asm->EOL("Compilation Unit Length"); + + 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(0); Asm->EOL("End Mark"); + EmitLabel("pubnames_end", Unit->getID()); + + Asm->EOL(); + if (MainCU) + return; } - - Asm->EmitInt32(0); Asm->EOL("End Mark"); - EmitLabel("pubnames_end", Unit->getID()); - - Asm->EOL(); } /// EmitDebugStr - Emit visible names into a debug str section. @@ -3404,10 +2747,12 @@ private: /// EmitDebugMacInfo - Emit visible names into a debug macinfo section. /// void EmitDebugMacInfo() { - // Start the dwarf macinfo section. - Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection()); + if (TAI->doesSupportMacInfoSection()) { + // Start the dwarf macinfo section. + Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection()); - Asm->EOL(); + Asm->EOL(); + } } /// ConstructCompileUnits - Create a compile unit DIEs. @@ -3417,34 +2762,31 @@ private: getGlobalVariablesUsing(*M, CUName, Result); for (std::vector::iterator RI = Result.begin(), RE = Result.end(); RI != RE; ++RI) { - DICompileUnit *DIUnit = new DICompileUnit(*RI); - unsigned ID = RecordSource(DIUnit->getDirectory(), - DIUnit->getFilename()); + 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()); + 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; - } - } - - /// 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); + if (DIUnit.isMain()) { + assert (!MainCU && "Multiple main compile units are found!"); + MainCU = Unit; + } + DW_CUs[DIUnit.getGV()] = Unit; } } @@ -3456,32 +2798,22 @@ private: getGlobalVariablesUsing(*M, GVName, Result); for (std::vector::iterator GVI = Result.begin(), GVE = Result.end(); GVI != GVE; ++GVI) { - DIGlobalVariable *DI_GV = new DIGlobalVariable(*GVI); - CompileUnit *DW_Unit = FindCompileUnit(DI_GV->getCompileUnit()); + DIGlobalVariable DI_GV(*GVI); + 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()); + DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV()); if (Slot) continue; - DIE *VariableDie = new DIE(DW_TAG_variable); - AddString(VariableDie, DW_AT_name, DW_FORM_string, DI_GV->getName()); - const std::string &LinkageName = DI_GV->getLinkageName(); - if (!LinkageName.empty()) - AddString(VariableDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - AddType(DW_Unit, VariableDie, DI_GV->getType()); - - if (!DI_GV->isLocalToUnit()) - AddUInt(VariableDie, DW_AT_external, DW_FORM_flag, 1); - - // Add source line info, if available. - AddSourceLine(VariableDie, DI_GV); + 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->getGV())); + Asm->getGlobalLinkName(DI_GV.getGlobal())); AddBlock(VariableDie, DW_AT_location, 0, Block); //Add to map. @@ -3491,19 +2823,7 @@ private: DW_Unit->getDie()->AddChild(VariableDie); //Expose as global. FIXME - need to check external flag. - DW_Unit->AddGlobal(DI_GV->getName(), VariableDie); - } - } - - /// ConstructGlobalDIEs - Create DIEs for each of the externally visible - /// global variables. - void ConstructGlobalDIEs() { - std::vector GlobalVariables; - MMI->getAnchoredDescriptors(*M, GlobalVariables); - - for (unsigned i = 0, N = GlobalVariables.size(); i < N; ++i) { - GlobalVariableDesc *GVD = GlobalVariables[i]; - NewGlobalVariable(GVD); + DW_Unit->AddGlobal(DI_GV.getName(), VariableDie); } } @@ -3517,44 +2837,28 @@ private: for (std::vector::iterator RI = Result.begin(), RE = Result.end(); RI != RE; ++RI) { - DISubprogram *SP = new DISubprogram(*RI); - CompileUnit *Unit = FindCompileUnit(SP->getCompileUnit()); + DISubprogram SP(*RI); + CompileUnit *Unit = MainCU; + if (!Unit) + Unit = FindCompileUnit(SP.getCompileUnit()); - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(SP->getGV()); + // Check for pre-existence. + DIE *&Slot = Unit->getDieMapSlotFor(SP.getGV()); if (Slot) continue; - DIE *SubprogramDie = new DIE(DW_TAG_subprogram); - AddString(SubprogramDie, DW_AT_name, DW_FORM_string, SP->getName()); - const std::string &LinkageName = SP->getLinkageName(); - if (!LinkageName.empty()) - AddString(SubprogramDie, DW_AT_MIPS_linkage_name, DW_FORM_string, - LinkageName); - DIType SPTy = SP->getType(); - AddType(Unit, SubprogramDie, SPTy); - if (!SP->isLocalToUnit()) - AddUInt(SubprogramDie, DW_AT_external, DW_FORM_flag, 1); - AddUInt(SubprogramDie, DW_AT_prototyped, DW_FORM_flag, 1); - - AddSourceLine(SubprogramDie, SP); + if (!SP.isDefinition()) + // This is a method declaration which will be handled while + // constructing class type. + 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); - } - } - - /// ConstructSubprogramDIEs - Create DIEs for each of the externally visible - /// subprograms. - void ConstructSubprogramDIEs() { - std::vector Subprograms; - MMI->getAnchoredDescriptors(*M, Subprograms); - - for (unsigned i = 0, N = Subprograms.size(); i < N; ++i) { - SubprogramDesc *SPD = Subprograms[i]; - NewSubprogram(SPD); + Unit->AddGlobal(SP.getName(), SubprogramDie); } } @@ -3564,13 +2868,12 @@ public: // DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) : Dwarf(OS, A, T, "dbg") - , CompileUnits() + , MainCU(NULL) , AbbreviationsSet(InitAbbreviationsSetSize) , Abbreviations() , ValuesSet(InitValuesSetSize) , Values() , StringPool() - , DescToUnitMap() , SectionMap() , SectionSourceLines() , didInitial(false) @@ -3579,18 +2882,23 @@ public: { } 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]; } /// SetDebugInfo - Create global DIEs and emit initial debug info sections. /// This is inovked by the target AsmPrinter. - void SetDebugInfo() { - // FIXME - Check if the module has debug info or not. + void SetDebugInfo(MachineModuleInfo *mmi) { + // Create all the compile unit DIEs. ConstructCompileUnits(); + + if (DW_CUs.empty()) + return; + + MMI = mmi; + shouldEmit = true; + MMI->setDebugInfoAvailability(true); // Create DIEs for each of the externally visible global variables. ConstructGlobalVariableDIEs(); @@ -3618,46 +2926,6 @@ public: EmitInitial(); } - /// 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(); - } - } - - // Emit initial sections - EmitInitial(); - } - } - /// BeginModule - Emit all Dwarf sections that should come prior to the /// content. void BeginModule(Module *M) { @@ -3761,8 +3029,8 @@ public: } // 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 @@ -3772,7 +3040,7 @@ 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())); @@ -3788,6 +3056,47 @@ public: public: + /// ValidDebugInfo - Return true if V represents valid debug info value. + bool ValidDebugInfo(Value *V) { + + if (!V) + return false; + + if (!shouldEmit) + return false; + + GlobalVariable *GV = getGlobalVariable(V); + if (!GV) + return false; + + if (GV->getLinkage() != GlobalValue::InternalLinkage + && GV->getLinkage() != GlobalValue::LinkOnceLinkage) + return false; + + DIDescriptor DI(GV); + // Check current version. Allow Version6 for now. + unsigned Version = DI.getVersion(); + if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6) + 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; + } + + 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. @@ -3841,9 +3150,19 @@ public: /// RecordVariable - Indicate the declaration of a local variable. /// void RecordVariable(GlobalVariable *GV, unsigned FrameIndex) { - DbgScope *Scope = getOrCreateScope(GV); - DIVariable *VD = new DIVariable(GV); - DbgVariable *DV = new DbgVariable(VD, FrameIndex); + 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); } }; @@ -3852,8 +3171,6 @@ public: /// DwarfException - Emits Dwarf exception handling directives. /// class DwarfException : public Dwarf { - -private: struct FunctionEHFrameInfo { std::string FnName; unsigned Number; @@ -3993,7 +3310,8 @@ 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"; } @@ -4070,7 +3388,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 @@ -4912,7 +4231,7 @@ void DwarfWriter::BeginModule(Module *M, DD = new DwarfDebug(OS, A, T); DE->BeginModule(M); DD->BeginModule(M); - DD->SetModuleInfo(MMI); + DD->SetDebugInfo(MMI); DE->SetModuleInfo(MMI); } @@ -4941,6 +4260,11 @@ void DwarfWriter::EndFunction(MachineFunction *MF) { MMI->EndFunction(); } +/// ValidDebugInfo - Return true if V represents valid debug info value. +bool DwarfWriter::ValidDebugInfo(Value *V) { + return DD && DD->ValidDebugInfo(V); +} + /// RecordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide /// correspondence to the source line list. @@ -4970,3 +4294,10 @@ unsigned DwarfWriter::RecordRegionEnd(GlobalVariable *V) { 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); +} +