// 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() ||
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 {
// 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
}
}
-/// 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
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;
}
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
/// 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;
}
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;
}
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;
}
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;
}
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;
}
/// 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 &&
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();
/// 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());
}
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))
/// addCompileUnit - Add compile unit into CUs.
bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
- if (!CU.Verify())
+ if (!CU)
return false;
-
if (!NodesSeen.insert(CU))
return false;
/// addGlobalVariable - Add global variable into GVs.
bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
- if (!DIDescriptor(DIG).isGlobalVariable())
+ if (!DIG)
return false;
if (!NodesSeen.insert(DIG))
// addSubprogram - Add subprgoram into SPs.
bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
- if (!DIDescriptor(SP).isSubprogram())
+ if (!SP)
return false;
if (!NodesSeen.insert(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);