diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h index c7682c29218..a5597322fcb 100644 --- a/include/llvm/CodeGen/DwarfWriter.h +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -84,9 +84,12 @@ public: /// the source line list. unsigned RecordSourceLine(unsigned Line, unsigned Col, unsigned Src); - /// RecordSource - Register a source file with debug info. Returns an source - /// ID. - unsigned RecordSource(const std::string &Dir, const std::string &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 DirectoryIds and SourceFileIds maps + /// as well. + unsigned getOrCreateSourceID(const std::string &DirName, + const std::string &FileName); /// RecordRegionStart - Indicate the start of a region. unsigned RecordRegionStart(GlobalVariable *V); diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 26973b1cb15..3edb57fce81 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" @@ -39,6 +34,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; @@ -67,40 +66,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 +103,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); } @@ -559,7 +524,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) { @@ -1172,33 +1137,6 @@ 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. /// @@ -1260,9 +1198,13 @@ class DwarfDebug : public Dwarf { // 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. @@ -1276,11 +1218,27 @@ class DwarfDebug : public Dwarf { /// std::vector Abbreviations; - /// Directories - Uniquing vector for directories. - UniqueVector Directories; + /// DirectoryIdMap - Directory name to directory id map. + /// + StringMap DirectoryIdMap; - /// SrcFiles - Uniquing vector for source files. - UniqueVector SrcFiles; + /// DirectoryNames - A list of directory names. + SmallVector DirectoryNames; + + /// SourceFileIdMap - Source file name to source file id map. + /// + StringMap SourceFileIdMap; + + /// SourceFileNames - A list of source file names. + SmallVector SourceFileNames; + + /// SourceIdMap - Source id map, i.e. pair of directory id and source file + /// id mapped to a unique id. + DenseMap, unsigned> SourceIdMap; + + /// SourceIds - Reverse map from source id to directory id + file id pair. + /// + SmallVector, 8> SourceIds; /// Lines - List of of source line correspondence. std::vector Lines; @@ -1434,7 +1392,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) { @@ -1691,7 +1649,8 @@ private: 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) @@ -1782,7 +1741,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) { @@ -1846,7 +1806,8 @@ private: DIE *ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) { DIE *Enumerator = new DIE(DW_TAG_enumerator); - AddString(Enumerator, DW_AT_name, DW_FORM_string, ETy->getName()); + const std::string &Name = ETy->getName(); + 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; @@ -1856,7 +1817,8 @@ private: 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 &Name = GV.getName(); + AddString(GVDie, DW_AT_name, DW_FORM_string, Name); const std::string &LinkageName = GV.getLinkageName(); if (!LinkageName.empty()) AddString(GVDie, DW_AT_MIPS_linkage_name, DW_FORM_string, LinkageName); @@ -1870,7 +1832,7 @@ 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(); + const std::string &Name = DT.getName(); if (!Name.empty()) AddString(MemberDie, DW_AT_name, DW_FORM_string, Name); @@ -1914,7 +1876,8 @@ 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 &Name = SP.getName(); + AddString(SPDie, DW_AT_name, DW_FORM_string, Name); const std::string &LinkageName = SP.getLinkageName(); if (!LinkageName.empty()) AddString(SPDie, DW_AT_MIPS_linkage_name, DW_FORM_string, @@ -1955,7 +1918,7 @@ private: /// 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; } @@ -1978,7 +1941,8 @@ private: // Define variable debug information entry. DIE *VariableDie = new DIE(Tag); - AddString(VariableDie, DW_AT_name, DW_FORM_string, VD.getName()); + const std::string &Name = VD.getName(); + AddString(VariableDie, DW_AT_name, DW_FORM_string, Name); // Add source line info if available. AddSourceLine(VariableDie, &VD); @@ -2119,27 +2083,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 = MainCU; - if (!Unit) - Unit = FindCompileUnit(SPD.getCompileUnit()); - - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); - if (!SPDie) - /* A subprogram die may not exist if the corresponding function - does not have any debug info. */ - continue; + 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, @@ -2151,12 +2100,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 @@ -2316,9 +2286,8 @@ private: SizeAndOffsetDie(MainCU->getDie(), Offset, true); return; } - for (DenseMap::iterator CI = DW_CUs.begin(), - CE = DW_CUs.end(); CI != CE; ++CI) { - CompileUnit *Unit = CI->second; + 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 @@ -2328,45 +2297,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; - 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; + if (MainCU) { + EmitDebugInfoPerCU(MainCU); + return; } + + for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) + EmitDebugInfoPerCU(CompileUnits[i]); } /// EmitAbbreviations - Emit the abbreviation section. @@ -2469,19 +2440,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 = getSourceDirsectoryAndFileIds(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"); @@ -2501,7 +2472,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(); @@ -2515,16 +2487,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 = + getSourceDirsectoryAndFileIds(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"); @@ -2656,53 +2628,52 @@ private: Asm->EOL(); } + void EmitDebugPubNamesPerCU(CompileUnit *Unit) { + EmitDifference("pubnames_end", Unit->getID(), + "pubnames_begin", Unit->getID(), true); + Asm->EOL("Length of Public Names Info"); + + EmitLabel("pubnames_begin", Unit->getID()); + + Asm->EmitInt16(DWARF_VERSION); Asm->EOL("DWARF Version"); + + EmitSectionOffset("info_begin", "section_info", + Unit->getID(), 0, true, false); + Asm->EOL("Offset of Compilation Unit Info"); + + EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(), + true); + 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(); + } + /// 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; - 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; + 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. @@ -2792,122 +2763,160 @@ private: } } + void ConstructCompileUnit(GlobalVariable *GV) { + DICompileUnit DIUnit(GV); + unsigned ID = getOrCreateSourceID(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); + 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); - 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; + 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); } - DW_CUs[DIUnit.getGV()] = Unit; - } + } + + 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. + DW_Unit->AddGlobal(DI_GV.getName(), VariableDie); + return true; } /// ConstructGlobalVariableDIEs - Create DIEs for each of the externally /// visible global variables. Return true if at least one global DIE is /// created. bool ConstructGlobalVariableDIEs() { - std::string GVName = "llvm.dbg.global_variables"; - std::vector Result; - getGlobalVariablesUsing(*M, GVName, Result); - bool result = false; - for (std::vector::iterator GVI = Result.begin(), - GVE = Result.end(); GVI != GVE; ++GVI) { - DIGlobalVariable DI_GV(*GVI); - CompileUnit *DW_Unit = MainCU; - if (!DW_Unit) - DW_Unit = FindCompileUnit(DI_GV.getCompileUnit()); + GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables"); + if (!Root) + return false; - // Check for pre-existence. - DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV()); - if (Slot) continue; + 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"); - DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV); + 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; + } - // 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); + bool ConstructSubprogram(GlobalVariable *GV) { + DISubprogram SP(GV); + CompileUnit *Unit = MainCU; + if (!Unit) + Unit = FindCompileUnit(SP.getCompileUnit()); - //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); - - if (!result) - result = true; - } - return result; + // 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. + Unit->AddGlobal(SP.getName(), SubprogramDie); + return true; } /// ConstructSubprograms - Create DIEs for each of the externally visible /// subprograms. Return true if at least one subprogram DIE is created. bool ConstructSubprograms() { - std::string SPName = "llvm.dbg.subprograms"; - std::vector Result; - getGlobalVariablesUsing(*M, SPName, Result); - bool result = false; - for (std::vector::iterator RI = Result.begin(), - RE = Result.end(); RI != RE; ++RI) { + GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms"); + if (!Root) + return false; - DISubprogram SP(*RI); - CompileUnit *Unit = MainCU; - if (!Unit) - Unit = FindCompileUnit(SP.getCompileUnit()); + 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"); - // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(SP.getGV()); - if (Slot) continue; - - 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); - - if (!result) - result = true; - } - return result; + 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: @@ -2940,7 +2949,7 @@ public: // Create all the compile unit DIEs. ConstructCompileUnits(); - if (DW_CUs.empty()) + if (CompileUnits.empty()) return; // Create DIEs for each of the externally visible global variables. @@ -2964,9 +2973,12 @@ public: // 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()); + for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) { + // Remember source id starts at 1. + std::pair Id = getSourceDirsectoryAndFileIds(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()); @@ -3152,7 +3164,7 @@ 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]; + CompileUnit *Unit = CompileUnitMap[V]; assert(Unit && "Unable to find CompileUnit"); unsigned ID = MMI->NextLabelID(); Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID)); @@ -3172,12 +3184,77 @@ public: 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)); + /// 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]; + } + + /// getNumSourceFiles - Return the number of source files in the debug info. + /// + unsigned getNumSourceFiles() const { + return SourceFileNames.size(); + } + + /// 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(); + } + + /// getSourceDirsectoryAndFileIds - Return the directory and file ids that + /// maps to the source id. Source id starts at 1. + std::pair + getSourceDirsectoryAndFileIds(unsigned SId) const { + return SourceIds[SId-1]; + } + + /// 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; } /// RecordRegionStart - Indicate the start of a region. @@ -3891,7 +3968,7 @@ public: void EndModule() { 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(), @@ -4324,11 +4401,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. diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index fb3d101f122..a0ed4755f9f 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -319,8 +319,8 @@ bool FastISel::SelectCall(User *I) { DbgStopPointInst *SPI = cast(I); if (DW && DW->ValidDebugInfo(SPI->getContext())) { DICompileUnit CU(cast(SPI->getContext())); - unsigned SrcFile = DW->RecordSource(CU.getDirectory(), - CU.getFilename()); + unsigned SrcFile = DW->getOrCreateSourceID(CU.getDirectory(), + CU.getFilename()); unsigned Line = SPI->getLine(); unsigned Col = SPI->getColumn(); unsigned ID = DW->RecordSourceLine(Line, Col, SrcFile); @@ -361,8 +361,8 @@ bool FastISel::SelectCall(User *I) { // (most?) gdb expects. DISubprogram Subprogram(cast(SP)); DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - unsigned SrcFile = DW->RecordSource(CompileUnit.getDirectory(), - CompileUnit.getFilename()); + unsigned SrcFile = DW->getOrCreateSourceID(CompileUnit.getDirectory(), + CompileUnit.getFilename()); // Record the source line but does not create a label for the normal // function start. It will be emitted at asm emission time. However, diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 3cfe4f47a0e..d5d62dd2ab6 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1287,8 +1287,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { GlobalVariable *CU_GV = cast(DSP->getCompileUnit()); if (DW && (useDEBUG_LOC || useLABEL) && !CU_GV->isDeclaration()) { DICompileUnit CU(cast(DSP->getCompileUnit())); - unsigned SrcFile = DW->RecordSource(CU.getDirectory(), - CU.getFilename()); + unsigned SrcFile = DW->getOrCreateSourceID(CU.getDirectory(), + CU.getFilename()); unsigned Line = DSP->getLine(); unsigned Col = DSP->getColumn(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 4791465b096..91fecc32251 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -335,8 +335,8 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, if (DW && DW->ValidDebugInfo(SPI->getContext())) { DICompileUnit CU(cast(SPI->getContext())); - unsigned SrcFile = DW->RecordSource(CU.getDirectory(), - CU.getFilename()); + unsigned SrcFile = DW->getOrCreateSourceID(CU.getDirectory(), + CU.getFilename()); unsigned idx = MF->getOrCreateDebugLocID(SrcFile, SPI->getLine(), SPI->getColumn()); @@ -354,8 +354,8 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, if (DW->ValidDebugInfo(SP)) { DISubprogram Subprogram(cast(SP)); DICompileUnit CU(Subprogram.getCompileUnit()); - unsigned SrcFile = DW->RecordSource(CU.getDirectory(), - CU.getFilename()); + unsigned SrcFile = DW->getOrCreateSourceID(CU.getDirectory(), + CU.getFilename()); unsigned Line = Subprogram.getLineNumber(); DL = DebugLoc::get(MF->getOrCreateDebugLocID(SrcFile, Line, 0)); } @@ -3892,16 +3892,16 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DwarfWriter *DW = DAG.getDwarfWriter(); DbgStopPointInst &SPI = cast(I); if (DW && DW->ValidDebugInfo(SPI.getContext())) { + MachineFunction &MF = DAG.getMachineFunction(); DAG.setRoot(DAG.getDbgStopPoint(getRoot(), SPI.getLine(), SPI.getColumn(), SPI.getContext())); DICompileUnit CU(cast(SPI.getContext())); - unsigned SrcFile = DW->RecordSource(CU.getDirectory(), CU.getFilename()); - unsigned idx = DAG.getMachineFunction(). - getOrCreateDebugLocID(SrcFile, - SPI.getLine(), - SPI.getColumn()); + unsigned SrcFile = DW->getOrCreateSourceID(CU.getDirectory(), + CU.getFilename()); + unsigned idx = MF.getOrCreateDebugLocID(SrcFile, + SPI.getLine(), SPI.getColumn()); setCurDebugLoc(DebugLoc::get(idx)); } return 0; @@ -3940,10 +3940,11 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { if (SP && DW->ValidDebugInfo(SP)) { // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is // what (most?) gdb expects. + MachineFunction &MF = DAG.getMachineFunction(); DISubprogram Subprogram(cast(SP)); DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - unsigned SrcFile = DW->RecordSource(CompileUnit.getDirectory(), - CompileUnit.getFilename()); + unsigned SrcFile = DW->getOrCreateSourceID(CompileUnit.getDirectory(), + CompileUnit.getFilename()); // Record the source line but does not create a label for the normal // function start. It will be emitted at asm emission time. However, @@ -3957,8 +3958,7 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { getRoot(), LabelID)); } - setCurDebugLoc(DebugLoc::get(DAG.getMachineFunction(). - getOrCreateDebugLocID(SrcFile, Line, 0))); + setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID(SrcFile, Line, 0))); } return 0;