mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-26 09:18:56 +00:00
Debug Info: Use identifier to reference DIType in base type field of
ptr_to_member. We introduce a new class DITypeRef that represents a reference to a DIType. It wraps around a Value*, which can be either an identifier in MDString or an actual MDNode. The class has a helper function "resolve" that finds the actual MDNode for a given DITypeRef. We specialize getFieldAs to return a field that is a reference to a DIType. To correctly access the base type field of ptr_to_member, getClassType now calls getFieldAs<DITypeRef> to return a DITypeRef. Also add a typedef for DITypeIdentifierMap and a helper generateDITypeIdentifierMap in DebugInfo.h. In DwarfDebug.cpp, we keep a DITypeIdentifierMap and call generateDITypeIdentifierMap to actually populate the map. Verifier is updated accordingly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190081 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
#ifndef LLVM_DEBUGINFO_H
|
#ifndef LLVM_DEBUGINFO_H
|
||||||
#define LLVM_DEBUGINFO_H
|
#define LLVM_DEBUGINFO_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -45,12 +46,19 @@ namespace llvm {
|
|||||||
class DILexicalBlockFile;
|
class DILexicalBlockFile;
|
||||||
class DIVariable;
|
class DIVariable;
|
||||||
class DIType;
|
class DIType;
|
||||||
|
class DITypeRef;
|
||||||
class DIObjCProperty;
|
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.
|
/// DIDescriptor - A thin wraper around MDNode to access encoded debug info.
|
||||||
/// This should not be stored in a container, because the underlying MDNode
|
/// This should not be stored in a container, because the underlying MDNode
|
||||||
/// may change in certain situations.
|
/// may change in certain situations.
|
||||||
class DIDescriptor {
|
class DIDescriptor {
|
||||||
|
// Befriends DITypeRef so DITypeRef can befriend the protected member
|
||||||
|
// function: getFieldAs<DITypeRef>.
|
||||||
|
friend class DITypeRef;
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
FlagPrivate = 1 << 0,
|
FlagPrivate = 1 << 0,
|
||||||
@@ -143,6 +151,23 @@ namespace llvm {
|
|||||||
void dump() const;
|
void dump() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Specialize getFieldAs to handle fields that are references to DITypes.
|
||||||
|
template <>
|
||||||
|
DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
|
||||||
|
|
||||||
|
/// Represents reference to a DIType, abstracts over direct and
|
||||||
|
/// identifier-based metadata type references.
|
||||||
|
class DITypeRef {
|
||||||
|
friend DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
|
||||||
|
|
||||||
|
/// TypeVal can be either a MDNode or a MDString, in the latter,
|
||||||
|
/// MDString specifies the type identifier.
|
||||||
|
const Value *TypeVal;
|
||||||
|
explicit DITypeRef(const Value *V);
|
||||||
|
public:
|
||||||
|
DIType resolve(const DITypeIdentifierMap &Map) const;
|
||||||
|
};
|
||||||
|
|
||||||
/// DISubrange - This is used to represent ranges, for array bounds.
|
/// DISubrange - This is used to represent ranges, for array bounds.
|
||||||
class DISubrange : public DIDescriptor {
|
class DISubrange : public DIDescriptor {
|
||||||
friend class DIDescriptor;
|
friend class DIDescriptor;
|
||||||
@@ -296,9 +321,9 @@ namespace llvm {
|
|||||||
/// associated with one.
|
/// associated with one.
|
||||||
MDNode *getObjCProperty() const;
|
MDNode *getObjCProperty() const;
|
||||||
|
|
||||||
DIType getClassType() const {
|
DITypeRef getClassType() const {
|
||||||
assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
|
assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
|
||||||
return getFieldAs<DIType>(10);
|
return getFieldAs<DITypeRef>(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant *getConstant() const {
|
Constant *getConstant() const {
|
||||||
@@ -720,6 +745,9 @@ namespace llvm {
|
|||||||
/// cleanseInlinedVariable - Remove inlined scope from the variable.
|
/// cleanseInlinedVariable - Remove inlined scope from the variable.
|
||||||
DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
|
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
|
/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To
|
||||||
/// list debug info MDNodes used by an instruction, DebugInfoFinder uses
|
/// list debug info MDNodes used by an instruction, DebugInfoFinder uses
|
||||||
/// processDeclare, processValue and processLocation to handle DbgDeclareInst,
|
/// processDeclare, processValue and processLocation to handle DbgDeclareInst,
|
||||||
|
@@ -905,7 +905,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
|
|||||||
|
|
||||||
if (Tag == dwarf::DW_TAG_ptr_to_member_type)
|
if (Tag == dwarf::DW_TAG_ptr_to_member_type)
|
||||||
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
|
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
|
||||||
getOrCreateTypeDIE(DTy.getClassType()));
|
getOrCreateTypeDIE(DD->resolve(DTy.getClassType())));
|
||||||
// Add source line info if available and TyDesc is not a forward declaration.
|
// Add source line info if available and TyDesc is not a forward declaration.
|
||||||
if (!DTy.isForwardDecl())
|
if (!DTy.isForwardDecl())
|
||||||
addSourceLine(&Buffer, DTy);
|
addSourceLine(&Buffer, DTy);
|
||||||
|
@@ -823,6 +823,7 @@ void DwarfDebug::beginModule() {
|
|||||||
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
|
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
|
||||||
if (!CU_Nodes)
|
if (!CU_Nodes)
|
||||||
return;
|
return;
|
||||||
|
TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
|
||||||
|
|
||||||
// Emit initial sections so we can reference labels later.
|
// Emit initial sections so we can reference labels later.
|
||||||
emitSectionLabels();
|
emitSectionLabels();
|
||||||
@@ -2631,3 +2632,8 @@ void DwarfDebug::emitDebugStrDWO() {
|
|||||||
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
|
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
|
||||||
OffSec, StrSym);
|
OffSec, StrSym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the MDNode for the given type reference.
|
||||||
|
MDNode *DwarfDebug::resolve(DITypeRef TRef) const {
|
||||||
|
return TRef.resolve(TypeIdentifierMap);
|
||||||
|
}
|
||||||
|
@@ -450,6 +450,9 @@ class DwarfDebug {
|
|||||||
// Holder for the skeleton information.
|
// Holder for the skeleton information.
|
||||||
DwarfUnits SkeletonHolder;
|
DwarfUnits SkeletonHolder;
|
||||||
|
|
||||||
|
// Maps from a type identifier to the actual MDNode.
|
||||||
|
DITypeIdentifierMap TypeIdentifierMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void addScopeVariable(LexicalScope *LS, DbgVariable *Var);
|
void addScopeVariable(LexicalScope *LS, DbgVariable *Var);
|
||||||
@@ -679,6 +682,10 @@ public:
|
|||||||
|
|
||||||
/// Returns the Dwarf Version.
|
/// Returns the Dwarf Version.
|
||||||
unsigned getDwarfVersion() const { return DwarfVersion; }
|
unsigned getDwarfVersion() const { return DwarfVersion; }
|
||||||
|
|
||||||
|
/// Find the MDNode for the given type reference.
|
||||||
|
MDNode *resolve(DITypeRef TRef) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
} // End of namespace llvm
|
} // End of namespace llvm
|
||||||
|
|
||||||
|
@@ -75,6 +75,18 @@ void DIBuilder::finalize() {
|
|||||||
DIType(TempImportedModules).replaceAllUsesWith(IMs);
|
DIType(TempImportedModules).replaceAllUsesWith(IMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use the type identifier instead of the actual MDNode if possible,
|
||||||
|
/// to help type uniquing. This function returns the identifier if it
|
||||||
|
/// exists for the given type, otherwise returns the MDNode.
|
||||||
|
static Value *getTypeIdentifier(DIType T) {
|
||||||
|
if (!T.isCompositeType())
|
||||||
|
return T;
|
||||||
|
DICompositeType DTy(T);
|
||||||
|
if (!DTy.getIdentifier())
|
||||||
|
return T;
|
||||||
|
return DTy.getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return
|
/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return
|
||||||
/// N.
|
/// N.
|
||||||
static MDNode *getNonCompileUnitScope(MDNode *N) {
|
static MDNode *getNonCompileUnitScope(MDNode *N) {
|
||||||
@@ -322,7 +334,7 @@ DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy,
|
|||||||
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
|
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
|
||||||
ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
|
ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
|
||||||
PointeeTy,
|
PointeeTy,
|
||||||
Base
|
getTypeIdentifier(Base)
|
||||||
};
|
};
|
||||||
return DIDerivedType(MDNode::get(VMContext, Elts));
|
return DIDerivedType(MDNode::get(VMContext, Elts));
|
||||||
}
|
}
|
||||||
|
@@ -425,6 +425,17 @@ static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) {
|
|||||||
return !Fld || isa<MDString>(Fld);
|
return !Fld || isa<MDString>(Fld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if a value can be a TypeRef.
|
||||||
|
static bool isTypeRef(const Value *Val) {
|
||||||
|
return !Val || isa<MDString>(Val) || isa<MDNode>(Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if a field at position Elt of a MDNode can be a TypeRef.
|
||||||
|
static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) {
|
||||||
|
Value *Fld = getField(DbgNode, Elt);
|
||||||
|
return isTypeRef(Fld);
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify - Verify that a type descriptor is well formed.
|
/// Verify - Verify that a type descriptor is well formed.
|
||||||
bool DIType::Verify() const {
|
bool DIType::Verify() const {
|
||||||
if (!isType())
|
if (!isType())
|
||||||
@@ -470,8 +481,8 @@ bool DIDerivedType::Verify() const {
|
|||||||
if (!fieldIsMDNode(DbgNode, 9))
|
if (!fieldIsMDNode(DbgNode, 9))
|
||||||
return false;
|
return false;
|
||||||
if (getTag() == dwarf::DW_TAG_ptr_to_member_type)
|
if (getTag() == dwarf::DW_TAG_ptr_to_member_type)
|
||||||
// Make sure ClassType @ field 10 is MDNode.
|
// Make sure ClassType @ field 10 is a TypeRef.
|
||||||
if (!fieldIsMDNode(DbgNode, 10))
|
if (!fieldIsTypeRef(DbgNode, 10))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return isDerivedType() && DbgNode->getNumOperands() >= 10 &&
|
return isDerivedType() && DbgNode->getNumOperands() >= 10 &&
|
||||||
@@ -923,6 +934,32 @@ bool llvm::isSubprogramContext(const MDNode *Context) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update DITypeIdentifierMap by going through retained types of each CU.
|
||||||
|
DITypeIdentifierMap llvm::generateDITypeIdentifierMap(
|
||||||
|
const NamedMDNode *CU_Nodes) {
|
||||||
|
DITypeIdentifierMap Map;
|
||||||
|
for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) {
|
||||||
|
DICompileUnit CU(CU_Nodes->getOperand(CUi));
|
||||||
|
DIArray Retain = CU.getRetainedTypes();
|
||||||
|
for (unsigned Ti = 0, Te = Retain.getNumElements(); Ti != Te; ++Ti) {
|
||||||
|
if (!Retain.getElement(Ti).isCompositeType())
|
||||||
|
continue;
|
||||||
|
DICompositeType Ty(Retain.getElement(Ti));
|
||||||
|
if (MDString *TypeId = Ty.getIdentifier()) {
|
||||||
|
// Definition has priority over declaration.
|
||||||
|
// Try to insert (TypeId, Ty) to Map.
|
||||||
|
std::pair<DITypeIdentifierMap::iterator, bool> P =
|
||||||
|
Map.insert(std::make_pair(TypeId, Ty));
|
||||||
|
// If TypeId already exists in Map and this is a definition, replace
|
||||||
|
// whatever we had (declaration or definition) with the definition.
|
||||||
|
if (!P.second && !Ty.isForwardDecl())
|
||||||
|
P.first->second = Ty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Map;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// DebugInfoFinder implementations.
|
// DebugInfoFinder implementations.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -1378,3 +1415,34 @@ void DIVariable::printExtendedName(raw_ostream &OS) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DITypeRef::DITypeRef(const Value *V) : TypeVal(V) {
|
||||||
|
assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a DITypeIdentifierMap, tries to find the corresponding
|
||||||
|
/// DIType for a DITypeRef.
|
||||||
|
DIType DITypeRef::resolve(const DITypeIdentifierMap &Map) const {
|
||||||
|
if (!TypeVal)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (const MDNode *MD = dyn_cast<MDNode>(TypeVal)) {
|
||||||
|
assert(DIType(MD).isType() &&
|
||||||
|
"MDNode in DITypeRef should be a DIType.");
|
||||||
|
return MD;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MDString *MS = cast<MDString>(TypeVal);
|
||||||
|
// 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 Iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specialize getFieldAs to handle fields that are references to DITypes.
|
||||||
|
template <>
|
||||||
|
DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const {
|
||||||
|
return DITypeRef(getField(DbgNode, Elt));
|
||||||
|
}
|
||||||
|
29
test/DebugInfo/tu-member-pointer.ll
Normal file
29
test/DebugInfo/tu-member-pointer.ll
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
; REQUIRES: object-emission
|
||||||
|
|
||||||
|
; RUN: llc -filetype=obj -O0 < %s > %t
|
||||||
|
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
|
||||||
|
; CHECK: [[TYPE:.*]]: DW_TAG_base_type
|
||||||
|
; CHECK: DW_TAG_ptr_to_member_type
|
||||||
|
; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + {{.*}} => {[[TYPE]]})
|
||||||
|
; IR generated from clang -g with the following source:
|
||||||
|
; struct Foo {
|
||||||
|
; int e;
|
||||||
|
; };
|
||||||
|
; int Foo:*x = 0;
|
||||||
|
|
||||||
|
@x = global i64 -1, align 8
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!10}
|
||||||
|
|
||||||
|
!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !2, metadata !5, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [foo.cpp] [DW_LANG_C_plus_plus]
|
||||||
|
!1 = metadata !{metadata !"foo.cpp", metadata !"."}
|
||||||
|
!2 = metadata !{i32 0}
|
||||||
|
!3 = metadata !{metadata !4}
|
||||||
|
!4 = metadata !{i32 786451, metadata !1, null, metadata !"Foo", i32 1, i64 0, i64 0, i32 0, i32 4, null, null, i32 0, null, null, metadata !"_ZTS3Foo"} ; [ DW_TAG_structure_type ] [Foo] [line 1, size 0, align 0, offset 0] [decl] [from ]
|
||||||
|
!5 = metadata !{metadata !6}
|
||||||
|
!6 = metadata !{i32 786484, i32 0, null, metadata !"x", metadata !"x", metadata !"", metadata !7, i32 4, metadata !8, i32 0, i32 1, i64* @x, null} ; [ DW_TAG_variable ] [x] [line 4] [def]
|
||||||
|
!7 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [foo.cpp]
|
||||||
|
!8 = metadata !{i32 786463, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !9, metadata !"_ZTS3Foo"} ; [ DW_TAG_ptr_to_member_type ] [line 0, size 0, align 0, offset 0] [from int]
|
||||||
|
!9 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
|
||||||
|
!10 = metadata !{i32 2, metadata !"Dwarf Version", i32 2}
|
Reference in New Issue
Block a user