Make sure that if we're going to attempt to add a type to a DIE that
[oota-llvm.git] / lib / IR / DebugInfo.cpp
index b611f458c0ea0ff06e7c9470d8514ae6caed0045..fc9324949d0d960e8f0afd53fbcd0191fd5f65a7 100644 (file)
@@ -34,24 +34,6 @@ using namespace llvm::dwarf;
 // DIDescriptor
 //===----------------------------------------------------------------------===//
 
-DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) {
-}
-
-DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) {
-}
-
-DIDescriptor::DIDescriptor(const DILexicalBlockFile F) : DbgNode(F.DbgNode) {
-}
-
-DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) {
-}
-
-DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) {
-}
-
-DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) {
-}
-
 bool DIDescriptor::Verify() const {
   return DbgNode &&
          (DIDerivedType(DbgNode).Verify() ||
@@ -249,11 +231,6 @@ bool DIDescriptor::isGlobalVariable() const {
                      getTag() == dwarf::DW_TAG_constant);
 }
 
-/// isGlobal - Return true if the specified tag is legal for DIGlobal.
-bool DIDescriptor::isGlobal() const {
-  return isGlobalVariable();
-}
-
 /// isUnspecifiedParmeter - Return true if the specified tag is
 /// DW_TAG_unspecified_parameters.
 bool DIDescriptor::isUnspecifiedParameter() const {
@@ -344,23 +321,17 @@ bool DIDescriptor::isImportedEntity() const {
 // Simple Descriptor Constructors and other Methods
 //===----------------------------------------------------------------------===//
 
-DIType::DIType(const MDNode *N) : DIScope(N) {
-  if (!N) return;
-  if (!isType())
-    DbgNode = 0;
-}
-
 unsigned DIArray::getNumElements() const {
   if (!DbgNode)
     return 0;
   return DbgNode->getNumOperands();
 }
 
-/// replaceAllUsesWith - Replace all uses of debug info referenced by
-/// this descriptor.
+/// replaceAllUsesWith - Replace all uses of the MDNode used by this
+/// type with the one in the passed descriptor.
 void DIType::replaceAllUsesWith(DIDescriptor &D) {
-  if (!DbgNode)
-    return;
+
+  assert(DbgNode && "Trying to replace an unverified type!");
 
   // Since we use a TrackingVH for the node, its easy for clients to manufacture
   // legitimate situations where they want to replaceAllUsesWith() on something
@@ -376,11 +347,11 @@ void DIType::replaceAllUsesWith(DIDescriptor &D) {
   }
 }
 
-/// replaceAllUsesWith - Replace all uses of debug info referenced by
-/// this descriptor.
+/// replaceAllUsesWith - Replace all uses of the MDNode used by this
+/// type with the one in D.
 void DIType::replaceAllUsesWith(MDNode *D) {
-  if (!DbgNode)
-    return;
+
+  assert(DbgNode && "Trying to replace an unverified type!");
 
   // Since we use a TrackingVH for the node, its easy for clients to manufacture
   // legitimate situations where they want to replaceAllUsesWith() on something
@@ -417,10 +388,12 @@ bool DIType::isUnsignedDIType() {
 bool DICompileUnit::Verify() const {
   if (!isCompileUnit())
     return false;
-  StringRef N = getFilename();
-  if (N.empty())
+
+  // Don't bother verifying the compilation directory or producer string
+  // as those could be empty.
+  if (getFilename().empty())
     return false;
-  // It is possible that directory and produce string is empty.
+
   return DbgNode->getNumOperands() == 13;
 }
 
@@ -433,22 +406,38 @@ bool DIObjCProperty::Verify() const {
   return DbgNode->getNumOperands() == 8;
 }
 
+/// Check if a field at position Elt of a MDNode is a MDNode.
+/// We currently allow an empty string and an integer.
+/// But we don't allow a non-empty string in a MDNode field.
+static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) {
+  // FIXME: This function should return true, if the field is null or the field
+  // is indeed a MDNode: return !Fld || isa<MDNode>(Fld).
+  Value *Fld = getField(DbgNode, Elt);
+  if (Fld && isa<MDString>(Fld) &&
+      !cast<MDString>(Fld)->getString().empty())
+    return false;
+  return true;
+}
+
 /// Verify - Verify that a type descriptor is well formed.
 bool DIType::Verify() const {
   if (!isType())
     return false;
-  unsigned Tag = getTag();
+  // Make sure Context @ field 2 is MDNode.
+  if (!fieldIsMDNode(DbgNode, 2))
+    return false;
+
+  // FIXME: Sink this into the various subclass verifies.
+  uint16_t Tag = getTag();
   if (!isBasicType() && Tag != dwarf::DW_TAG_const_type &&
       Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type &&
       Tag != dwarf::DW_TAG_ptr_to_member_type &&
       Tag != dwarf::DW_TAG_reference_type &&
       Tag != dwarf::DW_TAG_rvalue_reference_type &&
-      Tag != dwarf::DW_TAG_restrict_type &&
-      Tag != dwarf::DW_TAG_array_type &&
+      Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_array_type &&
       Tag != dwarf::DW_TAG_enumeration_type &&
       Tag != dwarf::DW_TAG_subroutine_type &&
-      Tag != dwarf::DW_TAG_inheritance &&
-      Tag != dwarf::DW_TAG_friend &&
+      Tag != dwarf::DW_TAG_inheritance && Tag != dwarf::DW_TAG_friend &&
       getFilename().empty())
     return false;
   // DIType is abstract, it should be a BasicType, a DerivedType or
@@ -471,6 +460,14 @@ bool DIBasicType::Verify() const {
 
 /// Verify - Verify that a derived type descriptor is well formed.
 bool DIDerivedType::Verify() const {
+  // Make sure DerivedFrom @ field 9 is MDNode.
+  if (!fieldIsMDNode(DbgNode, 9))
+    return false;
+  if (getTag() == dwarf::DW_TAG_ptr_to_member_type)
+    // Make sure ClassType @ field 10 is MDNode.
+    if (!fieldIsMDNode(DbgNode, 10))
+      return false;
+
   return isDerivedType() && DbgNode->getNumOperands() >= 10 &&
          DbgNode->getNumOperands() <= 14;
 }
@@ -480,6 +477,18 @@ bool DICompositeType::Verify() const {
   if (!isCompositeType())
     return false;
 
+  // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are MDNodes.
+  if (!fieldIsMDNode(DbgNode, 9))
+    return false;
+  if (!fieldIsMDNode(DbgNode, 12))
+    return false;
+
+  // If this is an array type verify that we have a DIType in the derived type
+  // field as that's the type of our element.
+  if (getTag() == dwarf::DW_TAG_array_type)
+    if (!DIType(getTypeDerivedFrom()))
+      return false;
+
   return DbgNode->getNumOperands() >= 10 && DbgNode->getNumOperands() <= 14;
 }
 
@@ -488,6 +497,14 @@ bool DISubprogram::Verify() const {
   if (!isSubprogram())
     return false;
 
+  // Make sure context @ field 2 and type @ field 7 are MDNodes.
+  if (!fieldIsMDNode(DbgNode, 2))
+    return false;
+  if (!fieldIsMDNode(DbgNode, 7))
+    return false;
+  // Containing type @ field 12.
+  if (!fieldIsMDNode(DbgNode, 12))
+    return false;
   return DbgNode->getNumOperands() == 20;
 }
 
@@ -498,6 +515,14 @@ bool DIGlobalVariable::Verify() const {
 
   if (getDisplayName().empty())
     return false;
+  // Make sure context @ field 2 and type @ field 8 are MDNodes.
+  if (!fieldIsMDNode(DbgNode, 2))
+    return false;
+  if (!fieldIsMDNode(DbgNode, 8))
+    return false;
+  // Make sure StaticDataMemberDeclaration @ field 12 is MDNode.
+  if (!fieldIsMDNode(DbgNode, 12))
+    return false;
 
   return DbgNode->getNumOperands() == 13;
 }
@@ -507,6 +532,11 @@ bool DIVariable::Verify() const {
   if (!isVariable())
     return false;
 
+  // Make sure context @ field 1 and type @ field 5 are MDNodes.
+  if (!fieldIsMDNode(DbgNode, 1))
+    return false;
+  if (!fieldIsMDNode(DbgNode, 5))
+    return false;
   return DbgNode->getNumOperands() >= 8;
 }
 
@@ -574,7 +604,7 @@ bool DIImportedEntity::Verify() const {
 /// getOriginalTypeSize - If this type is derived from a base type then
 /// return base type size.
 uint64_t DIDerivedType::getOriginalTypeSize() const {
-  unsigned Tag = getTag();
+  uint16_t Tag = getTag();
 
   if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
       Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
@@ -668,6 +698,29 @@ Value *DITemplateValueParameter::getValue() const {
   return getField(DbgNode, 4);
 }
 
+// If the current node has a parent scope then return that,
+// else return an empty scope.
+DIScope DIScope::getContext() const {
+
+  if (isType())
+    return DIType(DbgNode).getContext();
+
+  if (isSubprogram())
+    return DISubprogram(DbgNode).getContext();
+
+  if (isLexicalBlock())
+    return DILexicalBlock(DbgNode).getContext();
+
+  if (isLexicalBlockFile())
+    return DILexicalBlockFile(DbgNode).getContext();
+
+  if (isNameSpace())
+    return DINameSpace(DbgNode).getContext();
+
+  assert((isFile() || isCompileUnit()) && "Unhandled type of scope.");
+  return DIScope();
+}
+
 StringRef DIScope::getFilename() const {
   if (!DbgNode)
     return StringRef();
@@ -865,18 +918,8 @@ void DebugInfoFinder::processModule(const Module &M) {
 
 /// processLocation - Process DILocation.
 void DebugInfoFinder::processLocation(DILocation Loc) {
-  if (!Loc.Verify()) return;
-  DIDescriptor S(Loc.getScope());
-  if (S.isCompileUnit())
-    addCompileUnit(DICompileUnit(S));
-  else if (S.isSubprogram())
-    processSubprogram(DISubprogram(S));
-  else if (S.isLexicalBlock())
-    processLexicalBlock(DILexicalBlock(S));
-  else if (S.isLexicalBlockFile()) {
-    DILexicalBlockFile DBF = DILexicalBlockFile(S);
-    processLexicalBlock(DILexicalBlock(DBF.getScope()));
-  }
+  if (!Loc) return;
+  processScope(Loc.getScope());
   processLocation(Loc.getOrigLocation());
 }
 
@@ -976,12 +1019,13 @@ void DebugInfoFinder::processValue(const DbgValueInst *DVI) {
 
   if (!NodesSeen.insert(DV))
     return;
+  processScope(DIVariable(N).getContext());
   processType(DIVariable(N).getType());
 }
 
 /// addType - Add type into Tys.
 bool DebugInfoFinder::addType(DIType DT) {
-  if (!DT.isValid())
+  if (!DT)
     return false;
 
   if (!NodesSeen.insert(DT))
@@ -993,9 +1037,8 @@ bool DebugInfoFinder::addType(DIType DT) {
 
 /// addCompileUnit - Add compile unit into CUs.
 bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
-  if (!CU.Verify())
+  if (!CU)
     return false;
-
   if (!NodesSeen.insert(CU))
     return false;
 
@@ -1005,7 +1048,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
 
 /// addGlobalVariable - Add global variable into GVs.
 bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
-  if (!DIDescriptor(DIG).isGlobalVariable())
+  if (!DIG)
     return false;
 
   if (!NodesSeen.insert(DIG))
@@ -1017,7 +1060,7 @@ bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
 
 // addSubprogram - Add subprgoram into SPs.
 bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
-  if (!DIDescriptor(SP).isSubprogram())
+  if (!SP)
     return false;
 
   if (!NodesSeen.insert(SP))
@@ -1030,6 +1073,10 @@ bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
 bool DebugInfoFinder::addScope(DIScope Scope) {
   if (!Scope)
     return false;
+  // FIXME: Ocaml binding generates a scope with no content, we treat it
+  // as null for now.
+  if (Scope->getNumOperands() == 0)
+    return false;
   if (!NodesSeen.insert(Scope))
     return false;
   Scopes.push_back(Scope);