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);
|
||||
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
|
||||
@@ -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 variant_part = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateVariantPart(
|
||||
@@ -1702,7 +1718,7 @@ fn prepare_enum_metadata(
|
||||
DIFlags::FlagZero,
|
||||
discriminator_metadata,
|
||||
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.
|
||||
|
||||
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