[PATCH] Let replaceVTableHolder accept any type
Tom Tromey via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 16 12:25:14 PDT 2017
In Rust, a trait can be implemented for any type, and if a trait
object pointer is used for the type, then a virtual table will be
emitted for that trait/type combination.
We would like debuggers to be able to inspect trait objects, which
requires finding the concrete type associated with a given vtable.
This patch changes LLVM so that any type can be passed to
replaceVTableHolder. This allows the Rust compiler to emit the needed
debug info -- associating a vtable with the concrete type for which it
was emitted.
This is a DWARF extension: DWARF only specifies the meaning of
DW_AT_containing_type in one specific situation. This style of DWARF
extension is routine, though, and LLVM already has one such case for
DW_AT_containing_type.
---
include/llvm/IR/DIBuilder.h | 4 +--
lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 5 +--
lib/IR/DIBuilder.cpp | 2 +-
.../DebugInfo/Generic/containing-type-extension.ll | 38 ++++++++++++++++++++++
unittests/IR/MetadataTest.cpp | 4 +++
5 files changed, 48 insertions(+), 5 deletions(-)
create mode 100644 test/DebugInfo/Generic/containing-type-extension.ll
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index eac48d9..3c2074d 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -757,12 +757,12 @@ namespace llvm {
const DILocation *DL,
Instruction *InsertBefore);
- /// Replace the vtable holder in the given composite type.
+ /// Replace the vtable holder in the given type.
///
/// If this creates a self reference, it may orphan some unresolved cycles
/// in the operands of \c T, so \a DIBuilder needs to track that.
void replaceVTableHolder(DICompositeType *&T,
- DICompositeType *VTableHolder);
+ DIType *VTableHolder);
/// Replace arrays on a composite type.
///
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 784a1d5..ce74659 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -960,8 +960,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
// This is outside the DWARF spec, but GDB expects a DW_AT_containing_type
// inside C++ composite types to point to the base class with the vtable.
- if (auto *ContainingType =
- dyn_cast_or_null<DICompositeType>(resolve(CTy->getVTableHolder())))
+ // Rust uses DW_AT_containing_type to link a vtable to the type
+ // for which it was created.
+ if (auto *ContainingType = resolve(CTy->getVTableHolder()))
addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
*getOrCreateTypeDIE(ContainingType));
diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp
index 18979a8..837b1ec 100644
--- a/lib/IR/DIBuilder.cpp
+++ b/lib/IR/DIBuilder.cpp
@@ -874,7 +874,7 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(
}
void DIBuilder::replaceVTableHolder(DICompositeType *&T,
- DICompositeType *VTableHolder) {
+ DIType *VTableHolder) {
{
TypedTrackingMDRef<DICompositeType> N(T);
N->replaceVTableHolder(VTableHolder);
diff --git a/test/DebugInfo/Generic/containing-type-extension.ll b/test/DebugInfo/Generic/containing-type-extension.ll
new file mode 100644
index 0000000..7f39f6b
--- /dev/null
+++ b/test/DebugInfo/Generic/containing-type-extension.ll
@@ -0,0 +1,38 @@
+; REQUIRES: object-emission
+
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
+; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s
+
+; Make sure we correctly handle context of a subprogram being a type identifier.
+; CHECK: [[SP:.*]]: DW_TAG_structure_type
+; CHECK: DW_AT_containing_type [DW_FORM_ref4] (cu + {{.*}}
+; CHECK: DW_AT_name [DW_FORM_strp] {{.*}}= "vtable")
+
+; The code doesn't actually matter.
+define i32 @main() #0 !dbg !4 {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval
+ ret i32 0, !dbg !10
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 (trunk 185475)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !15, imports: !2)
+!1 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "main", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped | DIFlagMainSubprogram, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !5, type: !6, variables: !2)
+!5 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test")
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8}
+!8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !DILocation(line: 7, scope: !4)
+!11 = !{i32 1, !"Debug Info Version", i32 3}
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "vtable", size: 8, align: 8, elements: !2, identifier: "vtable", vtableHolder: !8)
+!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
+!14 = !DIGlobalVariable(name: "vtable", linkageName: "vtable", scope: null, file: !1, line: 1, type: !12, isLocal: true, isDefinition: true)
+!15 = !{!13}
diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp
index 3ab0ad4..03e2d27 100644
--- a/unittests/IR/MetadataTest.cpp
+++ b/unittests/IR/MetadataTest.cpp
@@ -1314,6 +1314,10 @@ TEST_F(DICompositeTypeTest, replaceOperands) {
EXPECT_EQ(nullptr, N->getVTableHolder());
N->replaceVTableHolder(VTableHolder);
EXPECT_EQ(VTableHolder, N->getVTableHolder());
+ // As an extension, the containing type can be anything.
+ DIType *BasicType = getBasicType("basic");
+ N->replaceVTableHolder(BasicType);
+ EXPECT_EQ(BasicType, N->getVTableHolder());
N->replaceVTableHolder(nullptr);
EXPECT_EQ(nullptr, N->getVTableHolder());
--
2.9.5
More information about the llvm-commits
mailing list