Skip to content

Commit ae25518

Browse files
authored
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](https://github.com/rust-lang/rust/blob/f21dee2c6179276321a88a63300dce74ff707e92/src/rustllvm/PassWrapper.cpp#L1101).
2 parents be6b4c0 + 3a5a8a5 commit ae25518

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/librustc_codegen_llvm/debuginfo/metadata.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ impl TypeMap<'ll, 'tcx> {
189189
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
190190
UniqueTypeId(interner_key)
191191
}
192+
193+
// Get the unique type id string for an enum variant part.
194+
// Variant parts are not types and shouldn't really have their own id,
195+
// but it makes set_members_of_composite_type() simpler.
196+
fn get_unique_type_id_str_of_enum_variant_part<'a>(&mut self,
197+
enum_type_id: UniqueTypeId) -> &str {
198+
let variant_part_type_id = format!("{}_variant_part",
199+
self.get_unique_type_id_as_string(enum_type_id));
200+
let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
201+
self.unique_id_interner.get(interner_key)
202+
}
192203
}
193204

194205
// A description of some recursive type. It can either be already finished (as
@@ -1689,6 +1700,11 @@ fn prepare_enum_metadata(
16891700
},
16901701
};
16911702

1703+
let variant_part_unique_type_id_str = SmallCStr::new(
1704+
debug_context(cx).type_map
1705+
.borrow_mut()
1706+
.get_unique_type_id_str_of_enum_variant_part(unique_type_id)
1707+
);
16921708
let empty_array = create_DIArray(DIB(cx), &[]);
16931709
let variant_part = unsafe {
16941710
llvm::LLVMRustDIBuilderCreateVariantPart(
@@ -1702,7 +1718,7 @@ fn prepare_enum_metadata(
17021718
DIFlags::FlagZero,
17031719
discriminator_metadata,
17041720
empty_array,
1705-
unique_type_id_str.as_ptr())
1721+
variant_part_unique_type_id_str.as_ptr())
17061722
};
17071723

17081724
// The variant part must be wrapped in a struct according to DWARF.

src/test/debuginfo/enum-thinlto.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// ignore-tidy-linelength
2+
3+
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
4+
// min-system-llvm-version: 8.0
5+
// min-gdb-version: 8.2
6+
7+
// compile-flags:-g -Z thinlto
8+
9+
// === GDB TESTS ===================================================================================
10+
11+
// gdb-command:run
12+
13+
// gdb-command:print *abc
14+
// gdbr-check:$1 = enum_thinlto::ABC::TheA{x: 0, y: 8970181431921507452}
15+
16+
// === LLDB TESTS ==================================================================================
17+
18+
// lldb-command:run
19+
20+
// lldb-command:print *abc
21+
// lldbg-check:(enum_thinlto::ABC) $0 = ABC { }
22+
23+
#![allow(unused_variables)]
24+
#![feature(omit_gdb_pretty_printer_section)]
25+
#![omit_gdb_pretty_printer_section]
26+
27+
// The first element is to ensure proper alignment, irrespective of the machines word size. Since
28+
// the size of the discriminant value is machine dependent, this has be taken into account when
29+
// datatype layout should be predictable as in this case.
30+
#[derive(Debug)]
31+
enum ABC {
32+
TheA { x: i64, y: i64 },
33+
TheB (i64, i32, i32),
34+
}
35+
36+
fn main() {
37+
let abc = ABC::TheA { x: 0, y: 0x7c7c_7c7c_7c7c_7c7c };
38+
39+
f(&abc);
40+
}
41+
42+
fn f(abc: &ABC) {
43+
zzz(); // #break
44+
45+
println!("{:?}", abc);
46+
}
47+
48+
fn zzz() {()}

0 commit comments

Comments
 (0)