Skip to content

Commit

Permalink
Generate debuginfo for unions
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Sep 3, 2016
1 parent d9b332b commit 079c390
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 2 deletions.
106 changes: 104 additions & 2 deletions src/librustc_trans/debuginfo/metadata.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -1038,6 +1041,7 @@ enum MemberDescriptionFactory<'tcx> {
StructMDF(StructMemberDescriptionFactory<'tcx>),
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
EnumMDF(EnumMemberDescriptionFactory<'tcx>),
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
VariantMDF(VariantMemberDescriptionFactory<'tcx>)
}

Expand All @@ -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)
}
Expand Down Expand Up @@ -1154,7 +1161,6 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
)
}


//=-----------------------------------------------------------------------------
// Tuples
//=-----------------------------------------------------------------------------
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
49 changes: 49 additions & 0 deletions src/test/debuginfo/union-smoke.rs
@@ -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() {()}

0 comments on commit 079c390

Please sign in to comment.