As part of the ongoing work in finalizing the accelerator tables, extend
authorEric Christopher <echristo@apple.com>
Fri, 6 Jan 2012 04:35:23 +0000 (04:35 +0000)
committerEric Christopher <echristo@apple.com>
Fri, 6 Jan 2012 04:35:23 +0000 (04:35 +0000)
the debug type accelerator tables to contain the tag and a flag
stating whether or not a compound type is a complete type.

rdar://10652330

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147651 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
lib/CodeGen/AsmPrinter/DwarfAccelTable.h
lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
lib/CodeGen/AsmPrinter/DwarfDebug.cpp

index 6c77a631a924e6dc3339febec975defd4277a855..940592ed26bcdb79e09eed6250404268e9e1edef 100644 (file)
@@ -42,16 +42,22 @@ DwarfAccelTable::DwarfAccelTable(DwarfAccelTable::Atom atom) :
   HeaderData(atom) {
 }
 
+// The length of the header data is always going to be 4 + 4 + 4*NumAtoms.
+DwarfAccelTable::DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &atomList) :
+  Header(8 + (atomList.size() * 4)),
+  HeaderData(atomList) {
+}
+
 DwarfAccelTable::~DwarfAccelTable() {
-  for (size_t i = 0, e = Data.size() ; i < e; ++i)
+  for (size_t i = 0, e = Data.size(); i < e; ++i)
     delete Data[i];
 }
 
