Debug Info: define a DIRef template.
[oota-llvm.git] / include / llvm / DebugInfo.h
index f7e6434b4d72e8770c06fe6c6e70371954b887ce..deebcfd43959b9047502a2b449c7087bb8319fa1 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef LLVM_DEBUGINFO_H
 #define LLVM_DEBUGINFO_H
 
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -34,6 +36,7 @@ namespace llvm {
   class DbgValueInst;
   class Instruction;
   class MDNode;
+  class MDString;
   class NamedMDNode;
   class LLVMContext;
   class raw_ostream;
@@ -44,12 +47,20 @@ namespace llvm {
   class DILexicalBlockFile;
   class DIVariable;
   class DIType;
+  class DIScope;
   class DIObjCProperty;
 
+  /// Maps from type identifier to the actual MDNode.
+  typedef DenseMap<const MDString *, MDNode*> DITypeIdentifierMap;
+
   /// DIDescriptor - A thin wraper around MDNode to access encoded debug info.
   /// This should not be stored in a container, because the underlying MDNode
   /// may change in certain situations.
   class DIDescriptor {
+    // Befriends DIRef so DIRef can befriend the protected member
+    // function: getFieldAs<DIRef>.
+    template <typename T>
+    friend class DIRef;
   public:
     enum {
       FlagPrivate            = 1 << 0,
@@ -110,7 +121,7 @@ namespace llvm {
       return !operator==(Other);
     }
 
-    unsigned getTag() const {
+    uint16_t getTag() const {
       return getUnsignedField(0) & ~LLVMDebugVersionMask;
     }
 
@@ -179,6 +190,10 @@ namespace llvm {
     bool Verify() const;
   };
 
+  template <typename T>
+  class DIRef;
+  typedef DIRef<DIScope> DIScopeRef;
+
   /// DIScope - A base class for various scopes.
   class DIScope : public DIDescriptor {
   protected:
@@ -189,9 +204,13 @@ namespace llvm {
 
     /// Gets the parent scope for this scope node or returns a
     /// default constructed scope.
-    DIScope getContext() const;
+    DIScopeRef getContext() const;
     StringRef getFilename() const;
     StringRef getDirectory() const;
+
+    /// Generate a reference to this DIScope. Uses the type identifier instead
+    /// of the actual MDNode if possible, to help type uniquing.
+    DIScopeRef generateRef();
   };
 
   /// DIType - This is a wrapper for a type.
@@ -208,7 +227,7 @@ namespace llvm {
     /// Verify - Verify that a type descriptor is well formed.
     bool Verify() const;
 
-    DIScope getContext() const          { return getFieldAs<DIScope>(2); }
+    DIScopeRef getContext() const;
     StringRef getName() const           { return getStringField(3);     }
     unsigned getLineNumber() const      { return getUnsignedField(4); }
     uint64_t getSizeInBits() const      { return getUInt64Field(5); }
@@ -264,6 +283,53 @@ namespace llvm {
     void replaceAllUsesWith(MDNode *D);
   };
 
+  /// Represents reference to a DIDescriptor, abstracts over direct and
+  /// identifier-based metadata references.
+  template <typename T>
+  class DIRef {
+    template <typename DescTy>
+    friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
+    friend DIScopeRef DIScope::getContext() const;
+    friend DIScopeRef DIScope::generateRef();
+
+    /// Val can be either a MDNode or a MDString, in the latter,
+    /// MDString specifies the type identifier.
+    const Value *Val;
+    explicit DIRef(const Value *V);
+  public:
+    T resolve(const DITypeIdentifierMap &Map) const {
+      if (!Val)
+        return T();
+
+      if (const MDNode *MD = dyn_cast<MDNode>(Val))
+        return T(MD);
+
+      const MDString *MS = cast<MDString>(Val);
+      // Find the corresponding MDNode.
+      DITypeIdentifierMap::const_iterator Iter = Map.find(MS);
+      assert(Iter != Map.end() && "Identifier not in the type map?");
+      assert(DIType(Iter->second).isType() &&
+             "MDNode in DITypeIdentifierMap should be a DIType.");
+      return T(Iter->second);
+    }
+    operator Value *() const { return const_cast<Value*>(Val); }
+  };
+
+  /// Specialize getFieldAs to handle fields that are references to DIScopes.
+  template <>
+  DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
+  /// Specialize DIRef constructor for DIScopeRef.
+  template <>
+  DIRef<DIScope>::DIRef(const Value *V);
+
+  typedef DIRef<DIType> DITypeRef;
+  /// Specialize getFieldAs to handle fields that are references to DITypes.
+  template <>
+  DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
+  /// Specialize DIRef constructor for DITypeRef.
+  template <>
+  DIRef<DIType>::DIRef(const Value *V);
+
   /// DIBasicType - A basic type, like 'int' or 'float'.
   class DIBasicType : public DIType {
   public:
@@ -295,9 +361,9 @@ namespace llvm {
     /// associated with one.
     MDNode *getObjCProperty() const;
 
-    DIType getClassType() const {
+    DITypeRef getClassType() const {
       assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
-      return getFieldAs<DIType>(10);
+      return getFieldAs<DITypeRef>(10);
     }
 
     Constant *getConstant() const {
@@ -323,12 +389,14 @@ namespace llvm {
 
     DIArray getTypeArray() const { return getFieldAs<DIArray>(10); }
     void setTypeArray(DIArray Elements, DIArray TParams = DIArray());
+    void addMember(DIDescriptor D);
     unsigned getRunTimeLang() const { return getUnsignedField(11); }
-    DICompositeType getContainingType() const {
-      return getFieldAs<DICompositeType>(12);
+    DITypeRef getContainingType() const {
+      return getFieldAs<DITypeRef>(12);
     }
     void setContainingType(DICompositeType ContainingType);
     DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); }
+    MDString *getIdentifier() const;
 
     /// Verify - Verify that a composite type descriptor is well formed.
     bool Verify() const;
@@ -391,8 +459,8 @@ namespace llvm {
     unsigned getVirtuality() const { return getUnsignedField(10); }
     unsigned getVirtualIndex() const { return getUnsignedField(11); }
 
-    DICompositeType getContainingType() const {
-      return getFieldAs<DICompositeType>(12);
+    DITypeRef getContainingType() const {
+      return getFieldAs<DITypeRef>(12);
     }
 
     unsigned getFlags() const {
@@ -695,10 +763,6 @@ namespace llvm {
   /// getDICompositeType - Find underlying composite type.
   DICompositeType getDICompositeType(DIType T);
 
-  /// isSubprogramContext - Return true if Context is either a subprogram
-  /// or another context nested inside a subprogram.
-  bool isSubprogramContext(const MDNode *Context);
-
   /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
   /// to hold function specific information.
   NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP);
@@ -717,6 +781,9 @@ namespace llvm {
   /// cleanseInlinedVariable - Remove inlined scope from the variable.
   DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
 
+  /// Construct DITypeIdentifierMap by going through retained types of each CU.
+  DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
+
   /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To
   /// list debug info MDNodes used by an instruction, DebugInfoFinder uses
   /// processDeclare, processValue and processLocation to handle DbgDeclareInst,
@@ -790,6 +857,7 @@ namespace llvm {
     SmallVector<MDNode *, 8> TYs;  // Types
     SmallVector<MDNode *, 8> Scopes; // Scopes
     SmallPtrSet<MDNode *, 64> NodesSeen;
+    DITypeIdentifierMap TypeIdentifierMap;
   };
 } // end namespace llvm