From e0108a47abcd1977670aa2ca0e5e88321cf789bf Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 11 Jul 2013 12:51:47 +0200 Subject: [PATCH] debuginfo: DI generation for enums uses adt::represent_type() now. --- src/librustc/middle/trans/adt.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 156 +++++++++++++++++++++++ src/test/debug-info/borrowed-enum.rs | 2 +- src/test/debug-info/managed-enum.rs | 2 +- src/test/debug-info/struct-in-enum.rs | 2 +- src/test/debug-info/struct-style-enum.rs | 2 +- src/test/debug-info/tuple-style-enum.rs | 2 +- src/test/debug-info/unique-enum.rs | 2 +- 8 files changed, 163 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 821242d64c96..fd38ec39bb1b 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -94,7 +94,7 @@ pub enum Repr { } /// For structs, and struct-like parts of anything fancier. -struct Struct { +pub struct Struct { size: u64, align: u64, packed: bool, diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 48ab05661781..93a6ab4fcd90 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -50,6 +50,7 @@ use middle::trans::common::*; use middle::trans::machine; use middle::trans::type_of; use middle::trans::type_::Type; +use middle::trans::adt; use middle::trans; use middle::ty; use util::ppaux::ty_to_str; @@ -560,6 +561,161 @@ fn create_tuple_metadata(cx: &mut CrateContext, span); } +// The stage0 snapshot does not yet support the fixes from PR #7557, so there are two versions of +// following function for now +#[cfg(not(stage0))] +fn create_enum_metadata(cx: &mut CrateContext, + enum_type: ty::t, + enum_def_id: ast::def_id, + substs: &ty::substs, + span: span) + -> DIType { + + let enum_name = ty_to_str(cx.tcx, enum_type); + + // For empty enums there is an early exit. Just describe it as an empty struct with the + // appropriate type name + if ty::type_is_empty(cx.tcx, enum_type) { + return create_composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span); + } + + // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be + // needed in all of the following cases. + let discriminant_llvm_type = Type::enum_discrim(cx); + let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type); + + assert!(Type::enum_discrim(cx) == cx.int_type); + let discriminant_type_metadata = get_or_create_type_metadata(cx, ty::mk_int(), span); + + let variants : &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); + + let enumerators_metadata : ~[DIDescriptor] = variants + .iter() + .transform(|v| { + let name : &str = cx.sess.str_of(v.name); + let discriminant_value = v.disr_val as c_ulonglong; + + do name.as_c_str |name| { unsafe { + llvm::LLVMDIBuilderCreateEnumerator( + DIB(cx), + name, + discriminant_value) + }} + }) + .collect(); + + let loc = span_start(cx, span); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + + let discriminant_type_metadata = do enum_name.as_c_str |enum_name| { unsafe { + llvm::LLVMDIBuilderCreateEnumerationType( + DIB(cx), + file_metadata, + enum_name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(discriminant_size), + bytes_to_bits(discriminant_align), + create_DIArray(DIB(cx), enumerators_metadata), + discriminant_type_metadata) + }}; + + let type_rep = adt::represent_type(cx, enum_type); + + match *type_rep { + adt::CEnum(*) => { + return discriminant_type_metadata; + } + adt::Univariant(ref struct_def, _destroyed_flag) => { + assert!(variants.len() == 1); + return create_adt_struct_metadata(cx, struct_def, variants[0], None, span); + } + adt::General(ref struct_defs) => { + let variants_member_metadata : ~[DIDescriptor] = do struct_defs + .iter() + .enumerate() + .transform |(i, struct_def)| { + let variant_type_metadata = create_adt_struct_metadata( + cx, + struct_def, + variants[i], + Some(discriminant_type_metadata), + span); + + do "".as_c_str |name| { unsafe { + llvm::LLVMDIBuilderCreateMemberType( + DIB(cx), + file_metadata, + name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(struct_def.size as uint), + bytes_to_bits(struct_def.align as uint), + bytes_to_bits(0), + 0, + variant_type_metadata) + }} + }.collect(); + + let enum_llvm_type = type_of::type_of(cx, enum_type); + let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type); + + return do enum_name.as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateUnionType( + DIB(cx), + file_metadata, + enum_name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(enum_type_size), + bytes_to_bits(enum_type_align), + 0, // Flags + create_DIArray(DIB(cx), variants_member_metadata), + 0) // RuntimeLang + }}; + } + _ => { return ptr::null(); } + } + + fn create_adt_struct_metadata(cx: &mut CrateContext, + struct_def: &adt::Struct, + variant_info: &ty::VariantInfo, + discriminant_type_metadata: Option, + span: span) + -> DICompositeType + { + let arg_llvm_types : ~[Type] = do struct_def.fields.map |&ty| { type_of::type_of(cx, ty) }; + let arg_metadata : ~[DIType] = do struct_def.fields.iter().enumerate() + .transform |(i, &ty)| { + match discriminant_type_metadata { + Some(metadata) if i == 0 => metadata, + _ => get_or_create_type_metadata(cx, ty, span) + } + }.collect(); + + let mut arg_names = match variant_info.arg_names { + Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() }, + None => do variant_info.args.map |_| { ~"" } + }; + + if (discriminant_type_metadata.is_some()) { + arg_names.insert(0, ~""); + } + + let variant_llvm_type = Type::struct_(arg_llvm_types, struct_def.packed); + let variant_name : &str = cx.sess.str_of(variant_info.name); + + return create_composite_type_metadata( + cx, + variant_llvm_type, + variant_name, + arg_llvm_types, + arg_names, + arg_metadata, + span); + } +} + +#[cfg(stage0)] fn create_enum_metadata(cx: &mut CrateContext, enum_type: ty::t, enum_def_id: ast::def_id, diff --git a/src/test/debug-info/borrowed-enum.rs b/src/test/debug-info/borrowed-enum.rs index c73cddf0d89a..8c9a7799a293 100644 --- a/src/test/debug-info/borrowed-enum.rs +++ b/src/test/debug-info/borrowed-enum.rs @@ -22,7 +22,7 @@ // check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}} // debugger:print *univariant_ref -// check:$3 = {{4820353753753434}} +// check:$3 = {4820353753753434} // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when diff --git a/src/test/debug-info/managed-enum.rs b/src/test/debug-info/managed-enum.rs index 794a362e5731..1a3600a7d8cb 100644 --- a/src/test/debug-info/managed-enum.rs +++ b/src/test/debug-info/managed-enum.rs @@ -22,7 +22,7 @@ // check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}} // debugger:print univariant->val -// check:$3 = {{-9747455}} +// check:$3 = {-9747455} // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when diff --git a/src/test/debug-info/struct-in-enum.rs b/src/test/debug-info/struct-in-enum.rs index c8ad621f6f0d..6d4a40e193fa 100644 --- a/src/test/debug-info/struct-in-enum.rs +++ b/src/test/debug-info/struct-in-enum.rs @@ -21,7 +21,7 @@ // check:$2 = {{Case2, 0, {x = 286331153, y = 286331153, z = 4369}}, {Case2, 0, 1229782938247303441, 4369}} // debugger:print univariant -// check:$3 = {{{x = 123, y = 456, z = 789}}} +// check:$3 = {{x = 123, y = 456, z = 789}} struct Struct { x: u32, diff --git a/src/test/debug-info/struct-style-enum.rs b/src/test/debug-info/struct-style-enum.rs index 2be15e0f80f2..972772b07d28 100644 --- a/src/test/debug-info/struct-style-enum.rs +++ b/src/test/debug-info/struct-style-enum.rs @@ -24,7 +24,7 @@ // check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}} // debugger:print univariant -// check:$4 = {{a = -1}} +// check:$4 = {a = -1} // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs index 43b97a9bbfc4..66e64a1e20aa 100644 --- a/src/test/debug-info/tuple-style-enum.rs +++ b/src/test/debug-info/tuple-style-enum.rs @@ -24,7 +24,7 @@ // check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}} // debugger:print univariant -// check:$4 = {{-1}} +// check:$4 = {-1} // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when diff --git a/src/test/debug-info/unique-enum.rs b/src/test/debug-info/unique-enum.rs index c231ea5a42bb..443f641a8585 100644 --- a/src/test/debug-info/unique-enum.rs +++ b/src/test/debug-info/unique-enum.rs @@ -22,7 +22,7 @@ // check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}} // debugger:print *univariant -// check:$3 = {{123234}} +// check:$3 = {123234} // The first element is to ensure proper alignment, irrespective of the machines word size. Since // the size of the discriminant value is machine dependent, this has be taken into account when