-void DwarfAccelTable::AddName(StringRef Name, DIE* die) {
+void DwarfAccelTable::AddName(StringRef Name, DIE* die, char Flags) {
   // If the string is in the list already then add this die to the list
   // otherwise add a new one.
-  DIEArray &DIEs = Entries[Name];
-  DIEs.push_back(die);
+  DataArray &DIEs = Entries[Name];
+  DIEs.push_back(new HashDataContents(die, Flags));
 }
 
 void DwarfAccelTable::ComputeBucketCount(void) {
@@ -76,15 +82,16 @@ void DwarfAccelTable::ComputeBucketCount(void) {
 namespace {
   // DIESorter - comparison predicate that sorts DIEs by their offset.
   struct DIESorter {
-    bool operator()(DIE *A, DIE *B) const {
-      return A->getOffset() < B->getOffset();
+    bool operator()(const struct DwarfAccelTable::HashDataContents *A,
+                    const struct DwarfAccelTable::HashDataContents *B) const {
+      return A->Die->getOffset() < B->Die->getOffset();
     }
   };
 }
 
 void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) {
   // Create the individual hash data outputs.
-  for (StringMap<DIEArray>::iterator
+  for (StringMap<DataArray>::iterator
          EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
     struct HashData *Entry = new HashData((*EI).getKeyData());
 
@@ -93,10 +100,10 @@ void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) {
     (*EI).second.erase(std::unique((*EI).second.begin(), (*EI).second.end()),
                        (*EI).second.end());
 
-    for (DIEArray::const_iterator DI = (*EI).second.begin(),
+    for (DataArray::const_iterator DI = (*EI).second.begin(),
            DE = (*EI).second.end();
          DI != DE; ++DI)
-      Entry->addOffset((*DI)->getOffset());
+      Entry->addData((*DI));
     Data.push_back(Entry);
   }
 
@@ -202,11 +209,18 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) {
       Asm->EmitSectionOffset(D->getStringPoolEntry((*HI)->Str),
                              D->getStringPool());
       Asm->OutStreamer.AddComment("Num DIEs");
-      Asm->EmitInt32((*HI)->DIEOffsets.size());
-      for (std::vector<uint32_t>::const_iterator
-             DI = (*HI)->DIEOffsets.begin(), DE = (*HI)->DIEOffsets.end();
+      Asm->EmitInt32((*HI)->Data.size());
+      for (std::vector<struct HashDataContents*>::const_iterator
+             DI = (*HI)->Data.begin(), DE = (*HI)->Data.end();
            DI != DE; ++DI) {
-        Asm->EmitInt32((*DI));
+        // Emit the DIE offset
+        Asm->EmitInt32((*DI)->Die->getOffset());
+        // If we have multiple Atoms emit that info too.
+        // FIXME: A bit of a hack, we either emit only one atom or all info.
+        if (HeaderData.Atoms.size() > 1) {
+          Asm->EmitInt16((*DI)->Die->getTag());
+          Asm->EmitInt8((*DI)->Flags);
+        }
       }
       // Emit a 0 to terminate the data unless we have a hash collision.
       if (PrevHash != (*HI)->HashValue)
@@ -242,10 +256,10 @@ void DwarfAccelTable::print(raw_ostream &O) {
   HeaderData.print(O);
 
   O << "Entries: \n";
-  for (StringMap<DIEArray>::const_iterator
+  for (StringMap<DataArray>::const_iterator
          EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
     O << "Name: " << (*EI).getKeyData() << "\n";
-    for (DIEArray::const_iterator DI = (*EI).second.begin(),
+    for (DataArray::const_iterator DI = (*EI).second.begin(),
            DE = (*EI).second.end();
          DI != DE; ++DI)
       (*DI)->print(O);
index 0c1e949c7f2e2dbefa1ff80d6b1f299f61e85ad8..464ada48474f98d84830ec878c35a96afc2c7e7f 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
+#include "DIE.h"
 #include <vector>
 #include <map>
 
@@ -134,6 +135,14 @@ public:
     eAtomTypeTypeFlags  = 5u    // Flags from enum TypeFlags
   };
 
+  enum TypeFlags {
+    eTypeFlagClassMask = 0x0000000fu,
+    
+    // Always set for C++, only set for ObjC if this is the
+    // @implementation for a class.
+    eTypeFlagClassIsImplementation  = ( 1u << 1 )
+  };  
+  
   // Make these public so that they can be used as a general interface to
   // the class.
   struct Atom {
@@ -144,7 +153,7 @@ public:
     static const char * AtomTypeString(enum AtomType);
 #ifndef NDEBUG
     void print(raw_ostream &O) {
-      O << "Type: " << dwarf::TagString(type) << "\n"
+      O << "Type: " << AtomTypeString(type) << "\n"
         << "Form: " << dwarf::FormEncodingString(form) << "\n";
     }
     void dump() {
@@ -159,6 +168,13 @@ public:
     uint32_t die_offset_base;
     std::vector<Atom> Atoms;
 
+    TableHeaderData(std::vector<DwarfAccelTable::Atom> &AtomList,
+                    uint32_t offset = 0) :
+      die_offset_base(offset) {
+      for (size_t i = 0, e = AtomList.size(); i != e; ++i)
+        Atoms.push_back(AtomList[i]);
+    }
+    
     TableHeaderData(DwarfAccelTable::Atom Atom, uint32_t offset = 0)
     : die_offset_base(offset) {
       Atoms.push_back(Atom);
@@ -184,15 +200,32 @@ public:
   // uint32_t str_offset
   // uint32_t hash_data_count
   // HashData[hash_data_count]
+public:
+  struct HashDataContents {
+    DIE *Die; // Offsets
+    char Flags; // Specific flags to output
+
+    HashDataContents(DIE *D, char Flags) :
+      Die(D),
+      Flags(Flags) { };
+    #ifndef NDEBUG
+    void print(raw_ostream &O) const {
+      O << "  Offset: " << Die->getOffset() << "\n";
+      O << "  Tag: " << dwarf::TagString(Die->getTag()) << "\n";
+      O << "  Flags: " << Flags << "\n";
+    }
+    #endif
+  };
+private:
   struct HashData {
     StringRef Str;
     uint32_t HashValue;
     MCSymbol *Sym;
-    std::vector<uint32_t> DIEOffsets; // offsets
+    std::vector<struct HashDataContents*> Data; // offsets
     HashData(StringRef S) : Str(S) {
       HashValue = DwarfAccelTable::HashDJB(S);
     }
-    void addOffset(uint32_t off) { DIEOffsets.push_back(off); }
+    void addData(struct HashDataContents *Datum) { Data.push_back(Datum); }
     #ifndef NDEBUG
     void print(raw_ostream &O) {
       O << "Name: " << Str << "\n";
@@ -201,8 +234,11 @@ public:
       if (Sym) Sym->print(O);
       else O << "<none>";
       O << "\n";
-      for (size_t i = 0; i < DIEOffsets.size(); i++)
-        O << "  Offset: " << DIEOffsets[i] << "\n";
+      for (size_t i = 0; i < Data.size(); i++) {
+        O << "  Offset: " << Data[i]->Die->getOffset() << "\n";
+        O << "  Tag: " << dwarf::TagString(Data[i]->Die->getTag()) << "\n";
+        O << "  Flags: " << Data[i]->Flags << "\n";
+      }
     }
     void dump() {
       print(dbgs());
@@ -226,8 +262,8 @@ public:
   std::vector<HashData*> Data;
 
   // String Data
-  typedef std::vector<DIE*> DIEArray;
-  typedef StringMap<DIEArray> StringEntries;
+  typedef std::vector<struct HashDataContents*> DataArray;
+  typedef StringMap<DataArray> StringEntries;
   StringEntries Entries;
 
   // Buckets/Hashes/Offsets
@@ -238,9 +274,10 @@ public:
   
   // Public Implementation
  public:
-  DwarfAccelTable(DwarfAccelTable::Atom Atom);
+  DwarfAccelTable(DwarfAccelTable::Atom);
+  DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &);
   ~DwarfAccelTable();
-  void AddName(StringRef, DIE*);
+  void AddName(StringRef, DIE*, char = 0);
   void FinalizeTable(AsmPrinter *, const char *);
   void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *);
 #ifndef NDEBUG
index f43a5bf84213e49a311a89f0334973f4009e75c4..e499d2c8bfee5450d7c1a35dc9cfc4d91316402b 100644 (file)
@@ -13,6 +13,7 @@
 
 #define DEBUG_TYPE "dwarfdebug"
 
+#include "DwarfAccelTable.h"
 #include "DwarfCompileUnit.h"
 #include "DwarfDebug.h"
 #include "llvm/Constants.h"
@@ -608,8 +609,20 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
   }
   // If this is a named finished type then include it in the list of types
   // for the accelerator tables.
-  if (!Ty.getName().empty() && !Ty.isForwardDecl())
-    addAccelType(Ty.getName(), TyDIE);
+  if (!Ty.getName().empty() && !Ty.isForwardDecl()) {
+    bool IsImplementation = 0;
+    if (Ty.isCompositeType()) {
+      DICompositeType CT(Ty);
+      IsImplementation = (CT.getRunTimeLang() == 0) ||
+        CT.isObjcClassComplete();;
+    }
+    
+    addAccelType(Ty.getName(),
+                 std::make_pair(TyDIE,
+                                (IsImplementation ?
+                               DwarfAccelTable::eTypeFlagClassIsImplementation :
+                                 0)));
+  }
   
   addToContextOwner(TyDIE, Ty.getContext());
   return TyDIE;
index 07a772338ee9e05a2a866bcc33196ebdb0066465..fe65927ff56e587bc0bfdfee376561592560572e 100644 (file)
@@ -65,7 +65,7 @@ class CompileUnit {
   StringMap<std::vector<DIE*> > AccelNames;
   StringMap<std::vector<DIE*> > AccelObjC;
   StringMap<std::vector<DIE*> > AccelNamespace;
-  StringMap<std::vector<DIE*> > AccelTypes;
+  StringMap<std::vector<std::pair<DIE*, unsigned> > > AccelTypes;
 
   /// DIEBlocks - A list of all the DIEBlocks in use.
   std::vector<DIEBlock *> DIEBlocks;
@@ -93,7 +93,8 @@ public:
   const StringMap<std::vector<DIE*> > &getAccelNamespace() const {
     return AccelNamespace;
   }
-  const StringMap<std::vector<DIE*> > &getAccelTypes() const {
+  const StringMap<std::vector<std::pair<DIE*, unsigned > > >
+  &getAccelTypes() const {
     return AccelTypes;
   }
   
@@ -119,8 +120,8 @@ public:
     std::vector<DIE*> &DIEs = AccelNamespace[Name];
     DIEs.push_back(Die);
   }
-  void addAccelType(StringRef Name, DIE *Die) {
-    std::vector<DIE*> &DIEs = AccelTypes[Name];
+  void addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die) {
+    std::vector<std::pair<DIE*, unsigned > > &DIEs = AccelTypes[Name];
     DIEs.push_back(Die);
   }
   
index 94ce04a92d461eb27260386d38866850a22a33fb..7e58c3027304677694edbeb2aa9f0fb65c30b173 100644 (file)
@@ -1844,19 +1844,26 @@ void DwarfDebug::emitAccelNamespaces() {
 
 /// emitAccelTypes() - Emit type dies into a hashed accelerator table.
 void DwarfDebug::emitAccelTypes() {
-  DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
-                                           dwarf::DW_FORM_data4));
+  std::vector<DwarfAccelTable::Atom> Atoms;
+  Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
+                                        dwarf::DW_FORM_data4));
+  Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTag,
+                                        dwarf::DW_FORM_data2));
+  Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTypeFlags,
+                                        dwarf::DW_FORM_data1));
+  DwarfAccelTable AT(Atoms);
   for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
          E = CUMap.end(); I != E; ++I) {
     CompileUnit *TheCU = I->second;
-    const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelTypes();
-    for (StringMap<std::vector<DIE*> >::const_iterator
+    const StringMap<std::vector<std::pair<DIE*, unsigned > > > &Names
+      = TheCU->getAccelTypes();
+    for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator
            GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
       const char *Name = GI->getKeyData();
-      std::vector<DIE *> Entities = GI->second;
-      for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
-             DE= Entities.end(); DI !=DE; ++DI)
-        AT.AddName(Name, (*DI));
+      std::vector<std::pair<DIE *, unsigned> > Entities = GI->second;
+      for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI
+             = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI)
+        AT.AddName(Name, (*DI).first, (*DI).second);
     }
   }