Generate debuginfo for unions
This commit is contained in:
parent
d9b332bd69
commit
079c390d50
2 changed files with 153 additions and 2 deletions
|
@ -786,7 +786,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
usage_site_span).finalize(cx)
|
usage_site_span).finalize(cx)
|
||||||
}
|
}
|
||||||
ty::TyUnion(..) => {
|
ty::TyUnion(..) => {
|
||||||
unimplemented!();
|
prepare_union_metadata(cx,
|
||||||
|
t,
|
||||||
|
unique_type_id,
|
||||||
|
usage_site_span).finalize(cx)
|
||||||
}
|
}
|
||||||
ty::TyTuple(ref elements) => {
|
ty::TyTuple(ref elements) => {
|
||||||
prepare_tuple_metadata(cx,
|
prepare_tuple_metadata(cx,
|
||||||
|
@ -1038,6 +1041,7 @@ enum MemberDescriptionFactory<'tcx> {
|
||||||
StructMDF(StructMemberDescriptionFactory<'tcx>),
|
StructMDF(StructMemberDescriptionFactory<'tcx>),
|
||||||
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
||||||
EnumMDF(EnumMemberDescriptionFactory<'tcx>),
|
EnumMDF(EnumMemberDescriptionFactory<'tcx>),
|
||||||
|
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
|
||||||
VariantMDF(VariantMemberDescriptionFactory<'tcx>)
|
VariantMDF(VariantMemberDescriptionFactory<'tcx>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,6 +1058,9 @@ impl<'tcx> MemberDescriptionFactory<'tcx> {
|
||||||
EnumMDF(ref this) => {
|
EnumMDF(ref this) => {
|
||||||
this.create_member_descriptions(cx)
|
this.create_member_descriptions(cx)
|
||||||
}
|
}
|
||||||
|
UnionMDF(ref this) => {
|
||||||
|
this.create_member_descriptions(cx)
|
||||||
|
}
|
||||||
VariantMDF(ref this) => {
|
VariantMDF(ref this) => {
|
||||||
this.create_member_descriptions(cx)
|
this.create_member_descriptions(cx)
|
||||||
}
|
}
|
||||||
|
@ -1154,7 +1161,6 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=-----------------------------------------------------------------------------
|
//=-----------------------------------------------------------------------------
|
||||||
// Tuples
|
// Tuples
|
||||||
//=-----------------------------------------------------------------------------
|
//=-----------------------------------------------------------------------------
|
||||||
|
@ -1209,6 +1215,66 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=-----------------------------------------------------------------------------
|
||||||
|
// Unions
|
||||||
|
//=-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct UnionMemberDescriptionFactory<'tcx> {
|
||||||
|
variant: ty::VariantDef<'tcx>,
|
||||||
|
substs: &'tcx Substs<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
|
||||||
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
||||||
|
-> Vec<MemberDescription> {
|
||||||
|
self.variant.fields.iter().map(|field| {
|
||||||
|
let fty = monomorphize::field_ty(cx.tcx(), self.substs, field);
|
||||||
|
MemberDescription {
|
||||||
|
name: field.name.to_string(),
|
||||||
|
llvm_type: type_of::type_of(cx, fty),
|
||||||
|
type_metadata: type_metadata(cx, fty, self.span),
|
||||||
|
offset: FixedMemberOffset { bytes: 0 },
|
||||||
|
flags: FLAGS_NONE,
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
|
union_type: Ty<'tcx>,
|
||||||
|
unique_type_id: UniqueTypeId,
|
||||||
|
span: Span)
|
||||||
|
-> RecursiveTypeDescription<'tcx> {
|
||||||
|
let union_name = compute_debuginfo_type_name(cx, union_type, false);
|
||||||
|
let union_llvm_type = type_of::in_memory_type_of(cx, union_type);
|
||||||
|
|
||||||
|
let (union_def_id, variant, substs) = match union_type.sty {
|
||||||
|
ty::TyUnion(def, substs) => (def.did, def.struct_variant(), substs),
|
||||||
|
_ => bug!("prepare_union_metadata on a non-union")
|
||||||
|
};
|
||||||
|
|
||||||
|
let (containing_scope, _) = get_namespace_and_span_for_item(cx, union_def_id);
|
||||||
|
|
||||||
|
let union_metadata_stub = create_union_stub(cx,
|
||||||
|
union_llvm_type,
|
||||||
|
&union_name,
|
||||||
|
unique_type_id,
|
||||||
|
containing_scope);
|
||||||
|
|
||||||
|
create_and_register_recursive_type_forward_declaration(
|
||||||
|
cx,
|
||||||
|
union_type,
|
||||||
|
unique_type_id,
|
||||||
|
union_metadata_stub,
|
||||||
|
union_llvm_type,
|
||||||
|
UnionMDF(UnionMemberDescriptionFactory {
|
||||||
|
variant: variant,
|
||||||
|
substs: substs,
|
||||||
|
span: span,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
//=-----------------------------------------------------------------------------
|
//=-----------------------------------------------------------------------------
|
||||||
// Enums
|
// Enums
|
||||||
|
@ -1798,6 +1864,42 @@ fn create_struct_stub(cx: &CrateContext,
|
||||||
return metadata_stub;
|
return metadata_stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_union_stub(cx: &CrateContext,
|
||||||
|
union_llvm_type: Type,
|
||||||
|
union_type_name: &str,
|
||||||
|
unique_type_id: UniqueTypeId,
|
||||||
|
containing_scope: DIScope)
|
||||||
|
-> DICompositeType {
|
||||||
|
let (union_size, union_align) = size_and_align_of(cx, union_llvm_type);
|
||||||
|
|
||||||
|
let unique_type_id_str = debug_context(cx).type_map
|
||||||
|
.borrow()
|
||||||
|
.get_unique_type_id_as_string(unique_type_id);
|
||||||
|
let name = CString::new(union_type_name).unwrap();
|
||||||
|
let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
|
||||||
|
let metadata_stub = unsafe {
|
||||||
|
// LLVMRustDIBuilderCreateUnionType() wants an empty array. A null
|
||||||
|
// pointer will lead to hard to trace and debug LLVM assertions
|
||||||
|
// later on in llvm/lib/IR/Value.cpp.
|
||||||
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||||
|
|
||||||
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||||
|
DIB(cx),
|
||||||
|
containing_scope,
|
||||||
|
name.as_ptr(),
|
||||||
|
unknown_file_metadata(cx),
|
||||||
|
UNKNOWN_LINE_NUMBER,
|
||||||
|
bytes_to_bits(union_size),
|
||||||
|
bytes_to_bits(union_align),
|
||||||
|
0, // Flags
|
||||||
|
empty_array,
|
||||||
|
0, // RuntimeLang
|
||||||
|
unique_type_id.as_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
return metadata_stub;
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates debug information for the given global variable.
|
/// Creates debug information for the given global variable.
|
||||||
///
|
///
|
||||||
/// Adds the created metadata nodes directly to the crate's IR.
|
/// Adds the created metadata nodes directly to the crate's IR.
|
||||||
|
|
49
src/test/debuginfo/union-smoke.rs
Normal file
49
src/test/debuginfo/union-smoke.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// min-lldb-version: 310
|
||||||
|
|
||||||
|
// compile-flags:-g
|
||||||
|
|
||||||
|
// === GDB TESTS ===================================================================================
|
||||||
|
|
||||||
|
// gdb-command:run
|
||||||
|
// gdb-command:print u
|
||||||
|
// gdb-check:$1 = {a = 11 '\v', b = 11}
|
||||||
|
// gdb-command:print union_smoke::SU
|
||||||
|
// gdb-check:$2 = {a = 10 '\n', b = 10}
|
||||||
|
|
||||||
|
// === LLDB TESTS ==================================================================================
|
||||||
|
|
||||||
|
// lldb-command:run
|
||||||
|
// lldb-command:print a
|
||||||
|
// lldb-check:[...]$0 = {a = 11 '\v', b = 11}
|
||||||
|
// lldb-command:print union_smoke::SU
|
||||||
|
// lldb-check:[...]$1 = {a = 10 '\n', b = 10}
|
||||||
|
|
||||||
|
#![allow(unused)]
|
||||||
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
#![feature(untagged_unions)]
|
||||||
|
|
||||||
|
union U {
|
||||||
|
a: u8,
|
||||||
|
b: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
static SU: U = U { a: 10 };
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let u = U { b: 11 };
|
||||||
|
|
||||||
|
zzz(); // #break
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zzz() {()}
|
Loading…
Add table
Add a link
Reference in a new issue