debuginfo: Fix debuginfo for Box<T> where T is unsized.
Before this fix, the debuginfo for the fields was generated from the struct defintion of Box<T>, but (at least at the moment) the compiler pretends that Box<T> is just a (fat) pointer, so the fields need to be `pointer` and `vtable` instead of `__0: Unique<T>` and `__1: Allocator`. This is meant as a temporary mitigation until we can make sure that simply treating Box as a regular struct in debuginfo does not cause too much breakage in the ecosystem.
This commit is contained in:
parent
600a80dedf
commit
e169261a6f
2 changed files with 33 additions and 5 deletions
|
@ -166,6 +166,13 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||||
pointee_type: Ty<'tcx>,
|
pointee_type: Ty<'tcx>,
|
||||||
unique_type_id: UniqueTypeId<'tcx>,
|
unique_type_id: UniqueTypeId<'tcx>,
|
||||||
) -> DINodeCreationResult<'ll> {
|
) -> DINodeCreationResult<'ll> {
|
||||||
|
// The debuginfo generated by this function is only valid if `ptr_type` is really just
|
||||||
|
// a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
|
||||||
|
debug_assert_eq!(
|
||||||
|
cx.size_and_align_of(ptr_type),
|
||||||
|
cx.size_and_align_of(cx.tcx.mk_mut_ptr(pointee_type))
|
||||||
|
);
|
||||||
|
|
||||||
let pointee_type_di_node = type_di_node(cx, pointee_type);
|
let pointee_type_di_node = type_di_node(cx, pointee_type);
|
||||||
|
|
||||||
return_if_di_node_created_in_meantime!(cx, unique_type_id);
|
return_if_di_node_created_in_meantime!(cx, unique_type_id);
|
||||||
|
@ -212,7 +219,17 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
),
|
),
|
||||||
|cx, owner| {
|
|cx, owner| {
|
||||||
let layout = cx.layout_of(ptr_type);
|
// FIXME: If this fat pointer is a `Box` then we don't want to use its
|
||||||
|
// type layout and instead use the layout of the raw pointer inside
|
||||||
|
// of it.
|
||||||
|
// The proper way to handle this is to not treat Box as a pointer
|
||||||
|
// at all and instead emit regular struct debuginfo for it. We just
|
||||||
|
// need to make sure that we don't break existing debuginfo consumers
|
||||||
|
// by doing that (at least not without a warning period).
|
||||||
|
let layout_type =
|
||||||
|
if ptr_type.is_box() { cx.tcx.mk_mut_ptr(pointee_type) } else { ptr_type };
|
||||||
|
|
||||||
|
let layout = cx.layout_of(layout_type);
|
||||||
let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
||||||
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,17 @@
|
||||||
// gdbg-check:$3 = {pointer = [...], vtable = [...]}
|
// gdbg-check:$3 = {pointer = [...], vtable = [...]}
|
||||||
// gdbr-check:$3 = &unsized::Foo<dyn core::fmt::Debug> {pointer: [...], vtable: [...]}
|
// gdbr-check:$3 = &unsized::Foo<dyn core::fmt::Debug> {pointer: [...], vtable: [...]}
|
||||||
|
|
||||||
|
// gdb-command:print _box
|
||||||
|
// gdbg-check:$4 = {pointer = [...], vtable = [...]}
|
||||||
|
// gdbr-check:$4 = alloc::boxed::Box<unsized::Foo<dyn core::fmt::Debug>, alloc::alloc::Global> {pointer: [...], vtable: [...]}
|
||||||
|
|
||||||
// gdb-command:print tuple_slice
|
// gdb-command:print tuple_slice
|
||||||
// gdbg-check:$4 = {data_ptr = [...], length = 2}
|
// gdbg-check:$5 = {data_ptr = [...], length = 2}
|
||||||
// gdbr-check:$4 = &(i32, i32, [i32]) {data_ptr: [...], length: 2}
|
// gdbr-check:$5 = &(i32, i32, [i32]) {data_ptr: [...], length: 2}
|
||||||
|
|
||||||
// gdb-command:print tuple_dyn
|
// gdb-command:print tuple_dyn
|
||||||
// gdbg-check:$5 = {pointer = [...], vtable = [...]}
|
// gdbg-check:$6 = {pointer = [...], vtable = [...]}
|
||||||
// gdbr-check:$5 = &(i32, i32, dyn core::fmt::Debug) {pointer: [...], vtable: [...]}
|
// gdbr-check:$6 = &(i32, i32, dyn core::fmt::Debug) {pointer: [...], vtable: [...]}
|
||||||
|
|
||||||
// === CDB TESTS ===================================================================================
|
// === CDB TESTS ===================================================================================
|
||||||
|
|
||||||
|
@ -42,6 +46,12 @@
|
||||||
// cdb-check: [+0x000] pointer : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
|
// cdb-check: [+0x000] pointer : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
|
||||||
// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
|
// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
|
||||||
|
|
||||||
|
// cdb-command:dx _box
|
||||||
|
// cdb-check:
|
||||||
|
// cdb-check:_box [Type: alloc::boxed::Box<unsized::Foo<dyn$<core::fmt::Debug> >,alloc::alloc::Global>]
|
||||||
|
// cdb-check:[+0x000] pointer : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
|
||||||
|
// cdb-check:[...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
|
||||||
|
|
||||||
// cdb-command:dx tuple_slice
|
// cdb-command:dx tuple_slice
|
||||||
// cdb-check:tuple_slice [Type: ref$<tuple$<i32,i32,slice$<i32> > >]
|
// cdb-check:tuple_slice [Type: ref$<tuple$<i32,i32,slice$<i32> > >]
|
||||||
// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$<i32,i32,slice$<i32> > *]
|
// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$<i32,i32,slice$<i32> > *]
|
||||||
|
@ -69,6 +79,7 @@ fn main() {
|
||||||
let a: &Foo<[u8]> = &foo.value;
|
let a: &Foo<[u8]> = &foo.value;
|
||||||
let b: &Foo<Foo<[u8]>> = &foo;
|
let b: &Foo<Foo<[u8]>> = &foo;
|
||||||
let c: &Foo<dyn std::fmt::Debug> = &Foo { value: 7i32 };
|
let c: &Foo<dyn std::fmt::Debug> = &Foo { value: 7i32 };
|
||||||
|
let _box: Box<Foo<dyn std::fmt::Debug>> = Box::new(Foo { value: 8i32 });
|
||||||
|
|
||||||
// Also check unsized tuples
|
// Also check unsized tuples
|
||||||
let tuple_slice: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
let tuple_slice: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue