Add support to emit debug info for C++ namespaces.
authorDevang Patel <dpatel@apple.com>
Tue, 15 Dec 2009 19:16:48 +0000 (19:16 +0000)
committerDevang Patel <dpatel@apple.com>
Tue, 15 Dec 2009 19:16:48 +0000 (19:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91440 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/DebugInfo.h
lib/Analysis/DebugInfo.cpp
lib/CodeGen/AsmPrinter/DIE.h
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h

index 232804e57da850f58b77922e57b246de0b672603..a6ccc29e791b06ff217aba7afc380858fc77ed10 100644 (file)
@@ -99,6 +99,7 @@ namespace llvm {
     bool isGlobalVariable() const;
     bool isScope() const;
     bool isCompileUnit() const;
+    bool isNameSpace() const;
     bool isLexicalBlock() const;
     bool isSubrange() const;
     bool isEnumerator() const;
@@ -218,7 +219,7 @@ namespace llvm {
     virtual ~DIType() {}
 
     DIDescriptor getContext() const     { return getDescriptorField(1); }
-    StringRef getName() const         { return getStringField(2);     }
+    StringRef getName() const           { return getStringField(2);     }
     DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
     unsigned getLineNumber() const      { return getUnsignedField(4); }
     uint64_t getSizeInBits() const      { return getUInt64Field(5); }
@@ -470,6 +471,22 @@ namespace llvm {
     StringRef getFilename() const  { return getContext().getFilename(); }
   };
 
+  /// DINameSpace - A wrapper for a C++ style name space.
+  class DINameSpace : public DIScope { 
+  public:
+    explicit DINameSpace(MDNode *N = 0) : DIScope(N) {
+      if (DbgNode && !isNameSpace())
+        DbgNode = 0;
+    }
+
+    DIScope getContext() const     { return getFieldAs<DIScope>(1);      }
+    StringRef getName() const      { return getStringField(2);           }
+    StringRef getDirectory() const { return getContext().getDirectory(); }
+    StringRef getFilename() const  { return getContext().getFilename();  }
+    DICompileUnit getCompileUnit() const { return getFieldAs<DICompileUnit>(3); }
+    unsigned getLineNumber() const { return getUnsignedField(4);         }
+  };
+
   /// DILocation - This object holds location information. This object
   /// is not associated with any DWARF tag.
   class DILocation : public DIDescriptor {
@@ -624,6 +641,11 @@ namespace llvm {
     /// with the specified parent context.
     DILexicalBlock CreateLexicalBlock(DIDescriptor Context);
 
+    /// CreateNameSpace - This creates new descriptor for a namespace
+    /// with the specified parent context.
+    DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name,
+                                DICompileUnit CU, unsigned LineNo);
+
     /// CreateLocation - Creates a debug info location.
     DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo,
                               DIScope S, DILocation OrigLoc);
index 1c9f5004152c7c52e5df99e0487259ee053598de..bd81314f46321b848cdde258a0361725c7c2ee4b 100644 (file)
@@ -227,6 +227,7 @@ bool DIDescriptor::isScope() const {
     case dwarf::DW_TAG_compile_unit:
     case dwarf::DW_TAG_lexical_block:
     case dwarf::DW_TAG_subprogram:
+    case dwarf::DW_TAG_namespace:
       return true;
     default:
       break;
@@ -242,6 +243,14 @@ bool DIDescriptor::isCompileUnit() const {
   return Tag == dwarf::DW_TAG_compile_unit;
 }
 
+/// isNameSpace - Return true if the specified tag is DW_TAG_namespace.
+bool DIDescriptor::isNameSpace() const {
+  assert (!isNull() && "Invalid descriptor!");
+  unsigned Tag = getTag();
+
+  return Tag == dwarf::DW_TAG_namespace;
+}
+
 /// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
 bool DIDescriptor::isLexicalBlock() const {
   assert (!isNull() && "Invalid descriptor!");
@@ -438,6 +447,8 @@ StringRef DIScope::getFilename() const {
     return DISubprogram(DbgNode).getFilename();
   else if (isCompileUnit())
     return DICompileUnit(DbgNode).getFilename();
+  else if (isNameSpace())
+    return DINameSpace(DbgNode).getFilename();
   else 
     assert (0 && "Invalid DIScope!");
   return StringRef();
@@ -450,6 +461,8 @@ StringRef DIScope::getDirectory() const {
     return DISubprogram(DbgNode).getDirectory();
   else if (isCompileUnit())
     return DICompileUnit(DbgNode).getDirectory();
+  else if (isNameSpace())
+    return DINameSpace(DbgNode).getDirectory();
   else 
     assert (0 && "Invalid DIScope!");
   return StringRef();
@@ -996,6 +1009,21 @@ DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) {
   return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2));
 }
 
+/// CreateNameSpace - This creates new descriptor for a namespace
+/// with the specified parent context.
+DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name,
+                                       DICompileUnit CompileUnit, 
+                                       unsigned LineNo) {
+  Value *Elts[] = {
+    GetTagConstant(dwarf::DW_TAG_namespace),
+    Context.getNode(),
+    MDString::get(VMContext, Name),
+    CompileUnit.getNode(),
+    ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
+  };
+  return DINameSpace(MDNode::get(VMContext, &Elts[0], 5));
+}
+
 /// CreateLocation - Creates a debug info location.
 DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo,
                                      DIScope S, DILocation OrigLoc) {
index cad8b89550246b67883c7e177771352791108b2b..a6dc9b690c23a07241a823ef25319f3728933606 100644 (file)
@@ -68,6 +68,7 @@ namespace llvm {
     /// Data - Raw data bytes for abbreviation.
     ///
     SmallVector<DIEAbbrevData, 8> Data;
+
   public:
     DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {}
     virtual ~DIEAbbrev() {}
@@ -131,19 +132,18 @@ namespace llvm {
     ///
     std::vector<DIE *> Children;
 
+    DIE *Parent;
+
     /// Attributes values.
     ///
     SmallVector<DIEValue*, 32> Values;
 
-    /// Abstract compile unit.
-    CompileUnit *AbstractCU;
-    
     // Private data for print()
     mutable unsigned IndentCount;
   public:
     explicit DIE(unsigned Tag)
       : Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0),
-        Size(0), IndentCount(0) {}
+        Size(0), Parent (0), IndentCount(0) {}
     virtual ~DIE();
 
     // Accessors.
@@ -154,13 +154,12 @@ namespace llvm {
     unsigned getSize() const { return Size; }
     const std::vector<DIE *> &getChildren() const { return Children; }
     SmallVector<DIEValue*, 32> &getValues() { return Values; }
-    CompileUnit *getAbstractCompileUnit() const { return AbstractCU; }
-
+    DIE *getParent() const { return Parent; }
     void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
     void setOffset(unsigned O) { Offset = O; }
     void setSize(unsigned S) { Size = S; }
-    void setAbstractCompileUnit(CompileUnit *CU) { AbstractCU = CU; }
-
+    void setParent(DIE *P) { Parent = P; }
+    
     /// addValue - Add a value and attributes to a DIE.
     ///
     void addValue(unsigned Attribute, unsigned Form, DIEValue *Value) {
@@ -179,8 +178,13 @@ namespace llvm {
     /// addChild - Add a child to the DIE.
     ///
     void addChild(DIE *Child) {
+      if (Child->getParent()) {
+        assert (Child->getParent() == this && "Unexpected DIE Parent!");
+        return;
+      }
       Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
       Children.push_back(Child);
+      Child->setParent(this);
     }
 
 #ifndef NDEBUG
index c200a46100c02fe5cae99f2023087588d7affb9a..f3b7f340357fb600a4a726b0c616521f9f25540d 100644 (file)
@@ -112,7 +112,12 @@ public:
 
   /// getDIEEntry - Returns the debug information entry for the speciefied
   /// debug variable.
-  DIEEntry *getDIEEntry(MDNode *N) { return GVToDIEEntryMap.lookup(N); }
+  DIEEntry *getDIEEntry(MDNode *N) { 
+    ValueMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N);
+    if (I == GVToDIEEntryMap.end())
+      return NULL;
+    return I->second;
+  }
 
   /// insertDIEEntry - Insert debug information entry into the map.
   void insertDIEEntry(MDNode *N, DIEEntry *E) {
@@ -446,6 +451,23 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
   addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
 }
 
+/// addSourceLine - Add location information to specified debug information
+/// entry.
+void DwarfDebug::addSourceLine(DIE *Die, const DINameSpace *NS) {
+  // If there is no compile unit specified, don't add a line #.
+  if (NS->getCompileUnit().isNull())
+    return;
+
+  unsigned Line = NS->getLineNumber();
+  StringRef FN = NS->getFilename();
+  StringRef Dir = NS->getDirectory();
+
+  unsigned FileID = GetOrCreateSourceID(Dir, FN);
+  assert(FileID && "Invalid file id");
+  addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
+  addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
+}
+
 /* Byref variables, in Blocks, are declared by the programmer as
    "SomeType VarName;", but the compiler creates a
    __Block_byref_x_VarName struct, and gives the variable VarName
@@ -745,6 +767,9 @@ void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
   else if (Context.isType()) {
     DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode()));
     ContextDIE->addChild(Die);
+  } else if (Context.isNameSpace()) {
+    DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode()));
+    ContextDIE->addChild(Die);
   } else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode()))
     ContextDIE->addChild(Die);
   else 
@@ -781,7 +806,6 @@ void DwarfDebug::addType(DIE *Entity, DIType Ty) {
 
   // Check for pre-existence.
   DIEEntry *Entry = ModuleCU->getDIEEntry(Ty.getNode());
-
   // If it exists then use the existing value.
   if (Entry) {
     Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry);
@@ -1030,13 +1054,6 @@ DIE *DwarfDebug::createGlobalVariableDIE(const DIGlobalVariable &GV) {
     addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
   addSourceLine(GVDie, &GV);
 
-  // Add address.
-  DIEBlock *Block = new DIEBlock();
-  addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
-  addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
-                 Asm->Mang->getMangledName(GV.getGlobal()));
-  addBlock(GVDie, dwarf::DW_AT_location, 0, Block);
-
   return GVDie;
 }
 
@@ -1285,7 +1302,6 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
    SPDie = new DIE(dwarf::DW_TAG_subprogram);
    addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, 
                SPDeclDie);
-   
    ModuleCU->addDie(SPDie);
  }
    
@@ -1559,6 +1575,20 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName)
   return SrcId;
 }
 
+/// getOrCreateNameSpace - Create a DIE for DINameSpace.
+DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) {
+  DIE *NDie = ModuleCU->getDIE(NS.getNode());
+  if (NDie)
+    return NDie;
+  NDie = new DIE(dwarf::DW_TAG_namespace);
+  ModuleCU->insertDIE(NS.getNode(), NDie);
+  if (!NS.getName().empty())
+    addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName());
+  addSourceLine(NDie, &NS);
+  addToContextOwner(NDie, NS.getContext());
+  return NDie;
+}
+
 CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) {
   DICompileUnit DIUnit(N);
   StringRef FN = DIUnit.getFilename();
@@ -1620,6 +1650,25 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
   ModuleCU->insertDIE(N, VariableDie);
 
   // Add to context owner.
+  if (DI_GV.isDefinition() 
+      && !DI_GV.getContext().isCompileUnit()) {
+    // Create specification DIE.
+    DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
+    addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
+                dwarf::DW_FORM_ref4, VariableDie);
+    DIEBlock *Block = new DIEBlock();
+    addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
+    addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
+                   Asm->Mang->getMangledName(DI_GV.getGlobal()));
+    addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
+    ModuleCU->addDie(VariableSpecDIE);
+  } else {
+    DIEBlock *Block = new DIEBlock();
+    addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
+    addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
+                   Asm->Mang->getMangledName(DI_GV.getGlobal()));
+    addBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
+  }
   addToContextOwner(VariableDie, DI_GV.getContext());
   
   // Expose as global. FIXME - need to check external flag.
@@ -1652,9 +1701,7 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) {
   ModuleCU->insertDIE(N, SubprogramDie);
 
   // Add to context owner.
-  if (SP.getContext().getNode() == SP.getCompileUnit().getNode())
-    if (TopLevelDIEs.insert(SubprogramDie))
-      TopLevelDIEsVector.push_back(SubprogramDie);
+  addToContextOwner(SubprogramDie, SP.getContext());
 
   // Expose as global.
   ModuleCU->addGlobal(SP.getName(), SubprogramDie);
@@ -2365,7 +2412,6 @@ void DwarfDebug::emitDebugInfo() {
   EmitLabel("info_end", ModuleCU->getID());
 
   Asm->EOL();
-
 }
 
 /// emitAbbreviations - Emit the abbreviation section.
index 12ad322b6853a257d616f583a2a9e667f2b77c12..2b8164e0b1993248f2de1085f38dee1598a559f5 100644 (file)
@@ -285,6 +285,7 @@ class DwarfDebug : public Dwarf {
   void addSourceLine(DIE *Die, const DIGlobal *G);
   void addSourceLine(DIE *Die, const DISubprogram *SP);
   void addSourceLine(DIE *Die, const DIType *Ty);
+  void addSourceLine(DIE *Die, const DINameSpace *NS);
 
   /// addAddress - Add an address attribute to a die based on the location
   /// provided.
@@ -315,6 +316,10 @@ class DwarfDebug : public Dwarf {
   /// addType - Add a new type attribute to the specified entity.
   void addType(DIE *Entity, DIType Ty);
 
+  /// getOrCreateNameSpace - Create a DIE for DINameSpace.
+  DIE *getOrCreateNameSpace(DINameSpace NS);
+
   /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
   /// given DIType.
   DIE *getOrCreateTypeDIE(DIType Ty);