Rollup merge of #59380 - philipc:thinlto-variant, r=michaelwoerister
Fix invalid DWARF for enums when using ThinLTO
We were setting the same identifier for both the DW_TAG_structure_type
and the DW_TAG_variant_part. This becomes a problem when using ThinLTO
becauses it uses the identifier as a key for a map of types that is used
to delete duplicates based on the ODR, so one of them is deleted as a
duplicate, resulting in invalid DWARF.
The DW_TAG_variant_part isn't a standalone type, so it doesn't need
an identifier. Fix by omitting its identifier.
ODR uniquing is [enabled here](f21dee2c61/src/rustllvm/PassWrapper.cpp (L1101)).
This commit is contained in:
@@ -189,6 +189,17 @@ impl TypeMap<'ll, 'tcx> {
|
|||||||
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
|
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
|
||||||
UniqueTypeId(interner_key)
|
UniqueTypeId(interner_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the unique type id string for an enum variant part.
|
||||||
|
// Variant parts are not types and shouldn't really have their own id,
|
||||||
|
// but it makes set_members_of_composite_type() simpler.
|
||||||
|
fn get_unique_type_id_str_of_enum_variant_part<'a>(&mut self,
|
||||||
|
enum_type_id: UniqueTypeId) -> &str {
|
||||||
|
let variant_part_type_id = format!("{}_variant_part",
|
||||||
|
self.get_unique_type_id_as_string(enum_type_id));
|
||||||
|
let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
|
||||||
|
self.unique_id_interner.get(interner_key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A description of some recursive type. It can either be already finished (as
|
// A description of some recursive type. It can either be already finished (as
|
||||||
@@ -1689,6 +1700,11 @@ fn prepare_enum_metadata(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let variant_part_unique_type_id_str = SmallCStr::new(
|
||||||
|
debug_context(cx).type_map
|
||||||
|
.borrow_mut()
|
||||||
|
.get_unique_type_id_str_of_enum_variant_part(unique_type_id)
|
||||||
|
);
|
||||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||||
let variant_part = unsafe {
|
let variant_part = unsafe {
|
||||||
llvm::LLVMRustDIBuilderCreateVariantPart(
|
llvm::LLVMRustDIBuilderCreateVariantPart(
|
||||||
@@ -1702,7 +1718,7 @@ fn prepare_enum_metadata(
|
|||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
discriminator_metadata,
|
discriminator_metadata,
|
||||||
empty_array,
|
empty_array,
|
||||||
unique_type_id_str.as_ptr())
|
variant_part_unique_type_id_str.as_ptr())
|
||||||
};
|
};
|
||||||
|
|
||||||
// The variant part must be wrapped in a struct according to DWARF.
|
// The variant part must be wrapped in a struct according to DWARF.
|
||||||
|
|||||||
48
src/test/debuginfo/enum-thinlto.rs
Normal file
48
src/test/debuginfo/enum-thinlto.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
|
||||||
|
// min-system-llvm-version: 8.0
|
||||||
|
// min-gdb-version: 8.2
|
||||||
|
|
||||||
|
// compile-flags:-g -Z thinlto
|
||||||
|
|
||||||
|
// === GDB TESTS ===================================================================================
|
||||||
|
|
||||||
|
// gdb-command:run
|
||||||
|
|
||||||
|
// gdb-command:print *abc
|
||||||
|
// gdbr-check:$1 = enum_thinlto::ABC::TheA{x: 0, y: 8970181431921507452}
|
||||||
|
|
||||||
|
// === LLDB TESTS ==================================================================================
|
||||||
|
|
||||||
|
// lldb-command:run
|
||||||
|
|
||||||
|
// lldb-command:print *abc
|
||||||
|
// lldbg-check:(enum_thinlto::ABC) $0 = ABC { }
|
||||||
|
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
|
// The first element is to ensure proper alignment, irrespective of the machines word size. Since
|
||||||
|
// the size of the discriminant value is machine dependent, this has be taken into account when
|
||||||
|
// datatype layout should be predictable as in this case.
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ABC {
|
||||||
|
TheA { x: i64, y: i64 },
|
||||||
|
TheB (i64, i32, i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let abc = ABC::TheA { x: 0, y: 0x7c7c_7c7c_7c7c_7c7c };
|
||||||
|
|
||||||
|
f(&abc);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f(abc: &ABC) {
|
||||||
|
zzz(); // #break
|
||||||
|
|
||||||
|
println!("{:?}", abc);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
||||||
Reference in New Issue
Block a user