forked from OSchip/llvm-project
Debug Info: Add basic support for external types references.
This is a necessary prerequisite for bootstrapping the emission of debug info inside modules. - Adds a FlagExternalTypeRef to DICompositeType. External types must have a unique identifier. - External type references are emitted using a forward declaration with a DW_AT_signature([DW_FORM_ref_sig8]) based on the UID. http://reviews.llvm.org/D9612 llvm-svn: 242302
This commit is contained in:
parent
5b4acbd6b6
commit
ee5feafc0f
|
@ -384,6 +384,13 @@ namespace llvm {
|
|||
DITypeRefArray ParameterTypes,
|
||||
unsigned Flags = 0);
|
||||
|
||||
/// Create an external type reference.
|
||||
/// \param Tag Dwarf TAG.
|
||||
/// \param File File in which the type is defined.
|
||||
/// \param UniqueIdentifier A unique identifier for the type.
|
||||
DICompositeType *createExternalTypeRef(unsigned Tag, DIFile *File,
|
||||
StringRef UniqueIdentifier);
|
||||
|
||||
/// Create a new DIType* with "artificial" flag set.
|
||||
DIType *createArtificialType(DIType *Ty);
|
||||
|
||||
|
|
|
@ -32,5 +32,6 @@ HANDLE_DI_FLAG((1 << 11), Vector)
|
|||
HANDLE_DI_FLAG((1 << 12), StaticMember)
|
||||
HANDLE_DI_FLAG((1 << 13), LValueReference)
|
||||
HANDLE_DI_FLAG((1 << 14), RValueReference)
|
||||
HANDLE_DI_FLAG((1 << 15), ExternalTypeRef)
|
||||
|
||||
#undef HANDLE_DI_FLAG
|
||||
|
|
|
@ -574,6 +574,7 @@ public:
|
|||
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
|
||||
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
|
||||
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
|
||||
bool isExternalTypeRef() const { return getFlags() & FlagExternalTypeRef; }
|
||||
|
||||
DITypeRef getRef() const { return DITypeRef::get(this); }
|
||||
|
||||
|
|
|
@ -467,7 +467,10 @@ void DwarfDebug::beginModule() {
|
|||
for (auto *Ty : CUNode->getRetainedTypes()) {
|
||||
// The retained types array by design contains pointers to
|
||||
// MDNodes rather than DIRefs. Unique them here.
|
||||
CU.getOrCreateTypeDIE(cast<DIType>(resolve(Ty->getRef())));
|
||||
DIType *RT = cast<DIType>(resolve(Ty->getRef()));
|
||||
if (!RT->isExternalTypeRef())
|
||||
// There is no point in force-emitting a forward declaration.
|
||||
CU.getOrCreateTypeDIE(RT);
|
||||
}
|
||||
// Emit imported_modules last so that the relevant context is already
|
||||
// available.
|
||||
|
@ -1884,7 +1887,7 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
|
|||
return &SplitTypeUnitFileTable;
|
||||
}
|
||||
|
||||
static uint64_t makeTypeSignature(StringRef Identifier) {
|
||||
uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
|
||||
MD5 Hash;
|
||||
Hash.update(Identifier);
|
||||
// ... take the least significant 8 bytes and return those. Our MD5
|
||||
|
|
|
@ -544,6 +544,9 @@ public:
|
|||
/// Process end of an instruction.
|
||||
void endInstruction() override;
|
||||
|
||||
/// Perform an MD5 checksum of \p Identifier and return the lower 64 bits.
|
||||
static uint64_t makeTypeSignature(StringRef Identifier);
|
||||
|
||||
/// Add a DIE to the set of types that we're going to pull into
|
||||
/// type units.
|
||||
void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
|
||||
|
|
|
@ -277,6 +277,13 @@ void DwarfUnit::addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type) {
|
|||
dwarf::DW_FORM_ref_sig8, DIETypeSignature(Type));
|
||||
}
|
||||
|
||||
void DwarfUnit::addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute,
|
||||
StringRef Identifier) {
|
||||
uint64_t Signature = DD->makeTypeSignature(Identifier);
|
||||
Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_ref_sig8,
|
||||
DIEInteger(Signature));
|
||||
}
|
||||
|
||||
void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute,
|
||||
DIEEntry Entry) {
|
||||
const DIE *DieCU = Die.getUnitOrNull();
|
||||
|
@ -700,7 +707,8 @@ DIE *DwarfUnit::createTypeDIE(const DICompositeType *Ty) {
|
|||
|
||||
constructTypeDIE(TyDIE, cast<DICompositeType>(Ty));
|
||||
|
||||
updateAcceleratorTables(Context, Ty, TyDIE);
|
||||
if (!Ty->isExternalTypeRef())
|
||||
updateAcceleratorTables(Context, Ty, TyDIE);
|
||||
return &TyDIE;
|
||||
}
|
||||
|
||||
|
@ -899,6 +907,13 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) {
|
|||
}
|
||||
|
||||
void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
|
||||
if (CTy->isExternalTypeRef()) {
|
||||
StringRef Identifier = CTy->getIdentifier();
|
||||
assert(!Identifier.empty() && "external type ref without identifier");
|
||||
addFlag(Buffer, dwarf::DW_AT_declaration);
|
||||
return addDIETypeSignature(Buffer, dwarf::DW_AT_signature, Identifier);
|
||||
}
|
||||
|
||||
// Add name if not anonymous or intermediate type.
|
||||
StringRef Name = CTy->getName();
|
||||
|
||||
|
|
|
@ -228,7 +228,11 @@ public:
|
|||
/// Add a DIE attribute data and value.
|
||||
void addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry Entry);
|
||||
|
||||
/// Add a type's DW_AT_signature and set the declaration flag.
|
||||
void addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type);
|
||||
/// Add an attribute containing the type signature for a unique identifier.
|
||||
void addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute,
|
||||
StringRef Identifier);
|
||||
|
||||
/// Add block data.
|
||||
void addBlock(DIE &Die, dwarf::Attribute Attribute, DIELoc *Block);
|
||||
|
|
|
@ -435,6 +435,18 @@ DISubroutineType *DIBuilder::createSubroutineType(DIFile *File,
|
|||
return DISubroutineType::get(VMContext, Flags, ParameterTypes);
|
||||
}
|
||||
|
||||
DICompositeType *DIBuilder::createExternalTypeRef(unsigned Tag, DIFile *File,
|
||||
StringRef UniqueIdentifier) {
|
||||
assert(!UniqueIdentifier.empty() && "external type ref without uid");
|
||||
auto *CTy =
|
||||
DICompositeType::get(VMContext, Tag, "", nullptr, 0, nullptr, nullptr, 0,
|
||||
0, 0, DINode::FlagExternalTypeRef, nullptr, 0,
|
||||
nullptr, nullptr, UniqueIdentifier);
|
||||
// Types with unique IDs need to be in the type map.
|
||||
retainType(CTy);
|
||||
return CTy;
|
||||
}
|
||||
|
||||
DICompositeType *DIBuilder::createEnumerationType(
|
||||
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
; REQUIRES: object-emission
|
||||
; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
|
||||
; Manually derived by externalizing the composite types from:
|
||||
;
|
||||
; namespace N { class B; }
|
||||
; using N::B;
|
||||
; class A;
|
||||
; A *a;
|
||||
;
|
||||
; Test the direct use of an external type.
|
||||
; CHECK: DW_TAG_variable
|
||||
; CHECK: DW_AT_type [DW_FORM_ref4] {{.*}}{[[PTR:.*]]}
|
||||
; CHECK: [[PTR]]: DW_TAG_pointer_type
|
||||
; CHECK: DW_AT_type [DW_FORM_ref4] {{.*}}{[[A:.*]]}
|
||||
; CHECK: [[A]]: DW_TAG_class_type
|
||||
; CHECK: DW_AT_declaration [DW_FORM_flag] (0x01)
|
||||
; CHECK: DW_AT_signature [DW_FORM_ref_sig8] (0x4e834ea939695c24)
|
||||
; CHECK: [[B:.*]]: DW_TAG_class_type
|
||||
; CHECK: DW_AT_declaration [DW_FORM_flag] (0x01)
|
||||
; CHECK: DW_AT_signature [DW_FORM_ref_sig8] (0x942e51c7addda5f7)
|
||||
; CHECK: DW_TAG_imported_declaration
|
||||
; CHECK: DW_AT_import [DW_FORM_ref4] {{.*}}[[B]]
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
%class.A = type opaque
|
||||
|
||||
@a = global %class.A* null, align 8
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!13, !14, !15}
|
||||
!llvm.ident = !{!16}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 242039) (llvm/trunk 242046)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3, globals: !5, imports: !11)
|
||||
!1 = !DIFile(filename: "test.cpp", directory: "/")
|
||||
!2 = !{}
|
||||
!3 = !{!4, !9}
|
||||
!4 = !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !1, flags: DIFlagExternalTypeRef, identifier: "_ZTS1A")
|
||||
!5 = !{!6}
|
||||
!6 = !DIGlobalVariable(name: "a", scope: !0, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, variable: %class.A** @a)
|
||||
!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1A", size: 64, align: 64)
|
||||
!8 = !DICompositeType(tag: DW_TAG_class_type, name: "B", file: !1, flags: DIFlagExternalTypeRef, identifier: "_ZTS1B")
|
||||
!9 = !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !1, flags: DIFlagExternalTypeRef, identifier: "_ZTSN1N1BE")
|
||||
!10 = !DINamespace(name: "N", scope: null, file: !1, line: 1)
|
||||
!11 = !{!12}
|
||||
!12 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !"_ZTSN1N1BE", line: 4)
|
||||
!13 = !{i32 2, !"Dwarf Version", i32 2}
|
||||
!14 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!15 = !{i32 1, !"PIC Level", i32 2}
|
||||
!16 = !{!"clang version 3.7.0 (trunk 242039) (llvm/trunk 242046)"}
|
Loading…
Reference in New Issue