Skip to content

Commit 079c390

Browse files
committed
Generate debuginfo for unions
1 parent d9b332b commit 079c390

File tree

2 files changed

+153
-2
lines changed

2 files changed

+153
-2
lines changed

src/librustc_trans/debuginfo/metadata.rs

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
786786
usage_site_span).finalize(cx)
787787
}
788788
ty::TyUnion(..) => {
789-
unimplemented!();
789+
prepare_union_metadata(cx,
790+
t,
791+
unique_type_id,
792+
usage_site_span).finalize(cx)
790793
}
791794
ty::TyTuple(ref elements) => {
792795
prepare_tuple_metadata(cx,
@@ -1038,6 +1041,7 @@ enum MemberDescriptionFactory<'tcx> {
10381041
StructMDF(StructMemberDescriptionFactory<'tcx>),
10391042
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
10401043
EnumMDF(EnumMemberDescriptionFactory<'tcx>),
1044+
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
10411045
VariantMDF(VariantMemberDescriptionFactory<'tcx>)
10421046
}
10431047

@@ -1054,6 +1058,9 @@ impl<'tcx> MemberDescriptionFactory<'tcx> {
10541058
EnumMDF(ref this) => {
10551059
this.create_member_descriptions(cx)
10561060
}
1061+
UnionMDF(ref this) => {
1062+
this.create_member_descriptions(cx)
1063+
}
10571064
VariantMDF(ref this) => {
10581065
this.create_member_descriptions(cx)
10591066
}
@@ -1154,7 +1161,6 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
11541161
)
11551162
}
11561163

1157-
11581164
//=-----------------------------------------------------------------------------
11591165
// Tuples
11601166
//=-----------------------------------------------------------------------------
@@ -1209,6 +1215,66 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
12091215
)
12101216
}
12111217

1218+
//=-----------------------------------------------------------------------------
1219+
// Unions
1220+
//=-----------------------------------------------------------------------------
1221+
1222+
struct UnionMemberDescriptionFactory<'tcx> {
1223+
variant: ty::VariantDef<'tcx>,
1224+
substs: &'tcx Substs<'tcx>,
1225+
span: Span,
1226+
}
1227+
1228+
impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
1229+
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
1230+
-> Vec<MemberDescription> {
1231+
self.variant.fields.iter().map(|field| {
1232+
let fty = monomorphize::field_ty(cx.tcx(), self.substs, field);
1233+
MemberDescription {
1234+
name: field.name.to_string(),
1235+
llvm_type: type_of::type_of(cx, fty),
1236+
type_metadata: type_metadata(cx, fty, self.span),
1237+
offset: FixedMemberOffset { bytes: 0 },
1238+
flags: FLAGS_NONE,
1239+
}
1240+
}).collect()
1241+
}
1242+
}
1243+
1244+
fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
1245+
union_type: Ty<'tcx>,
1246+
unique_type_id: UniqueTypeId,
1247+
span: Span)
1248+
-> RecursiveTypeDescription<'tcx> {
1249+
let union_name = compute_debuginfo_type_name(cx, union_type, false);
1250+
let union_llvm_type = type_of::in_memory_type_of(cx, union_type);
1251+
1252+
let (union_def_id, variant, substs) = match union_type.sty {
1253+
ty::TyUnion(def, substs) => (def.did, def.struct_variant(), substs),
1254+
_ => bug!("prepare_union_metadata on a non-union")
1255+
};
1256+
1257+
let (containing_scope, _) = get_namespace_and_span_for_item(cx, union_def_id);
1258+
1259+
let union_metadata_stub = create_union_stub(cx,
1260+
union_llvm_type,
1261+
&union_name,
1262+
unique_type_id,
1263+
containing_scope);
1264+
1265+
create_and_register_recursive_type_forward_declaration(
1266+
cx,
1267+
union_type,
1268+
unique_type_id,
1269+
union_metadata_stub,
1270+
union_llvm_type,
1271+
UnionMDF(UnionMemberDescriptionFactory {
1272+
variant: variant,
1273+
substs: substs,
1274+
span: span,
1275+
})
1276+
)
1277+
}
12121278

12131279
//=-----------------------------------------------------------------------------
12141280
// Enums
@@ -1798,6 +1864,42 @@ fn create_struct_stub(cx: &CrateContext,
17981864
return metadata_stub;
17991865
}
18001866

1867+
fn create_union_stub(cx: &CrateContext,
1868+
union_llvm_type: Type,
1869+
union_type_name: &str,
1870+
unique_type_id: UniqueTypeId,
1871+
containing_scope: DIScope)
1872+
-> DICompositeType {
1873+
let (union_size, union_align) = size_and_align_of(cx, union_llvm_type);
1874+
1875+
let unique_type_id_str = debug_context(cx).type_map
1876+
.borrow()
1877+
.get_unique_type_id_as_string(unique_type_id);
1878+
let name = CString::new(union_type_name).unwrap();
1879+
let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
1880+
let metadata_stub = unsafe {
1881+
// LLVMRustDIBuilderCreateUnionType() wants an empty array. A null
1882+
// pointer will lead to hard to trace and debug LLVM assertions
1883+
// later on in llvm/lib/IR/Value.cpp.
1884+
let empty_array = create_DIArray(DIB(cx), &[]);
1885+
1886+
llvm::LLVMRustDIBuilderCreateUnionType(
1887+
DIB(cx),
1888+
containing_scope,
1889+
name.as_ptr(),
1890+
unknown_file_metadata(cx),
1891+
UNKNOWN_LINE_NUMBER,
1892+
bytes_to_bits(union_size),
1893+
bytes_to_bits(union_align),
1894+
0, // Flags
1895+
empty_array,
1896+
0, // RuntimeLang
1897+
unique_type_id.as_ptr())
1898+
};
1899+
1900+
return metadata_stub;
1901+
}
1902+
18011903
/// Creates debug information for the given global variable.
18021904
///
18031905
/// Adds the created metadata nodes directly to the crate's IR.

src/test/debuginfo/union-smoke.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// min-lldb-version: 310
12+
13+
// compile-flags:-g
14+
15+
// === GDB TESTS ===================================================================================
16+
17+
// gdb-command:run
18+
// gdb-command:print u
19+
// gdb-check:$1 = {a = 11 '\v', b = 11}
20+
// gdb-command:print union_smoke::SU
21+
// gdb-check:$2 = {a = 10 '\n', b = 10}
22+
23+
// === LLDB TESTS ==================================================================================
24+
25+
// lldb-command:run
26+
// lldb-command:print a
27+
// lldb-check:[...]$0 = {a = 11 '\v', b = 11}
28+
// lldb-command:print union_smoke::SU
29+
// lldb-check:[...]$1 = {a = 10 '\n', b = 10}
30+
31+
#![allow(unused)]
32+
#![feature(omit_gdb_pretty_printer_section)]
33+
#![omit_gdb_pretty_printer_section]
34+
#![feature(untagged_unions)]
35+
36+
union U {
37+
a: u8,
38+
b: u64,
39+
}
40+
41+
static SU: U = U { a: 10 };
42+
43+
fn main() {
44+
let u = U { b: 11 };
45+
46+
zzz(); // #break
47+
}
48+
49+
fn zzz() {()}

0 commit comments

Comments
 (0)