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)
|
||||
}
|
||||
ty::TyUnion(..) => {
|
||||
unimplemented!();
|
||||
prepare_union_metadata(cx,
|
||||
t,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::TyTuple(ref elements) => {
|
||||
prepare_tuple_metadata(cx,
|
||||
|
@ -1038,6 +1041,7 @@ enum MemberDescriptionFactory<'tcx> {
|
|||
StructMDF(StructMemberDescriptionFactory<'tcx>),
|
||||
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
||||
EnumMDF(EnumMemberDescriptionFactory<'tcx>),
|
||||
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
|
||||
VariantMDF(VariantMemberDescriptionFactory<'tcx>)
|
||||
}
|
||||
|
||||
|
@ -1054,6 +1058,9 @@ impl<'tcx> MemberDescriptionFactory<'tcx> {
|
|||
EnumMDF(ref this) => {
|
||||
this.create_member_descriptions(cx)
|
||||
}
|
||||
UnionMDF(ref this) => {
|
||||
this.create_member_descriptions(cx)
|
||||
}
|
||||
VariantMDF(ref this) => {
|
||||
this.create_member_descriptions(cx)
|
||||
}
|
||||
|
@ -1154,7 +1161,6 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
//=-----------------------------------------------------------------------------
|
||||
// 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
|
||||
|
@ -1798,6 +1864,42 @@ fn create_struct_stub(cx: &CrateContext,
|
|||
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.
|
||||
///
|
||||
/// 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
Reference in a new issue