From 976d7a53cbb35d2f7814d2d13dcc55a304d5e7a7 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 26 Jun 2013 16:00:42 +0200 Subject: [PATCH 01/26] debuginfo: Began refactoring of composite type handling. --- src/librustc/lib/llvm.rs | 8 + src/librustc/middle/trans/debuginfo.rs | 213 ++++++++++++++---- src/librustc/middle/trans/machine.rs | 45 ++++ src/test/debug-info/box.rs | 10 +- src/test/debug-info/boxed-struct.rs | 60 +++++ src/test/debug-info/struct-with-destructor.rs | 4 +- 6 files changed, 293 insertions(+), 47 deletions(-) create mode 100644 src/test/debug-info/boxed-struct.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index aeb2017c9d647..215c002eec8d2 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1635,6 +1635,14 @@ pub mod llvm { #[fast_ffi] pub unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; + + /** Computes the byte offset of the indexed struct element for a target. */ + #[fast_ffi] + pub unsafe fn LLVMOffsetOfElement(TD: TargetDataRef, + StructTy: TypeRef, + Element: c_uint) + -> c_ulonglong; + /** * Returns the minimum alignment of a type when part of a call frame. */ diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 00b59d187bfd6..74d8825d6d468 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -49,6 +49,7 @@ use lib::llvm::debuginfo::*; use middle::trans::common::*; use middle::trans::machine; use middle::trans::type_of; +use middle::trans::type_::Type; use middle::trans; use middle::ty; use util::ppaux::ty_to_str; @@ -65,6 +66,8 @@ use syntax::codemap::span; use syntax::{ast, codemap, ast_util, ast_map}; use syntax::parse::token; + + static DW_LANG_RUST: int = 0x9000; static AutoVariableTag: int = 256; @@ -594,17 +597,102 @@ fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field] -> DICompositeType { debug!("create_struct: %?", ty::get(struct_type)); + let struct_name = ty_to_str(cx.tcx, struct_type); + let struct_llvm_type = type_of::type_of(cx, struct_type); + + let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty)); + let field_names = fields.map(|field| cx.sess.str_of(field.ident).to_owned()); + let field_types_metadata = fields.map(|field| create_ty(cx, field.mt.ty, span)); + + return create_composite_type( + cx, + struct_llvm_type, + struct_name, + field_llvm_types, + field_names, + field_types_metadata, + span); +} + +fn create_tuple(cx: &mut CrateContext, + tuple_type: ty::t, + component_types: &[ty::t], + span: span) + -> DICompositeType { + + let tuple_name = (cx.sess.str_of((dbg_cx(cx).names)("tuple"))).to_owned(); + let tuple_llvm_type = type_of::type_of(cx, tuple_type); + // Create a vec of empty strings. A vec::build_n() function would be nice for this. + let mut component_names : ~[~str] = vec::with_capacity(component_types.len()); + component_names.grow_fn(component_types.len(), |_| ~""); + + let component_llvm_types = component_types.map(|it| type_of::type_of(cx, *it)); + let component_types_metadata = component_types.map(|it| create_ty(cx, *it, span)); + + return create_composite_type( + cx, + tuple_llvm_type, + tuple_name, + component_llvm_types, + component_names, + component_types_metadata, + span); +} + +fn create_composite_type(cx: &mut CrateContext, + composite_llvm_type: Type, + composite_type_name: &str, + member_llvm_types: &[Type], + member_names: &[~str], + member_type_metadata: &[DIType], + span: span) + -> DICompositeType { + let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); + let file_metadata = create_file(cx, loc.file.name); + + let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type); + let composite_align = machine::llalign_of_min(cx, composite_llvm_type); + + let member_metadata = create_DIArray( + DIB(cx), + // transform the ty::t array of components into an array of DIEs + do vec::mapi(member_llvm_types) |i, member_llvm_type| { + let member_size = machine::llsize_of_alloc(cx, *member_llvm_type); + let member_align = machine::llalign_of_min(cx, *member_llvm_type); + let member_offset = machine::llelement_offset(cx, composite_llvm_type, i); + let member_name : &str = member_names[i]; + + do member_name.as_c_str |member_name| { unsafe { + llvm::LLVMDIBuilderCreateMemberType( + DIB(cx), + file_metadata, + member_name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(member_size), + bytes_to_bits(member_align), + bytes_to_bits(member_offset), + 0, + member_type_metadata[i]) + }} + }); - let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, struct_type), file_md, loc.line); - for fields.iter().advance |field| { - let field_t = field.mt.ty; - let ty_md = create_ty(cx, field_t, span); - let (size, align) = size_and_align_of(cx, field_t); - scx.add_member(cx.sess.str_of(field.ident), loc.line, size, align, ty_md); - } - return scx.finalize(); + return do composite_type_name.as_c_str |name| { unsafe { + llvm::LLVMDIBuilderCreateStructType( + DIB(cx), + file_metadata, + name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(composite_size), + bytes_to_bits(composite_align), + 0, + ptr::null(), + member_metadata, + 0, + ptr::null()) + }}; } // returns (void* type as a ValueRef, size in bytes, align in bytes) @@ -639,30 +727,83 @@ fn create_tuple(cx: &mut CrateContext, tuple_type: ty::t, elements: &[ty::t], sp return scx.finalize(); } -fn create_boxed_type(cx: &mut CrateContext, contents: ty::t, - span: span, boxed: DIType) -> DICompositeType { - debug!("create_boxed_type: %?", ty::get(contents)); - - let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); - let int_t = ty::mk_int(); - let refcount_type = create_basic_type(cx, int_t, span); - let name = ty_to_str(cx.tcx, contents); - - let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0); - scx.add_member("refcnt", 0, sys::size_of::(), - sys::min_align_of::(), refcount_type); - // the tydesc and other pointers should be irrelevant to the - // debugger, so treat them as void* types - let (vp, vpsize, vpalign) = voidptr(cx); - scx.add_member("tydesc", 0, vpsize, vpalign, vp); - scx.add_member("prev", 0, vpsize, vpalign, vp); - scx.add_member("next", 0, vpsize, vpalign, vp); - let (size, align) = size_and_align_of(cx, contents); - scx.add_member("boxed", 0, size, align, boxed); - return scx.finalize(); +fn create_boxed_type(cx: &mut CrateContext, + content_type: ty::t, + span: span) + -> DICompositeType { + + debug!("create_boxed_type: %?", ty::get(content_type)); + + let content_llvm_type = type_of::type_of(cx, content_type); + let content_type_metadata = create_ty(cx, content_type, span); + + let box_llvm_type = Type::box(cx, &content_llvm_type); + let member_llvm_types = box_llvm_type.field_types(); + let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"]; + + assert!(box_layout_is_as_expected(cx, member_llvm_types, content_llvm_type)); + + let int_type = ty::mk_int(); + let nil_pointer_type = ty::mk_nil_ptr(cx.tcx); + + let member_types_metadata = [ + create_ty(cx, int_type, span), + create_ty(cx, nil_pointer_type, span), + create_ty(cx, nil_pointer_type, span), + create_ty(cx, nil_pointer_type, span), + content_type_metadata + ]; + + return create_composite_type( + cx, + box_llvm_type, + "box name", + member_llvm_types, + member_names, + member_types_metadata, + span); + + fn box_layout_is_as_expected(cx: &CrateContext, + member_types: &[Type], + content_type: Type) + -> bool { + return member_types[0] == cx.int_type + && member_types[1] == cx.tydesc_type.ptr_to() + && member_types[2] == Type::i8().ptr_to() + && member_types[3] == Type::i8().ptr_to() + && member_types[4] == content_type; + } } +// fn create_boxed_type(cx: &mut CrateContext, +// contents: ty::t, +// span: span, +// boxed: DIType) +// -> DICompositeType { + +// debug!("create_boxed_type: %?", ty::get(contents)); + +// let loc = span_start(cx, span); +// let file_md = create_file(cx, loc.file.name); +// let int_t = ty::mk_int(); +// let refcount_type = create_basic_type(cx, int_t, span); +// let name = ty_to_str(cx.tcx, contents); + +// let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0); +// scx.add_member("refcnt", 0, sys::size_of::(), +// sys::min_align_of::(), refcount_type); +// // the tydesc and other pointers should be irrelevant to the +// // debugger, so treat them as void* types +// let (vp, vpsize, vpalign) = voidptr(cx); +// scx.add_member("tydesc", 0, vpsize, vpalign, vp); +// scx.add_member("prev", 0, vpsize, vpalign, vp); +// scx.add_member("next", 0, vpsize, vpalign, vp); +// let (size, align) = size_and_align_of(cx, contents); +// scx.add_member("val", 0, size, align, boxed); +// return scx.finalize(); +// } + + fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t, len: uint, span: span) -> DIType { debug!("create_fixed_vec: %?", ty::get(_vec_t)); @@ -840,9 +981,8 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { create_unimpl_ty(cx, t) } ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => { - let boxed = create_ty(cx, mt.ty, span); - let box_md = create_boxed_type(cx, mt.ty, span, boxed); - create_pointer_type(cx, t, span, box_md) + let box_metadata = create_boxed_type(cx, mt.ty, span); + create_pointer_type(cx, t, span, box_metadata) }, ty::ty_evec(ref mt, ref vstore) => { match *vstore { @@ -858,10 +998,7 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { } } }, - ty::ty_ptr(ref mt) => { - let pointee = create_ty(cx, mt.ty, span); - create_pointer_type(cx, t, span, pointee) - }, + ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { let pointee = create_ty(cx, mt.ty, span); create_pointer_type(cx, t, span, pointee) diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index 2cd313ff43154..c0b57a2206537 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -113,3 +113,48 @@ pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef { llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False); } } + +pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> uint { + unsafe { + return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as uint; + } +} + +// Computes the size of the data part of an enum. +pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint { + if cx.enum_sizes.contains_key(&t) { + return cx.enum_sizes.get_copy(&t); + } + + debug!("static_size_of_enum %s", ty_to_str(cx.tcx, t)); + + match ty::get(t).sty { + ty::ty_enum(tid, ref substs) => { + // Compute max(variant sizes). + let mut max_size = 0; + let variants = ty::enum_variants(cx.tcx, tid); + for variants.iter().advance |variant| { + if variant.args.len() == 0 { + loop; + } + + let lltypes = variant.args.map(|&variant_arg| { + let substituted = ty::subst(cx.tcx, substs, variant_arg); + type_of::sizing_type_of(cx, substituted) + }); + + debug!("static_size_of_enum: variant %s type %s", + cx.tcx.sess.str_of(variant.name), + cx.tn.type_to_str(Type::struct_(lltypes, false))); + + let this_size = llsize_of_real(cx, Type::struct_(lltypes, false)); + if max_size < this_size { + max_size = this_size; + } + } + cx.enum_sizes.insert(t, max_size); + return max_size; + } + _ => cx.sess.bug("static_size_of_enum called on non-enum") + } +} diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs index 4a3a65a90550c..543d8f1cdb7a4 100644 --- a/src/test/debug-info/box.rs +++ b/src/test/debug-info/box.rs @@ -8,20 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test - // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break _zzz // debugger:run // debugger:finish -// debugger:print a->boxed +// debugger:print a->val // check:$1 = 1 -// debugger:print b->boxed +// debugger:print b->val // check:$2 = {2, 3.5} -// debugger:print c->boxed +// debugger:print c->val // check:$3 = 4 -// debugger:print d->boxed +// debugger:print d->val // check:$4 = false fn main() { diff --git a/src/test/debug-info/boxed-struct.rs b/src/test/debug-info/boxed-struct.rs new file mode 100644 index 0000000000000..31b4746267554 --- /dev/null +++ b/src/test/debug-info/boxed-struct.rs @@ -0,0 +1,60 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical +// value. + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print unique->val +// check:$1 = {x = 99, y = 999, z = 9999, w = 99999} + +// debugger:print managed->val +// check:$2 = {x = 88, y = 888, z = 8888, w = 88888} + +// debugger:print unique_dtor->val +// check:$3 = {x = 77, y = 777, z = 7777, w = 77777} + +// debugger:print managed_dtor->val +// check:$4 = {x = 33, y = 333, z = 3333, w = 33333} + +struct StructWithSomePadding { + x: i16, + y: i32, + z: i32, + w: i64 +} + +struct StructWithDestructor { + x: i16, + y: i32, + z: i32, + w: i64 +} + +impl Drop for StructWithDestructor { + fn drop(&self) {} +} + +fn main() { + + let unique = ~StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; + let managed = @StructWithSomePadding { x: 88, y: 888, z: 8888, w: 88888 }; + + let unique_dtor = ~StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; + let managed_dtor = @StructWithDestructor { x: 33, y: 333, z: 3333, w: 33333 }; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs index f8281bba49e9f..9c72c676d5446 100644 --- a/src/test/debug-info/struct-with-destructor.rs +++ b/src/test/debug-info/struct-with-destructor.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run @@ -34,7 +32,7 @@ struct WithDestructor { } impl Drop for WithDestructor { - fn finalize(&self) {} + fn drop(&self) {} } struct NoDestructorGuarded { From 1b20831c1edc97bed1b397c57ae84cb465f5ce58 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 28 Jun 2013 09:32:25 +0200 Subject: [PATCH 02/26] debuginfo: Renamed *reference-to-* test cases to *borrowed-* --- src/test/debug-info/{reference-to-basic.rs => borrowed-basic.rs} | 0 .../{reference-to-managed-basic.rs => borrowed-managed-basic.rs} | 0 .../debug-info/{reference-to-struct.rs => borrowed-struct.rs} | 0 src/test/debug-info/{reference-to-tuple.rs => borrowed-tuple.rs} | 0 .../{reference-to-unique-basic.rs => borrowed-unique-basic.rs} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/test/debug-info/{reference-to-basic.rs => borrowed-basic.rs} (100%) rename src/test/debug-info/{reference-to-managed-basic.rs => borrowed-managed-basic.rs} (100%) rename src/test/debug-info/{reference-to-struct.rs => borrowed-struct.rs} (100%) rename src/test/debug-info/{reference-to-tuple.rs => borrowed-tuple.rs} (100%) rename src/test/debug-info/{reference-to-unique-basic.rs => borrowed-unique-basic.rs} (100%) diff --git a/src/test/debug-info/reference-to-basic.rs b/src/test/debug-info/borrowed-basic.rs similarity index 100% rename from src/test/debug-info/reference-to-basic.rs rename to src/test/debug-info/borrowed-basic.rs diff --git a/src/test/debug-info/reference-to-managed-basic.rs b/src/test/debug-info/borrowed-managed-basic.rs similarity index 100% rename from src/test/debug-info/reference-to-managed-basic.rs rename to src/test/debug-info/borrowed-managed-basic.rs diff --git a/src/test/debug-info/reference-to-struct.rs b/src/test/debug-info/borrowed-struct.rs similarity index 100% rename from src/test/debug-info/reference-to-struct.rs rename to src/test/debug-info/borrowed-struct.rs diff --git a/src/test/debug-info/reference-to-tuple.rs b/src/test/debug-info/borrowed-tuple.rs similarity index 100% rename from src/test/debug-info/reference-to-tuple.rs rename to src/test/debug-info/borrowed-tuple.rs diff --git a/src/test/debug-info/reference-to-unique-basic.rs b/src/test/debug-info/borrowed-unique-basic.rs similarity index 100% rename from src/test/debug-info/reference-to-unique-basic.rs rename to src/test/debug-info/borrowed-unique-basic.rs From 7a31a3e0716f33ceb7c7278cb7da4acbafd97e17 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 28 Jun 2013 09:35:21 +0200 Subject: [PATCH 03/26] debuginfo: Removed some misleading comments from test cases. --- src/test/debug-info/borrowed-struct.rs | 3 --- src/test/debug-info/borrowed-tuple.rs | 3 --- src/test/debug-info/borrowed-unique-basic.rs | 3 +-- src/test/debug-info/boxed-struct.rs | 3 --- src/test/debug-info/destructured-local.rs | 3 --- src/test/debug-info/function-arguments.rs | 3 --- 6 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/test/debug-info/borrowed-struct.rs b/src/test/debug-info/borrowed-struct.rs index f00872c00b0e4..646109ff1c438 100644 --- a/src/test/debug-info/borrowed-struct.rs +++ b/src/test/debug-info/borrowed-struct.rs @@ -10,9 +10,6 @@ // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 -// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical -// value. - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/borrowed-tuple.rs b/src/test/debug-info/borrowed-tuple.rs index 86d02185bdae7..58c753bb30a92 100644 --- a/src/test/debug-info/borrowed-tuple.rs +++ b/src/test/debug-info/borrowed-tuple.rs @@ -10,9 +10,6 @@ // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 -// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical -// value. - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/borrowed-unique-basic.rs b/src/test/debug-info/borrowed-unique-basic.rs index ce5b50459f660..f9ce1728930ed 100644 --- a/src/test/debug-info/borrowed-unique-basic.rs +++ b/src/test/debug-info/borrowed-unique-basic.rs @@ -10,8 +10,7 @@ // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 -// Gdb doesn't know -// about UTF-32 character encoding and will print a rust char as only +// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only // its numerical value. // compile-flags:-Z extra-debug-info diff --git a/src/test/debug-info/boxed-struct.rs b/src/test/debug-info/boxed-struct.rs index 31b4746267554..16ffda35956d6 100644 --- a/src/test/debug-info/boxed-struct.rs +++ b/src/test/debug-info/boxed-struct.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical -// value. - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs index bf53d95b588d0..ad4774c06ffa7 100644 --- a/src/test/debug-info/destructured-local.rs +++ b/src/test/debug-info/destructured-local.rs @@ -10,9 +10,6 @@ // xfail-test -// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical -// value. - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/function-arguments.rs b/src/test/debug-info/function-arguments.rs index f5563cda259e9..225dfedfec721 100644 --- a/src/test/debug-info/function-arguments.rs +++ b/src/test/debug-info/function-arguments.rs @@ -10,9 +10,6 @@ // xfail-test -// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical -// value. - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run From 36ea75683105447cb9f8338cd2a70493f4eb2c70 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 28 Jun 2013 11:56:35 +0200 Subject: [PATCH 04/26] debuginfo: Refactored vec slice code to use the new infrastructure. Added test cases for vec slices. --- src/librustc/middle/trans/debuginfo.rs | 118 +++++++++++++------------ src/test/debug-info/vec-slices.rs | 70 +++++++++++++++ src/test/debug-info/vec.rs | 18 +--- 3 files changed, 134 insertions(+), 72 deletions(-) create mode 100644 src/test/debug-info/vec-slices.rs diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 74d8825d6d468..6cb9ed4ec3817 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -149,7 +149,7 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { let loc = span_start(cx, local.span); let ty = node_id_type(bcx, local.node.id); let tymd = create_ty(cx, ty, local.node.ty.span); - let filemd = create_file(cx, loc.file.name); + let filemd = get_or_create_file(cx, loc.file.name); let context = match bcx.parent { None => create_function(bcx.fcx), Some(_) => create_block(bcx) @@ -203,7 +203,7 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option let ty = node_id_type(bcx, arg.id); let tymd = create_ty(cx, ty, arg.ty.span); - let filemd = create_file(cx, loc.file.name); + let filemd = get_or_create_file(cx, loc.file.name); let context = create_function(fcx); match arg.pat.node { @@ -297,7 +297,7 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { debug!("create_function: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span)); let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); + let file_md = get_or_create_file(cx, loc.file.name); let ret_ty_md = if cx.sess.opts.extra_debuginfo { match ret_ty.node { @@ -374,13 +374,13 @@ fn create_compile_unit(cx: @mut CrateContext) { }}}}}}; } -fn create_file(cx: &mut CrateContext, full_path: &str) -> DIFile { +fn get_or_create_file(cx: &mut CrateContext, full_path: &str) -> DIFile { match dbg_cx(cx).created_files.find_equiv(&full_path) { Some(file_md) => return *file_md, None => () } - debug!("create_file: %s", full_path); + debug!("get_or_create_file: %s", full_path); let work_dir = cx.sess.working_dir.to_str(); let file_name = @@ -428,7 +428,7 @@ fn create_block(bcx: block) -> DILexicalBlock { }; let cx = bcx.ccx(); let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); + let file_md = get_or_create_file(cx, loc.file.name); let block_md = unsafe { llvm::LLVMDIBuilderCreateLexicalBlock( @@ -639,6 +639,9 @@ fn create_tuple(cx: &mut CrateContext, span); } +/// Creates debug information for a composite type, that is, anything that results in a LLVM struct. +/// +/// Examples of Rust types to use this are: structs, tuples, boxes, and enums. fn create_composite_type(cx: &mut CrateContext, composite_llvm_type: Type, composite_type_name: &str, @@ -649,7 +652,7 @@ fn create_composite_type(cx: &mut CrateContext, -> DICompositeType { let loc = span_start(cx, span); - let file_metadata = create_file(cx, loc.file.name); + let file_metadata = get_or_create_file(cx, loc.file.name); let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type); let composite_align = machine::llalign_of_min(cx, composite_llvm_type); @@ -763,47 +766,21 @@ fn create_boxed_type(cx: &mut CrateContext, member_types_metadata, span); + // Unfortunately, we cannot assert anything but the correct types here---and not whether the + // 'next' and 'prev' pointers are in the order. fn box_layout_is_as_expected(cx: &CrateContext, - member_types: &[Type], - content_type: Type) + member_llvm_types: &[Type], + content_llvm_type: Type) -> bool { - return member_types[0] == cx.int_type - && member_types[1] == cx.tydesc_type.ptr_to() - && member_types[2] == Type::i8().ptr_to() - && member_types[3] == Type::i8().ptr_to() - && member_types[4] == content_type; + member_llvm_types.len() == 5 && + member_llvm_types[0] == cx.int_type && + member_llvm_types[1] == cx.tydesc_type.ptr_to() && + member_llvm_types[2] == Type::i8().ptr_to() && + member_llvm_types[3] == Type::i8().ptr_to() && + member_llvm_types[4] == content_llvm_type } } -// fn create_boxed_type(cx: &mut CrateContext, -// contents: ty::t, -// span: span, -// boxed: DIType) -// -> DICompositeType { - -// debug!("create_boxed_type: %?", ty::get(contents)); - -// let loc = span_start(cx, span); -// let file_md = create_file(cx, loc.file.name); -// let int_t = ty::mk_int(); -// let refcount_type = create_basic_type(cx, int_t, span); -// let name = ty_to_str(cx.tcx, contents); - -// let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0); -// scx.add_member("refcnt", 0, sys::size_of::(), -// sys::min_align_of::(), refcount_type); -// // the tydesc and other pointers should be irrelevant to the -// // debugger, so treat them as void* types -// let (vp, vpsize, vpalign) = voidptr(cx); -// scx.add_member("tydesc", 0, vpsize, vpalign, vp); -// scx.add_member("prev", 0, vpsize, vpalign, vp); -// scx.add_member("next", 0, vpsize, vpalign, vp); -// let (size, align) = size_and_align_of(cx, contents); -// scx.add_member("val", 0, size, align, boxed); -// return scx.finalize(); -// } - - fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t, len: uint, span: span) -> DIType { debug!("create_fixed_vec: %?", ty::get(_vec_t)); @@ -831,7 +808,7 @@ fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, debug!("create_boxed_vec: %?", ty::get(vec_t)); let loc = span_start(cx, vec_ty_span); - let file_md = create_file(cx, loc.file.name); + let file_md = get_or_create_file(cx, loc.file.name); let elem_ty_md = create_ty(cx, elem_t, vec_ty_span); let mut vec_scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0); @@ -896,21 +873,46 @@ fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, return mdval; } -fn create_vec_slice(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) - -> DICompositeType { - debug!("create_vec_slice: %?", ty::get(vec_t)); +fn create_vec_slice(cx: &mut CrateContext, + vec_type: ty::t, + element_type: ty::t, + span: span) + -> DICompositeType { - let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); - let elem_ty_md = create_ty(cx, elem_t, span); - let uint_type = create_basic_type(cx, ty::mk_uint(), span); - let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md); + debug!("create_vec_slice: %?", ty::get(vec_type)); - let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0); - let (_, ptr_size, ptr_align) = voidptr(cx); - scx.add_member("vec", 0, ptr_size, ptr_align, elem_ptr); - scx.add_member("length", 0, sys::size_of::(), sys::min_align_of::(), uint_type); - return scx.finalize(); + let slice_llvm_type = type_of::type_of(cx, vec_type); + let slice_type_name = ty_to_str(cx.tcx, vec_type); + + let member_llvm_types = slice_llvm_type.field_types(); + let member_names = &[~"data_ptr", ~"size_in_bytes"]; + + assert!(slice_layout_is_as_expected(cx, member_llvm_types, element_type)); + + let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const }); + + let member_type_metadata = &[ + create_ty(cx, data_ptr_type, span), + create_ty(cx, ty::mk_uint(), span) + ]; + + return create_composite_type( + cx, + slice_llvm_type, + slice_type_name, + member_llvm_types, + member_names, + member_type_metadata, + span); + + fn slice_layout_is_as_expected(cx: &mut CrateContext, + member_llvm_types: &[Type], + element_type: ty::t) + -> bool { + member_llvm_types.len() == 2 && + member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() && + member_llvm_types[1] == cx.int_type + } } fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t, @@ -918,7 +920,7 @@ fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: debug!("create_fn_ty: %?", ty::get(_fn_ty)); let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); + let file_md = get_or_create_file(cx, loc.file.name); let (vp, _, _) = voidptr(cx); let output_md = create_ty(cx, output, span); let output_ptr_md = create_pointer_type(cx, output, span, output_md); diff --git a/src/test/debug-info/vec-slices.rs b/src/test/debug-info/vec-slices.rs new file mode 100644 index 0000000000000..a7e47f992fc90 --- /dev/null +++ b/src/test/debug-info/vec-slices.rs @@ -0,0 +1,70 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break zzz +// debugger:run +// debugger:finish +// debugger:print empty.size_in_bytes +// check:$1 = 0 + +// debugger:print singleton.size_in_bytes +// check:$2 = 8 +// debugger:print *((int64_t[1]*)(singleton.data_ptr)) +// check:$3 = {1} + +// debugger:print multiple.size_in_bytes +// check:$4 = 32 +// debugger:print *((int64_t[4]*)(multiple.data_ptr)) +// check:$5 = {2, 3, 4, 5} + +// debugger:print slice_of_slice.size_in_bytes +// check:$6 = 16 +// debugger:print *((int64_t[2]*)(slice_of_slice.data_ptr)) +// check:$7 = {3, 4} + +// debugger:print padded_tuple.size_in_bytes +// check:$8 = 16 +// debugger:print padded_tuple.data_ptr[0] +// check:$9 = {6, 7} +// debugger:print padded_tuple.data_ptr[1] +// check:$10 = {8, 9} + +// debugger:print padded_struct.size_in_bytes +// check:$11 = 24 +// debugger:print padded_struct.data_ptr[0] +// check:$12 = {x = 10, y = 11, z = 12} +// debugger:print padded_struct.data_ptr[1] +// check:$13 = {x = 13, y = 14, z = 15} + +struct AStruct { + x: i16, + y: i32, + z: i16 +} + +fn main() { + let empty : &[i64] = &[]; + let singleton : &[i64] = &[1]; + let multiple : &[i64] = &[2, 3, 4, 5]; + let slice_of_slice = multiple.slice(1,3); + + let padded_tuple : &[(i32, i16)] = &[(6, 7), (8, 9)]; + + let padded_struct : &[AStruct] = &[ + AStruct { x: 10, y: 11, z: 12 }, + AStruct { x: 13, y: 14, z: 15 } + ]; + + zzz(); +} + +fn zzz() {()} diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs index f198a53729eb7..a9aca58fad7f7 100644 --- a/src/test/debug-info/vec.rs +++ b/src/test/debug-info/vec.rs @@ -8,28 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test - // compile-flags:-Z extra-debug-info // debugger:set print pretty off -// debugger:break _zzz +// debugger:break zzz // debugger:run // debugger:finish // debugger:print a // check:$1 = {1, 2, 3} -// debugger:print b.vec[0] -// check:$2 = 4 -// debugger:print c->boxed.data[1] -// check:$3 = 8 -// debugger:print d->boxed.data[2] -// check:$4 = 12 fn main() { let a = [1, 2, 3]; - let b = &[4, 5, 6]; - let c = @[7, 8, 9]; - let d = ~[10, 11, 12]; - _zzz(); + + zzz(); } -fn _zzz() {()} +fn zzz() {()} From f424e931da4c04e410b003f48503acee92720ffb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 28 Jun 2013 17:11:50 +0200 Subject: [PATCH 05/26] debuginfo: Refactoring of composite type info generation done. There is no more StructContext now. Better support for boxed vectors in there too. --- src/librustc/middle/trans/debuginfo.rs | 347 +++++++++---------------- src/test/debug-info/boxed-vec.rs | 34 +++ 2 files changed, 153 insertions(+), 228 deletions(-) create mode 100644 src/test/debug-info/boxed-vec.rs diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 6cb9ed4ec3817..a535333a19f92 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -55,9 +55,7 @@ use middle::ty; use util::ppaux::ty_to_str; use std::hashmap::HashMap; -use std::libc; -use std::libc::{c_uint, c_ulonglong}; -use std::cmp; +use std::libc::{c_uint, c_ulonglong, c_longlong}; use std::ptr; use std::str::as_c_str; use std::sys; @@ -148,7 +146,7 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { let loc = span_start(cx, local.span); let ty = node_id_type(bcx, local.node.id); - let tymd = create_ty(cx, ty, local.node.ty.span); + let tymd = get_or_create_ty(cx, ty, local.node.ty.span); let filemd = get_or_create_file(cx, loc.file.name); let context = match bcx.parent { None => create_function(bcx.fcx), @@ -202,7 +200,7 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option } let ty = node_id_type(bcx, arg.id); - let tymd = create_ty(cx, ty, arg.ty.span); + let tymd = get_or_create_ty(cx, ty, arg.ty.span); let filemd = get_or_create_file(cx, loc.file.name); let context = create_function(fcx); @@ -302,7 +300,7 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { let ret_ty_md = if cx.sess.opts.extra_debuginfo { match ret_ty.node { ast::ty_nil => ptr::null(), - _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) + _ => get_or_create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) } } else { ptr::null() @@ -445,11 +443,6 @@ fn create_block(bcx: block) -> DILexicalBlock { fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType { - let ty_id = ty::type_id(t); - match dbg_cx(cx).created_types.find(&ty_id) { - Some(ty_md) => return *ty_md, - None => () - } debug!("create_basic_type: %?", ty::get(t)); @@ -489,10 +482,6 @@ fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType { encoding as c_uint) }}; - // One could think that this call is not necessary, as the create_ty() function will insert the - // type descriptor into the cache anyway. Mind, however, that create_basic_type() is also called - // directly from other functions (e.g. create_boxed_type()). - dbg_cx(cx).created_types.insert(ty_id, ty_md); return ty_md; } @@ -510,91 +499,11 @@ fn create_pointer_type(cx: &mut CrateContext, t: ty::t, _span: span, pointee: DI return ptr_md; } -struct StructContext { - builder: DIBuilderRef, - file: DIFile, - name: ~str, - line: uint, - members: ~[DIDerivedType], - total_size: uint, - align: uint -} - -impl StructContext { - fn new(cx: &CrateContext, name: ~str, file: DIFile, line: uint) -> StructContext { - debug!("StructContext::create: %s", name); - return StructContext { - builder: DIB(cx), - file: file, - name: name, - line: line, - members: ~[], - total_size: 0, - align: 1 - }; - } - - fn add_member(&mut self, name: &str, line: uint, size: uint, align: uint, ty: DIType) { - let offset = roundup(self.total_size, align); - - debug!("StructContext(%s)::add_member: %s, size=%u, align=%u, offset=%u", - self.name, name, size, align, offset); - - let mem_t = do as_c_str(name) |name| { unsafe { - llvm::LLVMDIBuilderCreateMemberType( - self.builder, - self.file, - name, - self.file, - line as c_uint, - bytes_to_bits(size), - bytes_to_bits(align), - bytes_to_bits(offset), - 0, - ty) - }}; - self.members.push(mem_t); - self.total_size = offset + size; - // struct alignment is the max alignment of its' members - self.align = cmp::max(self.align, align); - } - - fn get_total_size_with_alignment(&self) -> uint { - roundup(self.total_size, self.align) - } - - fn finalize(&self) -> DICompositeType { - debug!("StructContext(%s)::finalize: total_size=%u, align=%u", - self.name, self.total_size, self.align); - let members_md = create_DIArray(self.builder, self.members); - - // The size of the struct/tuple must be rounded to the next multiple of its alignment. - // Otherwise gdb has trouble reading the struct correctly when it is embedded into another - // data structure. This is also the value `sizeof` in C would give. - let actual_total_size = self.get_total_size_with_alignment(); - - let struct_md = - do as_c_str(self.name) |name| { unsafe { - llvm::LLVMDIBuilderCreateStructType( - self.builder, - self.file, - name, - self.file, - self.line as c_uint, - bytes_to_bits(actual_total_size), - bytes_to_bits(self.align), - 0, - ptr::null(), - members_md, - 0, - ptr::null()) - }}; - return struct_md; - } -} - -fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field], span: span) - -> DICompositeType { +fn create_struct(cx: &mut CrateContext, + struct_type: ty::t, + fields: ~[ty::field], + span: span) + -> DICompositeType { debug!("create_struct: %?", ty::get(struct_type)); let struct_name = ty_to_str(cx.tcx, struct_type); @@ -602,7 +511,7 @@ fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field] let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty)); let field_names = fields.map(|field| cx.sess.str_of(field.ident).to_owned()); - let field_types_metadata = fields.map(|field| create_ty(cx, field.mt.ty, span)); + let field_types_metadata = fields.map(|field| get_or_create_ty(cx, field.mt.ty, span)); return create_composite_type( cx, @@ -620,14 +529,14 @@ fn create_tuple(cx: &mut CrateContext, span: span) -> DICompositeType { - let tuple_name = (cx.sess.str_of((dbg_cx(cx).names)("tuple"))).to_owned(); + let tuple_name = "tuple"; // TODO: better type name let tuple_llvm_type = type_of::type_of(cx, tuple_type); // Create a vec of empty strings. A vec::build_n() function would be nice for this. let mut component_names : ~[~str] = vec::with_capacity(component_types.len()); component_names.grow_fn(component_types.len(), |_| ~""); let component_llvm_types = component_types.map(|it| type_of::type_of(cx, *it)); - let component_types_metadata = component_types.map(|it| create_ty(cx, *it, span)); + let component_types_metadata = component_types.map(|it| get_or_create_ty(cx, *it, span)); return create_composite_type( cx, @@ -641,7 +550,7 @@ fn create_tuple(cx: &mut CrateContext, /// Creates debug information for a composite type, that is, anything that results in a LLVM struct. /// -/// Examples of Rust types to use this are: structs, tuples, boxes, and enums. +/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. fn create_composite_type(cx: &mut CrateContext, composite_llvm_type: Type, composite_type_name: &str, @@ -657,10 +566,10 @@ fn create_composite_type(cx: &mut CrateContext, let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type); let composite_align = machine::llalign_of_min(cx, composite_llvm_type); - let member_metadata = create_DIArray( - DIB(cx), - // transform the ty::t array of components into an array of DIEs - do vec::mapi(member_llvm_types) |i, member_llvm_type| { + let xxx : ~[DIDescriptor] = member_llvm_types + .iter() + .enumerate() + .transform(|(i, member_llvm_type)| { let member_size = machine::llsize_of_alloc(cx, *member_llvm_type); let member_align = machine::llalign_of_min(cx, *member_llvm_type); let member_offset = machine::llelement_offset(cx, composite_llvm_type, i); @@ -678,8 +587,32 @@ fn create_composite_type(cx: &mut CrateContext, bytes_to_bits(member_offset), 0, member_type_metadata[i]) - }} - }); + }}}) + .collect(); + + let member_metadata = create_DIArray(DIB(cx), xxx); + // transform the ty::t array of components into an array of DIEs + // do vec::mapi(member_llvm_types) |i, member_llvm_type| { + // do member_llvm_types.iter().enumerate().transform |(i, member_llvm_type)| { + // let member_size = machine::llsize_of_alloc(cx, *member_llvm_type); + // let member_align = machine::llalign_of_min(cx, *member_llvm_type); + // let member_offset = machine::llelement_offset(cx, composite_llvm_type, i); + // let member_name : &str = member_names[i]; + + // do member_name.as_c_str |member_name| { unsafe { + // llvm::LLVMDIBuilderCreateMemberType( + // DIB(cx), + // file_metadata, + // member_name, + // file_metadata, + // loc.line as c_uint, + // bytes_to_bits(member_size), + // bytes_to_bits(member_align), + // bytes_to_bits(member_offset), + // 0, + // member_type_metadata[i]) + // }} + // }.collect()); return do composite_type_name.as_c_str |name| { unsafe { llvm::LLVMDIBuilderCreateStructType( @@ -713,33 +646,12 @@ fn voidptr(cx: &mut CrateContext) -> (DIDerivedType, uint, uint) { return (vp, size, align); } -fn create_tuple(cx: &mut CrateContext, tuple_type: ty::t, elements: &[ty::t], span: span) - -> DICompositeType { - debug!("create_tuple: %?", ty::get(tuple_type)); - - let loc = span_start(cx, span); - let file_md = create_file(cx, loc.file.name); - - let name = fmt!("tuple_%u", token::gensym("tuple")); - let mut scx = StructContext::new(cx, name, file_md, loc.line); - for elements.iter().advance |element| { - let ty_md = create_ty(cx, *element, span); - let (size, align) = size_and_align_of(cx, *element); - scx.add_member("", loc.line, size, align, ty_md); - } - return scx.finalize(); -} - fn create_boxed_type(cx: &mut CrateContext, - content_type: ty::t, + content_llvm_type: Type, + content_type_metadata: DIType, span: span) -> DICompositeType { - debug!("create_boxed_type: %?", ty::get(content_type)); - - let content_llvm_type = type_of::type_of(cx, content_type); - let content_type_metadata = create_ty(cx, content_type, span); - let box_llvm_type = Type::box(cx, &content_llvm_type); let member_llvm_types = box_llvm_type.field_types(); let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"]; @@ -750,10 +662,10 @@ fn create_boxed_type(cx: &mut CrateContext, let nil_pointer_type = ty::mk_nil_ptr(cx.tcx); let member_types_metadata = [ - create_ty(cx, int_type, span), - create_ty(cx, nil_pointer_type, span), - create_ty(cx, nil_pointer_type, span), - create_ty(cx, nil_pointer_type, span), + get_or_create_ty(cx, int_type, span), + get_or_create_ty(cx, nil_pointer_type, span), + get_or_create_ty(cx, nil_pointer_type, span), + get_or_create_ty(cx, nil_pointer_type, span), content_type_metadata ]; @@ -785,92 +697,60 @@ fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t, len: uint, span: span) -> DIType { debug!("create_fixed_vec: %?", ty::get(_vec_t)); - let elem_ty_md = create_ty(cx, elem_t, span); + let elem_ty_md = get_or_create_ty(cx, elem_t, span); let (size, align) = size_and_align_of(cx, elem_t); - let subrange = unsafe { - llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0_i64, len as i64) - }; + let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange( + DIB(cx), + 0, + len as c_longlong + )}; let subscripts = create_DIArray(DIB(cx), [subrange]); - return unsafe { - llvm::LLVMDIBuilderCreateArrayType( + return unsafe { llvm::LLVMDIBuilderCreateArrayType( DIB(cx), bytes_to_bits(size * len), bytes_to_bits(align), elem_ty_md, - subscripts) - }; + subscripts + )}; } -fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, - vec_ty_span: span) -> DICompositeType { - debug!("create_boxed_vec: %?", ty::get(vec_t)); - - let loc = span_start(cx, vec_ty_span); - let file_md = get_or_create_file(cx, loc.file.name); - let elem_ty_md = create_ty(cx, elem_t, vec_ty_span); - - let mut vec_scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0); - let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span); +fn create_boxed_vec(cx: &mut CrateContext, + element_type: ty::t, + span: span) + -> DICompositeType { - vec_scx.add_member( - "fill", - 0, - sys::size_of::(), - sys::min_align_of::(), - size_t_type); + let element_type_metadata = get_or_create_ty(cx, element_type, span); + let element_llvm_type = type_of::type_of(cx, element_type); + let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type); + let vec_type_name = &"vec"; - vec_scx.add_member( - "alloc", - 0, - sys::size_of::(), - sys::min_align_of::(), - size_t_type); + let member_llvm_types = vec_llvm_type.field_types(); + let member_names = &[~"fill", ~"alloc", ~"elements"]; - let subrange = unsafe { - llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0_i64, 0_i64) - }; - let (arr_size, arr_align) = size_and_align_of(cx, elem_t); - let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); - - let subscripts = create_DIArray(DIB(cx), [subrange]); - let data_ptr = unsafe { - llvm::LLVMDIBuilderCreateArrayType( - DIB(cx), - bytes_to_bits(arr_size), - bytes_to_bits(arr_align), - elem_ty_md, - subscripts) + let int_type_md = get_or_create_ty(cx, ty::mk_int(), span); + let array_type_md = unsafe { llvm::LLVMDIBuilderCreateArrayType( + DIB(cx), + bytes_to_bits(machine::llsize_of_alloc(cx, element_llvm_type)), + bytes_to_bits(machine::llalign_of_min(cx, element_llvm_type)), + element_type_metadata, + create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)])) }; - vec_scx.add_member( - "data", - 0, - 0, // clang says the size should be 0 - sys::min_align_of::(), data_ptr); - let vec_md = vec_scx.finalize(); + // fill alloc elements + let member_type_metadata = &[int_type_md, int_type_md, array_type_md]; - let mut box_scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0); - let int_t = ty::mk_int(); - let refcount_type = create_basic_type(cx, int_t, vec_ty_span); + let vec_md = create_composite_type( + cx, + vec_llvm_type, + vec_type_name, + member_llvm_types, + member_names, + member_type_metadata, + span); - box_scx.add_member( - "refcnt", - 0, - sys::size_of::(), - sys::min_align_of::(), - refcount_type); - - let (vp, vpsize, vpalign) = voidptr(cx); - box_scx.add_member("tydesc", 0, vpsize, vpalign, vp); - box_scx.add_member("prev", 0, vpsize, vpalign, vp); - box_scx.add_member("next", 0, vpsize, vpalign, vp); - let size = 2 * sys::size_of::(); - let align = sys::min_align_of::(); - box_scx.add_member("boxed", 0, size, align, vec_md); - let mdval = box_scx.finalize(); - return mdval; + return create_boxed_type(cx, vec_llvm_type, vec_md, span); } fn create_vec_slice(cx: &mut CrateContext, @@ -892,8 +772,8 @@ fn create_vec_slice(cx: &mut CrateContext, let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const }); let member_type_metadata = &[ - create_ty(cx, data_ptr_type, span), - create_ty(cx, ty::mk_uint(), span) + get_or_create_ty(cx, data_ptr_type, span), + get_or_create_ty(cx, ty::mk_uint(), span) ]; return create_composite_type( @@ -922,9 +802,9 @@ fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: let loc = span_start(cx, span); let file_md = get_or_create_file(cx, loc.file.name); let (vp, _, _) = voidptr(cx); - let output_md = create_ty(cx, output, span); + let output_md = get_or_create_ty(cx, output, span); let output_ptr_md = create_pointer_type(cx, output, span, output_md); - let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span) }; + let inputs_vals = do inputs.map |arg| { get_or_create_ty(cx, *arg, span) }; let members = ~[output_ptr_md, vp] + inputs_vals; return unsafe { @@ -950,27 +830,34 @@ fn create_unimpl_ty(cx: &mut CrateContext, t: ty::t) -> DIType { return md; } -fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { +fn get_or_create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { let ty_id = ty::type_id(t); match dbg_cx(cx).created_types.find(&ty_id) { Some(ty_md) => return *ty_md, None => () } - debug!("create_ty: %?", ty::get(t)); - - let sty = &ty::get(t).sty; - let ty_md = match *sty { - ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) - | ty::ty_float(_) => create_basic_type(cx, t, span), + debug!("get_or_create_ty: %?", ty::get(t)); + + let sty = copy ty::get(t).sty; + let ty_md = match sty { + ty::ty_nil | + ty::ty_bot | + ty::ty_bool | + ty::ty_int(_) | + ty::ty_uint(_) | + ty::ty_float(_) => { + create_basic_type(cx, t, span) + }, ty::ty_estr(ref vstore) => { let i8_t = ty::mk_i8(); match *vstore { ty::vstore_fixed(len) => { create_fixed_vec(cx, t, i8_t, len + 1, span) }, - ty::vstore_uniq | ty::vstore_box => { - let box_md = create_boxed_vec(cx, t, i8_t, span); + ty::vstore_uniq | + ty::vstore_box => { + let box_md = create_boxed_vec(cx, i8_t, span); create_pointer_type(cx, t, span, box_md) } ty::vstore_slice(_region) => { @@ -981,9 +868,12 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { ty::ty_enum(_did, ref _substs) => { cx.sess.span_note(span, "debuginfo for enum NYI"); create_unimpl_ty(cx, t) - } - ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => { - let box_metadata = create_boxed_type(cx, mt.ty, span); + }, + ty::ty_box(ref mt) | + ty::ty_uniq(ref mt) => { + let content_llvm_type = type_of::type_of(cx, mt.ty); + let content_type_metadata = get_or_create_ty(cx, mt.ty, span); + let box_metadata = create_boxed_type(cx, content_llvm_type, content_type_metadata, span); create_pointer_type(cx, t, span, box_metadata) }, ty::ty_evec(ref mt, ref vstore) => { @@ -991,18 +881,19 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { ty::vstore_fixed(len) => { create_fixed_vec(cx, t, mt.ty, len, span) }, - ty::vstore_uniq | ty::vstore_box => { - let box_md = create_boxed_vec(cx, t, mt.ty, span); + ty::vstore_uniq | + ty::vstore_box => { + let box_md = create_boxed_vec(cx, mt.ty, span); create_pointer_type(cx, t, span, box_md) }, - ty::vstore_slice(_region) => { + ty::vstore_slice(_) => { create_vec_slice(cx, t, mt.ty, span) } } }, ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { - let pointee = create_ty(cx, mt.ty, span); + let pointee = get_or_create_ty(cx, mt.ty, span); create_pointer_type(cx, t, span, pointee) }, ty::ty_bare_fn(ref barefnty) => { @@ -1025,7 +916,7 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { ty::ty_tup(ref elements) => { create_tuple(cx, t, *elements, span) }, - _ => cx.sess.bug("debuginfo: unexpected type in create_ty") + _ => cx.sess.bug("debuginfo: unexpected type in get_or_create_ty") }; dbg_cx(cx).created_types.insert(ty_id, ty_md); @@ -1067,7 +958,7 @@ fn span_start(cx: &CrateContext, span: span) -> codemap::Loc { fn size_and_align_of(cx: &mut CrateContext, t: ty::t) -> (uint, uint) { let llty = type_of::type_of(cx, t); - (machine::llsize_of_real(cx, llty), machine::llalign_of_min(cx, llty)) + (machine::llsize_of_alloc(cx, llty), machine::llalign_of_min(cx, llty)) } fn bytes_to_bits(bytes: uint) -> c_ulonglong { diff --git a/src/test/debug-info/boxed-vec.rs b/src/test/debug-info/boxed-vec.rs new file mode 100644 index 0000000000000..aeb081981c2d5 --- /dev/null +++ b/src/test/debug-info/boxed-vec.rs @@ -0,0 +1,34 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print managed->val.fill +// check:$1 = 24 +// debugger:print *((uint64_t[3]*)(managed->val.elements)) +// check:$2 = {7, 8, 9} + +// debugger:print unique->val.fill +// check:$3 = 32 +// debugger:print *((uint64_t[4]*)(unique->val.elements)) +// check:$4 = {10, 11, 12, 13} + +fn main() { + + let managed : @[i64] = @[7, 8, 9]; + let unique : ~[i64] = ~[10, 11, 12, 13]; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file From 6230ec14820c07755f533fff5664f91d3bc244b4 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 1 Jul 2013 12:10:08 +0200 Subject: [PATCH 06/26] debuginfo: Replaced vec::mapi with iterator version. --- src/librustc/middle/trans/debuginfo.rs | 43 +++++++------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index a535333a19f92..e2a8f8e01303c 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -62,9 +62,6 @@ use std::sys; use std::vec; use syntax::codemap::span; use syntax::{ast, codemap, ast_util, ast_map}; -use syntax::parse::token; - - static DW_LANG_RUST: int = 0x9000; @@ -529,7 +526,7 @@ fn create_tuple(cx: &mut CrateContext, span: span) -> DICompositeType { - let tuple_name = "tuple"; // TODO: better type name + let tuple_name = "tuple"; // this should have a better name let tuple_llvm_type = type_of::type_of(cx, tuple_type); // Create a vec of empty strings. A vec::build_n() function would be nice for this. let mut component_names : ~[~str] = vec::with_capacity(component_types.len()); @@ -566,7 +563,7 @@ fn create_composite_type(cx: &mut CrateContext, let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type); let composite_align = machine::llalign_of_min(cx, composite_llvm_type); - let xxx : ~[DIDescriptor] = member_llvm_types + let member_metadata : ~[DIDescriptor] = member_llvm_types .iter() .enumerate() .transform(|(i, member_llvm_type)| { @@ -587,33 +584,10 @@ fn create_composite_type(cx: &mut CrateContext, bytes_to_bits(member_offset), 0, member_type_metadata[i]) - }}}) + }} + }) .collect(); - let member_metadata = create_DIArray(DIB(cx), xxx); - // transform the ty::t array of components into an array of DIEs - // do vec::mapi(member_llvm_types) |i, member_llvm_type| { - // do member_llvm_types.iter().enumerate().transform |(i, member_llvm_type)| { - // let member_size = machine::llsize_of_alloc(cx, *member_llvm_type); - // let member_align = machine::llalign_of_min(cx, *member_llvm_type); - // let member_offset = machine::llelement_offset(cx, composite_llvm_type, i); - // let member_name : &str = member_names[i]; - - // do member_name.as_c_str |member_name| { unsafe { - // llvm::LLVMDIBuilderCreateMemberType( - // DIB(cx), - // file_metadata, - // member_name, - // file_metadata, - // loc.line as c_uint, - // bytes_to_bits(member_size), - // bytes_to_bits(member_align), - // bytes_to_bits(member_offset), - // 0, - // member_type_metadata[i]) - // }} - // }.collect()); - return do composite_type_name.as_c_str |name| { unsafe { llvm::LLVMDIBuilderCreateStructType( DIB(cx), @@ -625,7 +599,7 @@ fn create_composite_type(cx: &mut CrateContext, bytes_to_bits(composite_align), 0, ptr::null(), - member_metadata, + create_DIArray(DIB(cx), member_metadata), 0, ptr::null()) }}; @@ -873,7 +847,12 @@ fn get_or_create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { ty::ty_uniq(ref mt) => { let content_llvm_type = type_of::type_of(cx, mt.ty); let content_type_metadata = get_or_create_ty(cx, mt.ty, span); - let box_metadata = create_boxed_type(cx, content_llvm_type, content_type_metadata, span); + + let box_metadata = create_boxed_type(cx, + content_llvm_type, + content_type_metadata, + span); + create_pointer_type(cx, t, span, box_metadata) }, ty::ty_evec(ref mt, ref vstore) => { From 99ebb816cf9db45953c123bec95c2c3e19ed2302 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 1 Jul 2013 12:11:29 +0200 Subject: [PATCH 07/26] debuginfo: Added test cases for packed structs (/w drop) --- .../packed-struct-with-destructor.rs | 219 ++++++++++++++++++ src/test/debug-info/packed-struct.rs | 112 +++++++++ src/test/debug-info/struct-with-destructor.rs | 25 ++ 3 files changed, 356 insertions(+) create mode 100644 src/test/debug-info/packed-struct-with-destructor.rs create mode 100644 src/test/debug-info/packed-struct.rs diff --git a/src/test/debug-info/packed-struct-with-destructor.rs b/src/test/debug-info/packed-struct-with-destructor.rs new file mode 100644 index 0000000000000..9ff91aa00d1c9 --- /dev/null +++ b/src/test/debug-info/packed-struct-with-destructor.rs @@ -0,0 +1,219 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print packed +// check:$1 = {x = 123, y = 234, z = 345} + +// debugger:print packedInPacked +// check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} + +// debugger:print packedInUnpacked +// check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} + +// debugger:print unpackedInPacked +// check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} + + +// debugger:print packedInPackedWithDrop +// check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} + +// debugger:print packedInUnpackedWithDrop +// check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} + +// debugger:print unpackedInPackedWithDrop +// check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} + +// debugger:print deeplyNested +// check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} + +#[packed] +struct Packed { + x: i16, + y: i32, + z: i64 +} + +impl Drop for Packed { + fn drop(&self) {} +} + +#[packed] +struct PackedInPacked { + a: i32, + b: Packed, + c: i64, + d: Packed +} + +struct PackedInUnpacked { + a: i32, + b: Packed, + c: i64, + d: Packed +} + +struct Unpacked { + x: i64, + y: i32, + z: i16 +} + +impl Drop for Unpacked { + fn drop(&self) {} +} + +#[packed] +struct UnpackedInPacked { + a: i16, + b: Unpacked, + c: Unpacked, + d: i64 +} + +#[packed] +struct PackedInPackedWithDrop { + a: i32, + b: Packed, + c: i64, + d: Packed +} + +impl Drop for PackedInPackedWithDrop { + fn drop(&self) {} +} + +struct PackedInUnpackedWithDrop { + a: i32, + b: Packed, + c: i64, + d: Packed +} + +impl Drop for PackedInUnpackedWithDrop { + fn drop(&self) {} +} + +#[packed] +struct UnpackedInPackedWithDrop { + a: i16, + b: Unpacked, + c: Unpacked, + d: i64 +} + +impl Drop for UnpackedInPackedWithDrop { + fn drop(&self) {} +} + +struct DeeplyNested { + a: PackedInPacked, + b: UnpackedInPackedWithDrop, + c: PackedInUnpacked, + d: PackedInUnpackedWithDrop, + e: UnpackedInPacked, + f: PackedInPackedWithDrop +} + +fn main() { + let packed = Packed { x: 123, y: 234, z: 345 }; + + let packedInPacked = PackedInPacked { + a: 1111, + b: Packed { x: 2222, y: 3333, z: 4444 }, + c: 5555, + d: Packed { x: 6666, y: 7777, z: 8888 } + }; + + let packedInUnpacked = PackedInUnpacked { + a: -1111, + b: Packed { x: -2222, y: -3333, z: -4444 }, + c: -5555, + d: Packed { x: -6666, y: -7777, z: -8888 } + }; + + let unpackedInPacked = UnpackedInPacked { + a: 987, + b: Unpacked { x: 876, y: 765, z: 654 }, + c: Unpacked { x: 543, y: 432, z: 321 }, + d: 210 + }; + + let packedInPackedWithDrop = PackedInPackedWithDrop { + a: 11, + b: Packed { x: 22, y: 33, z: 44 }, + c: 55, + d: Packed { x: 66, y: 77, z: 88 } + }; + + let packedInUnpackedWithDrop = PackedInUnpackedWithDrop { + a: -11, + b: Packed { x: -22, y: -33, z: -44 }, + c: -55, + d: Packed { x: -66, y: -77, z: -88 } + }; + + let unpackedInPackedWithDrop = UnpackedInPackedWithDrop { + a: 98, + b: Unpacked { x: 87, y: 76, z: 65 }, + c: Unpacked { x: 54, y: 43, z: 32 }, + d: 21 + }; + + let deeplyNested = DeeplyNested { + a: PackedInPacked { + a: 1, + b: Packed { x: 2, y: 3, z: 4 }, + c: 5, + d: Packed { x: 6, y: 7, z: 8 } + }, + b: UnpackedInPackedWithDrop { + a: 9, + b: Unpacked { x: 10, y: 11, z: 12 }, + c: Unpacked { x: 13, y: 14, z: 15 }, + d: 16 + }, + c: PackedInUnpacked { + a: 17, + b: Packed { x: 18, y: 19, z: 20 }, + c: 21, + d: Packed { x: 22, y: 23, z: 24 } + }, + d: PackedInUnpackedWithDrop { + a: 25, + b: Packed { x: 26, y: 27, z: 28 }, + c: 29, + d: Packed { x: 30, y: 31, z: 32 } + }, + e: UnpackedInPacked { + a: 33, + b: Unpacked { x: 34, y: 35, z: 36 }, + c: Unpacked { x: 37, y: 38, z: 39 }, + d: 40 + }, + f: PackedInPackedWithDrop { + a: 41, + b: Packed { x: 42, y: 43, z: 44 }, + c: 45, + d: Packed { x: 46, y: 47, z: 48 } + } + }; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/packed-struct.rs b/src/test/debug-info/packed-struct.rs new file mode 100644 index 0000000000000..11c09cfceb57b --- /dev/null +++ b/src/test/debug-info/packed-struct.rs @@ -0,0 +1,112 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print packed +// check:$1 = {x = 123, y = 234, z = 345} + +// debugger:print packedInPacked +// check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} + +// debugger:print packedInUnpacked +// check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} + +// debugger:print unpackedInPacked +// check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} + +// debugger:print sizeof(packed) +// check:$5 = 14 + +// debugger:print sizeof(packedInPacked) +// check:$6 = 40 + +// debugger:print sizeof(packedInUnpacked) +// check:$7 = 48 + +// debugger:print sizeof(unpackedInPacked) +// check:$8 = 58 + + + +#[packed] +struct Packed { + x: i16, + y: i32, + z: i64 +} + +#[packed] +struct PackedInPacked { + a: i32, + b: Packed, + c: i64, + d: Packed +} + +// layout: aaaa bbbb bbbb bbbb bb.. .... cccc cccc dddd dddd dddd dd.. +struct PackedInUnpacked { + a: i32, + b: Packed, + c: i64, + d: Packed +} + +// layout: xx.. yyyy zz.. .... wwww wwww +struct Unpacked { + x: i16, + y: i32, + z: i16, + w: i64 +} + +// layout: aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd +#[packed] +struct UnpackedInPacked { + a: i16, + b: Unpacked, + c: Unpacked, + d: i64 +} + +fn main() { + let packed = Packed { x: 123, y: 234, z: 345 }; + + let packedInPacked = PackedInPacked { + a: 1111, + b: Packed { x: 2222, y: 3333, z: 4444 }, + c: 5555, + d: Packed { x: 6666, y: 7777, z: 8888 } + }; + + let packedInUnpacked = PackedInUnpacked { + a: -1111, + b: Packed { x: -2222, y: -3333, z: -4444 }, + c: -5555, + d: Packed { x: -6666, y: -7777, z: -8888 } + }; + + let unpackedInPacked = UnpackedInPacked { + a: 987, + b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, + c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, + d: -98 + }; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs index 9c72c676d5446..87e61ebe373f2 100644 --- a/src/test/debug-info/struct-with-destructor.rs +++ b/src/test/debug-info/struct-with-destructor.rs @@ -21,6 +21,13 @@ // debugger:print withDestructor // check:$3 = {a = {x = 10, y = 20}, guard = -1} +// debugger:print nested +// check:$4 = {a = {a = {x = 7890, y = 9870}}} + +// debugger:print sizeof(nested) +// check:$5 = 32 + + struct NoDestructor { x : i32, y : i64 @@ -45,6 +52,18 @@ struct WithDestructorGuarded { guard: i64 } +struct NestedInner { + a: WithDestructor +} + +impl Drop for NestedInner { + fn drop(&self) {} +} + +struct NestedOuter { + a: NestedInner +} + // The compiler adds a 'destructed' boolean field to structs implementing Drop. This field is used // at runtime to prevent drop() to be executed more than once (see middle::trans::adt). @@ -80,6 +99,12 @@ fn main() { guard: -1 }; + // expected layout = xxxx....yyyyyyyyD.......D... + // <--WithDestructor------> + // <-------NestedInner--------> + // <-------NestedOuter--------> + let nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }; + zzz(); } From 739f3eece9c341f4f1e70b8a0417853ed2a09cbc Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 2 Jul 2013 10:33:51 +0200 Subject: [PATCH 08/26] debuginfo: Added support for c-style enums. --- src/librustc/lib/llvm.rs | 21 ++- src/librustc/middle/trans/debuginfo.rs | 123 +++++++++++++----- src/rustllvm/RustWrapper.cpp | 30 +++++ src/test/debug-info/borrowed-basic.rs | 5 +- src/test/debug-info/borrowed-c-style-enum.rs | 42 ++++++ .../debug-info/c-style-enum-in-composite.rs | 117 +++++++++++++++++ src/test/debug-info/c-style-enum.rs | 60 +++++++++ 7 files changed, 361 insertions(+), 37 deletions(-) create mode 100644 src/test/debug-info/borrowed-c-style-enum.rs create mode 100644 src/test/debug-info/c-style-enum-in-composite.rs create mode 100644 src/test/debug-info/c-style-enum.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 215c002eec8d2..bfa8d84d5b0b8 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -2097,8 +2097,25 @@ pub mod llvm { Val: ValueRef, VarInfo: DIVariable, InsertBefore: ValueRef) -> ValueRef; - } -} + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateEnumerator( + Builder: DIBuilderRef, + Name: *c_char, + Val: c_ulonglong) -> ValueRef; + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateEnumerationType( + Builder: DIBuilderRef, + Scope: ValueRef, + Name: *c_char, + File: ValueRef, + LineNumber: c_uint, + SizeInBits: c_ulonglong, + AlignInBits: c_ulonglong, + Elements: ValueRef, + ClassType: ValueRef) -> ValueRef; +}} pub fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) { unsafe { diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index e2a8f8e01303c..d3878e242f3d2 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -143,11 +143,11 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { let loc = span_start(cx, local.span); let ty = node_id_type(bcx, local.node.id); - let tymd = get_or_create_ty(cx, ty, local.node.ty.span); + let tymd = get_or_create_type(cx, ty, local.node.ty.span); let filemd = get_or_create_file(cx, loc.file.name); let context = match bcx.parent { None => create_function(bcx.fcx), - Some(_) => create_block(bcx) + Some(_) => get_or_create_block(bcx) }; let var_md = do as_c_str(name) |name| { unsafe { @@ -167,7 +167,7 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { } }; - set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, get_or_create_block(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_md, bcx.llbb); llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); @@ -197,7 +197,7 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option } let ty = node_id_type(bcx, arg.id); - let tymd = get_or_create_ty(cx, ty, arg.ty.span); + let tymd = get_or_create_type(cx, ty, arg.ty.span); let filemd = get_or_create_file(cx, loc.file.name); let context = create_function(fcx); @@ -222,7 +222,7 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option }}; let llptr = fcx.llargs.get_copy(&arg.id); - set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, get_or_create_block(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( DIB(cx), llptr, mdnode, bcx.llbb); @@ -245,7 +245,7 @@ pub fn update_source_pos(bcx: block, span: span) { } debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span)); let loc = span_start(bcx.ccx(), span); - set_debug_location(bcx.ccx(), create_block(bcx), loc.line, loc.col.to_uint()) + set_debug_location(bcx.ccx(), get_or_create_block(bcx), loc.line, loc.col.to_uint()) } /// Creates debug information for the given function. @@ -297,7 +297,7 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { let ret_ty_md = if cx.sess.opts.extra_debuginfo { match ret_ty.node { ast::ty_nil => ptr::null(), - _ => get_or_create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) + _ => get_or_create_type(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) } } else { ptr::null() @@ -397,7 +397,7 @@ fn get_or_create_file(cx: &mut CrateContext, full_path: &str) -> DIFile { -fn create_block(bcx: block) -> DILexicalBlock { +fn get_or_create_block(bcx: block) -> DILexicalBlock { let mut bcx = bcx; let cx = bcx.ccx(); @@ -415,11 +415,11 @@ fn create_block(bcx: block) -> DILexicalBlock { None => () } - debug!("create_block: %s", bcx.sess().codemap.span_to_str(span)); + debug!("get_or_create_block: %s", bcx.sess().codemap.span_to_str(span)); let parent = match bcx.parent { None => create_function(bcx.fcx), - Some(b) => create_block(b) + Some(b) => get_or_create_block(b) }; let cx = bcx.ccx(); let loc = span_start(cx, span); @@ -508,7 +508,7 @@ fn create_struct(cx: &mut CrateContext, let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty)); let field_names = fields.map(|field| cx.sess.str_of(field.ident).to_owned()); - let field_types_metadata = fields.map(|field| get_or_create_ty(cx, field.mt.ty, span)); + let field_types_metadata = fields.map(|field| get_or_create_type(cx, field.mt.ty, span)); return create_composite_type( cx, @@ -533,7 +533,7 @@ fn create_tuple(cx: &mut CrateContext, component_names.grow_fn(component_types.len(), |_| ~""); let component_llvm_types = component_types.map(|it| type_of::type_of(cx, *it)); - let component_types_metadata = component_types.map(|it| get_or_create_ty(cx, *it, span)); + let component_types_metadata = component_types.map(|it| get_or_create_type(cx, *it, span)); return create_composite_type( cx, @@ -545,6 +545,66 @@ fn create_tuple(cx: &mut CrateContext, span); } +fn create_enum_md(cx: &mut CrateContext, + enum_type: ty::t, + enum_def_id: ast::def_id, + span: span) -> DIType { + + let enum_name = ty_to_str(cx.tcx, enum_type); + let discriminator_llvm_type = Type::enum_discrim(cx); + let discriminator_size = machine::llsize_of_alloc(cx, discriminator_llvm_type); + let discriminator_align = machine::llalign_of_min(cx, discriminator_llvm_type); + + assert!(Type::enum_discrim(cx) == cx.int_type); + let discriminator_type_md = get_or_create_type(cx, ty::mk_int(), span); + + if ty::type_is_empty(cx.tcx, enum_type) { + // XXX: This should not "rename" the type to nil + return get_or_create_type(cx, ty::mk_nil(), span); + } + + if ty::type_is_c_like_enum(cx.tcx, enum_type) { + + let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); + + let enumerators : ~[(~str, int)] = variants + .iter() + .transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val)) + .collect(); + + let enumerators_md : ~[DIDescriptor] = + do enumerators.iter().transform |&(name,value)| { + do name.as_c_str |name| { unsafe { + llvm::LLVMDIBuilderCreateEnumerator( + DIB(cx), + name, + value as c_ulonglong) + }} + }.collect(); + + let loc = span_start(cx, span); + let file_metadata = get_or_create_file(cx, loc.file.name); + + return 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(discriminator_size), + bytes_to_bits(discriminator_align), + create_DIArray(DIB(cx), enumerators_md), + discriminator_type_md) + }}; + } + + cx.sess.bug(""); +} + + + + /// Creates debug information for a composite type, that is, anything that results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. @@ -636,10 +696,10 @@ fn create_boxed_type(cx: &mut CrateContext, let nil_pointer_type = ty::mk_nil_ptr(cx.tcx); let member_types_metadata = [ - get_or_create_ty(cx, int_type, span), - get_or_create_ty(cx, nil_pointer_type, span), - get_or_create_ty(cx, nil_pointer_type, span), - get_or_create_ty(cx, nil_pointer_type, span), + get_or_create_type(cx, int_type, span), + get_or_create_type(cx, nil_pointer_type, span), + get_or_create_type(cx, nil_pointer_type, span), + get_or_create_type(cx, nil_pointer_type, span), content_type_metadata ]; @@ -671,7 +731,7 @@ fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t, len: uint, span: span) -> DIType { debug!("create_fixed_vec: %?", ty::get(_vec_t)); - let elem_ty_md = get_or_create_ty(cx, elem_t, span); + let elem_ty_md = get_or_create_type(cx, elem_t, span); let (size, align) = size_and_align_of(cx, elem_t); let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange( @@ -695,7 +755,7 @@ fn create_boxed_vec(cx: &mut CrateContext, span: span) -> DICompositeType { - let element_type_metadata = get_or_create_ty(cx, element_type, span); + let element_type_metadata = get_or_create_type(cx, element_type, span); let element_llvm_type = type_of::type_of(cx, element_type); let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type); let vec_type_name = &"vec"; @@ -703,7 +763,7 @@ fn create_boxed_vec(cx: &mut CrateContext, let member_llvm_types = vec_llvm_type.field_types(); let member_names = &[~"fill", ~"alloc", ~"elements"]; - let int_type_md = get_or_create_ty(cx, ty::mk_int(), span); + let int_type_md = get_or_create_type(cx, ty::mk_int(), span); let array_type_md = unsafe { llvm::LLVMDIBuilderCreateArrayType( DIB(cx), bytes_to_bits(machine::llsize_of_alloc(cx, element_llvm_type)), @@ -746,8 +806,8 @@ fn create_vec_slice(cx: &mut CrateContext, let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const }); let member_type_metadata = &[ - get_or_create_ty(cx, data_ptr_type, span), - get_or_create_ty(cx, ty::mk_uint(), span) + get_or_create_type(cx, data_ptr_type, span), + get_or_create_type(cx, ty::mk_uint(), span) ]; return create_composite_type( @@ -776,9 +836,9 @@ fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: let loc = span_start(cx, span); let file_md = get_or_create_file(cx, loc.file.name); let (vp, _, _) = voidptr(cx); - let output_md = get_or_create_ty(cx, output, span); + let output_md = get_or_create_type(cx, output, span); let output_ptr_md = create_pointer_type(cx, output, span, output_md); - let inputs_vals = do inputs.map |arg| { get_or_create_ty(cx, *arg, span) }; + let inputs_vals = do inputs.map |arg| { get_or_create_type(cx, *arg, span) }; let members = ~[output_ptr_md, vp] + inputs_vals; return unsafe { @@ -804,14 +864,14 @@ fn create_unimpl_ty(cx: &mut CrateContext, t: ty::t) -> DIType { return md; } -fn get_or_create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { +fn get_or_create_type(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { let ty_id = ty::type_id(t); match dbg_cx(cx).created_types.find(&ty_id) { Some(ty_md) => return *ty_md, None => () } - debug!("get_or_create_ty: %?", ty::get(t)); + debug!("get_or_create_type: %?", ty::get(t)); let sty = copy ty::get(t).sty; let ty_md = match sty { @@ -839,14 +899,15 @@ fn get_or_create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { } } }, - ty::ty_enum(_did, ref _substs) => { - cx.sess.span_note(span, "debuginfo for enum NYI"); - create_unimpl_ty(cx, t) + ty::ty_enum(def_id, ref _substs) => { + //cx.sess.span_note(span, "debuginfo for enum NYI"); + //create_unimpl_ty(cx, t) + create_enum_md(cx, t, def_id, span) }, ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => { let content_llvm_type = type_of::type_of(cx, mt.ty); - let content_type_metadata = get_or_create_ty(cx, mt.ty, span); + let content_type_metadata = get_or_create_type(cx, mt.ty, span); let box_metadata = create_boxed_type(cx, content_llvm_type, @@ -872,7 +933,7 @@ fn get_or_create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { }, ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { - let pointee = get_or_create_ty(cx, mt.ty, span); + let pointee = get_or_create_type(cx, mt.ty, span); create_pointer_type(cx, t, span, pointee) }, ty::ty_bare_fn(ref barefnty) => { @@ -895,7 +956,7 @@ fn get_or_create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { ty::ty_tup(ref elements) => { create_tuple(cx, t, *elements, span) }, - _ => cx.sess.bug("debuginfo: unexpected type in get_or_create_ty") + _ => cx.sess.bug("debuginfo: unexpected type in get_or_create_type") }; dbg_cx(cx).created_types.insert(ty_id, ty_md); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 614c1723c5fb7..27ba508293e94 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -785,3 +785,33 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore( unwrapDI(VarInfo), unwrap(InsertBefore))); } + +extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerator( + DIBuilderRef Builder, + const char* Name, + uint64_t Val) +{ + return wrap(Builder->createEnumerator(Name, Val)); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType( + DIBuilderRef Builder, + LLVMValueRef Scope, + const char* Name, + LLVMValueRef File, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMValueRef Elements, + LLVMValueRef ClassType) +{ + return wrap(Builder->createEnumerationType( + unwrapDI(Scope), + Name, + unwrapDI(File), + LineNumber, + SizeInBits, + AlignInBits, + unwrapDI(Elements), + unwrapDI(ClassType))); +} \ No newline at end of file diff --git a/src/test/debug-info/borrowed-basic.rs b/src/test/debug-info/borrowed-basic.rs index dfd0fbf865557..8e46816d41c35 100644 --- a/src/test/debug-info/borrowed-basic.rs +++ b/src/test/debug-info/borrowed-basic.rs @@ -10,10 +10,7 @@ // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 -// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values) -// as its numerical value along with its associated ASCII char, there -// doesn't seem to be any way around this. Also, gdb doesn't know -// about UTF-32 character encoding and will print a rust char as only +// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only // its numerical value. // compile-flags:-Z extra-debug-info diff --git a/src/test/debug-info/borrowed-c-style-enum.rs b/src/test/debug-info/borrowed-c-style-enum.rs new file mode 100644 index 0000000000000..2ca4c5a4397f7 --- /dev/null +++ b/src/test/debug-info/borrowed-c-style-enum.rs @@ -0,0 +1,42 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print *the_a_ref +// check:$1 = TheA + +// debugger:print *the_b_ref +// check:$2 = TheB + +// debugger:print *the_c_ref +// check:$3 = TheC + +enum ABC { TheA, TheB, TheC } + +fn main() { + let the_a = TheA; + let the_a_ref : &ABC = &the_a; + + let the_b = TheB; + let the_b_ref : &ABC = &the_b; + + let the_c = TheC; + let the_c_ref : &ABC = &the_c; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/c-style-enum-in-composite.rs b/src/test/debug-info/c-style-enum-in-composite.rs new file mode 100644 index 0000000000000..601d8ed441c13 --- /dev/null +++ b/src/test/debug-info/c-style-enum-in-composite.rs @@ -0,0 +1,117 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print tuple_interior_padding +// check:$1 = {0, OneHundred} + +// debugger:print tuple_padding_at_end +// check:$2 = {{1, OneThousand}, 2} + +// debugger:print tuple_different_enums +// check:$3 = {OneThousand, MountainView, OneMillion, Vienna} + +// debugger:print padded_struct +// check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} + +// debugger:print packed_struct +// check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} + +// debugger:print non_padded_struct +// check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} + +// debugger:print struct_with_drop +// check:$7 = {{a = OneHundred, b = Vienna}, 9} + +enum AnEnum { + OneHundred = 100, + OneThousand = 1000, + OneMillion = 1000000 +} + +enum AnotherEnum { + MountainView, + Toronto, + Vienna +} + +struct PaddedStruct { + a: i16, + b: AnEnum, + c: i16, + d: AnotherEnum, + e: i16 +} + +#[packed] +struct PackedStruct { + a: i16, + b: AnEnum, + c: i16, + d: AnotherEnum, + e: i16 +} + +struct NonPaddedStruct { + a: AnEnum, + b: AnotherEnum, + c: AnEnum, + d: AnotherEnum +} + +struct StructWithDrop { + a: AnEnum, + b: AnotherEnum +} + +impl Drop for StructWithDrop { + fn drop(&self) {()} +} + +fn main() { + + let tuple_interior_padding = (0_i16, OneHundred); + // It will depend on the machine architecture if any padding is actually involved here + let tuple_padding_at_end = ((1_u64, OneThousand), 2_u64); + let tuple_different_enums = (OneThousand, MountainView, OneMillion, Vienna); + + let padded_struct = PaddedStruct { + a: 3, + b: OneMillion, + c: 4, + d: Toronto, + e: 5 + }; + + let packed_struct = PackedStruct { + a: 6, + b: OneHundred, + c: 7, + d: Vienna, + e: 8 + }; + + let non_padded_struct = NonPaddedStruct { + a: OneMillion, + b: MountainView, + c: OneThousand, + d: Toronto + }; + + let struct_with_drop = (StructWithDrop { a: OneHundred, b: Vienna }, 9_i64); + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/c-style-enum.rs b/src/test/debug-info/c-style-enum.rs new file mode 100644 index 0000000000000..408e98102663a --- /dev/null +++ b/src/test/debug-info/c-style-enum.rs @@ -0,0 +1,60 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print auto_one +// check:$1 = One + +// debugger:print auto_two +// check:$2 = Two + +// debugger:print auto_three +// check:$3 = Three + +// debugger:print manual_one_hundred +// check:$4 = OneHundred + +// debugger:print manual_one_thousand +// check:$5 = OneThousand + +// debugger:print manual_one_million +// check:$6 = OneMillion + + +enum AutoDiscriminator { + One, + Two, + Three +} + +enum ManualDiscriminator { + OneHundred = 100, + OneThousand = 1000, + OneMillion = 1000000 +} + +fn main() { + + let auto_one = One; + let auto_two = Two; + let auto_three = Three; + + let manual_one_hundred = OneHundred; + let manual_one_thousand = OneThousand; + let manual_one_million = OneMillion; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file From f389bd8f2a72020c25e37b81757643abd481bc11 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 2 Jul 2013 18:10:24 +0200 Subject: [PATCH 09/26] debuginfo: Support for tuple-style enums (WIP) --- src/librustc/lib/llvm.rs | 16 ++- src/librustc/middle/trans/debuginfo.rs | 144 ++++++++++++++++-------- src/rustllvm/RustWrapper.cpp | 108 +++++++++++------- src/test/debug-info/c-style-enum.rs | 12 +- src/test/debug-info/nil-enum.rs | 38 +++++++ src/test/debug-info/tuple-style-enum.rs | 33 ++++++ 6 files changed, 261 insertions(+), 90 deletions(-) create mode 100644 src/test/debug-info/nil-enum.rs create mode 100644 src/test/debug-info/tuple-style-enum.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index bfa8d84d5b0b8..1ce4108b3b55d 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -2115,7 +2115,21 @@ pub mod llvm { AlignInBits: c_ulonglong, Elements: ValueRef, ClassType: ValueRef) -> ValueRef; -}} + + #[fast_ffi] + pub unsafe fn LLVMDIBuilderCreateUnionType( + Builder: DIBuilderRef, + Scope: ValueRef, + Name: *c_char, + File: ValueRef, + LineNumber: c_uint, + SizeInBits: c_ulonglong, + AlignInBits: c_ulonglong, + Flags: c_uint , + Elements: ValueRef, + RunTimeLang : c_uint) -> ValueRef; + } +} pub fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) { unsafe { diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index d3878e242f3d2..86bdf509d6583 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -501,9 +501,9 @@ fn create_struct(cx: &mut CrateContext, fields: ~[ty::field], span: span) -> DICompositeType { - debug!("create_struct: %?", ty::get(struct_type)); - let struct_name = ty_to_str(cx.tcx, struct_type); + debug!("create_struct: %s", struct_name); + let struct_llvm_type = type_of::type_of(cx, struct_type); let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty)); @@ -526,7 +526,7 @@ fn create_tuple(cx: &mut CrateContext, span: span) -> DICompositeType { - let tuple_name = "tuple"; // this should have a better name + let tuple_name = ty_to_str(cx.tcx, tuple_type); let tuple_llvm_type = type_of::type_of(cx, tuple_type); // Create a vec of empty strings. A vec::build_n() function would be nice for this. let mut component_names : ~[~str] = vec::with_capacity(component_types.len()); @@ -548,61 +548,117 @@ fn create_tuple(cx: &mut CrateContext, fn create_enum_md(cx: &mut CrateContext, enum_type: ty::t, enum_def_id: ast::def_id, - span: span) -> DIType { + substs: &ty::substs, + span: span) + -> DIType { let enum_name = ty_to_str(cx.tcx, enum_type); - let discriminator_llvm_type = Type::enum_discrim(cx); - let discriminator_size = machine::llsize_of_alloc(cx, discriminator_llvm_type); - let discriminator_align = machine::llalign_of_min(cx, discriminator_llvm_type); - - assert!(Type::enum_discrim(cx) == cx.int_type); - let discriminator_type_md = get_or_create_type(cx, ty::mk_int(), span); + // For empty enums there is an early exit. Just describe it as an empty struct with the + // appropriate name if ty::type_is_empty(cx.tcx, enum_type) { - // XXX: This should not "rename" the type to nil - return get_or_create_type(cx, ty::mk_nil(), span); + return create_composite_type(cx, Type::nil(), enum_name, &[], &[], &[], span); } - if ty::type_is_c_like_enum(cx.tcx, enum_type) { + // 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 = machine::llsize_of_alloc(cx, discriminant_llvm_type); + let discriminant_align = machine::llalign_of_min(cx, discriminant_llvm_type); + assert!(Type::enum_discrim(cx) == cx.int_type); + let discriminant_type_md = get_or_create_type(cx, ty::mk_int(), span); + + + let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); - let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); + let enumerators : ~[(~str, int)] = variants + .iter() + .transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val)) + .collect(); + + let enumerators_md : ~[DIDescriptor] = + do enumerators.iter().transform |&(name,value)| { + do name.as_c_str |name| { unsafe { + llvm::LLVMDIBuilderCreateEnumerator( + DIB(cx), + name, + value as c_ulonglong) + }} + }.collect(); - let enumerators : ~[(~str, int)] = variants - .iter() - .transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val)) - .collect(); + let loc = span_start(cx, span); + let file_metadata = get_or_create_file(cx, loc.file.name); - let enumerators_md : ~[DIDescriptor] = - do enumerators.iter().transform |&(name,value)| { - do name.as_c_str |name| { unsafe { - llvm::LLVMDIBuilderCreateEnumerator( - DIB(cx), - name, - value as c_ulonglong) - }} - }.collect(); + let discriminant_type_md = 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_md), + discriminant_type_md) + }}; - let loc = span_start(cx, span); - let file_metadata = get_or_create_file(cx, loc.file.name); + if ty::type_is_c_like_enum(cx.tcx, enum_type) { + return discriminant_type_md; + } - return do enum_name.as_c_str |enum_name| { unsafe { - llvm::LLVMDIBuilderCreateEnumerationType( + let variants_md = do variants.map |&vi| { + + let raw_types : &[ty::t] = vi.args; + let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) }; + let arg_llvm_types = ~[discriminant_llvm_type] + do arg_types.map |&ty| { type_of::type_of(cx, ty) }; + let arg_names = ~[~""] + arg_types.map(|_| ~""); + let arg_md = ~[discriminant_type_md] + do arg_types.map |&ty| { get_or_create_type(cx, ty, span) }; + + let variant_llvm_type = Type::struct_(arg_llvm_types, false); + let variant_type_size = machine::llsize_of_alloc(cx, variant_llvm_type); + let variant_type_align = machine::llalign_of_min(cx, variant_llvm_type); + + let variant_type_md = create_composite_type( + cx, + variant_llvm_type, + &"", + arg_llvm_types, + arg_names, + arg_md, + span); + + do "".as_c_str |name| { unsafe { + llvm::LLVMDIBuilderCreateMemberType( DIB(cx), file_metadata, - enum_name, + name, file_metadata, loc.line as c_uint, - bytes_to_bits(discriminator_size), - bytes_to_bits(discriminator_align), - create_DIArray(DIB(cx), enumerators_md), - discriminator_type_md) - }}; - } - - cx.sess.bug(""); -} + bytes_to_bits(variant_type_size), + bytes_to_bits(variant_type_align), + bytes_to_bits(0), + 0, + variant_type_md) + }} + }; + let enum_llvm_type = type_of::type_of(cx, enum_type); + let enum_type_size = machine::llsize_of_alloc(cx, enum_llvm_type); + let enum_type_align = machine::llalign_of_min(cx, enum_llvm_type); + return do "".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_md), + 0) // RuntimeLang + }}; +} /// Creates debug information for a composite type, that is, anything that results in a LLVM struct. @@ -899,10 +955,8 @@ fn get_or_create_type(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { } } }, - ty::ty_enum(def_id, ref _substs) => { - //cx.sess.span_note(span, "debuginfo for enum NYI"); - //create_unimpl_ty(cx, t) - create_enum_md(cx, t, def_id, span) + ty::ty_enum(def_id, ref substs) => { + create_enum_md(cx, t, def_id, substs, span) }, ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => { diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 27ba508293e94..2a1f26bf44108 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -565,8 +565,8 @@ extern "C" bool LLVMRustStartMultithreading() { typedef DIBuilder* DIBuilderRef; template -DIT unwrapDI(LLVMValueRef ref) { - return DIT(ref ? unwrap(ref) : NULL); +DIT unwrapDI(LLVMValueRef ref) { + return DIT(ref ? unwrap(ref) : NULL); } extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) { @@ -604,21 +604,21 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFile( extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType( DIBuilderRef Builder, - LLVMValueRef File, + LLVMValueRef File, LLVMValueRef ParameterTypes) { return wrap(Builder->createSubroutineType( - unwrapDI(File), + unwrapDI(File), unwrapDI(ParameterTypes))); } extern "C" LLVMValueRef LLVMDIBuilderCreateFunction( DIBuilderRef Builder, - LLVMValueRef Scope, + LLVMValueRef Scope, const char* Name, const char* LinkageName, - LLVMValueRef File, + LLVMValueRef File, unsigned LineNo, - LLVMValueRef Ty, + LLVMValueRef Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, @@ -628,11 +628,11 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFunction( LLVMValueRef TParam, LLVMValueRef Decl) { return wrap(Builder->createFunction( - unwrapDI(Scope), Name, LinkageName, - unwrapDI(File), LineNo, - unwrapDI(Ty), isLocalToUnit, isDefinition, ScopeLine, + unwrapDI(Scope), Name, LinkageName, + unwrapDI(File), LineNo, + unwrapDI(Ty), isLocalToUnit, isDefinition, ScopeLine, Flags, isOptimized, - unwrap(Fn), + unwrap(Fn), unwrapDI(TParam), unwrapDI(Decl))); } @@ -644,10 +644,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType( uint64_t AlignInBits, unsigned Encoding) { return wrap(Builder->createBasicType( - Name, SizeInBits, + Name, SizeInBits, AlignInBits, Encoding)); } - + extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType( DIBuilderRef Builder, LLVMValueRef PointeeTy, @@ -672,11 +672,11 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStructType( unsigned RunTimeLang, LLVMValueRef VTableHolder) { return wrap(Builder->createStructType( - unwrapDI(Scope), Name, - unwrapDI(File), LineNumber, - SizeInBits, AlignInBits, Flags, - unwrapDI(DerivedFrom), - unwrapDI(Elements), RunTimeLang, + unwrapDI(Scope), Name, + unwrapDI(File), LineNumber, + SizeInBits, AlignInBits, Flags, + unwrapDI(DerivedFrom), + unwrapDI(Elements), RunTimeLang, unwrapDI(VTableHolder))); } @@ -692,12 +692,12 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType( unsigned Flags, LLVMValueRef Ty) { return wrap(Builder->createMemberType( - unwrapDI(Scope), Name, + unwrapDI(Scope), Name, unwrapDI(File), LineNo, - SizeInBits, AlignInBits, OffsetInBits, Flags, + SizeInBits, AlignInBits, OffsetInBits, Flags, unwrapDI(Ty))); } - + extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock( DIBuilderRef Builder, LLVMValueRef Scope, @@ -705,10 +705,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock( unsigned Line, unsigned Col) { return wrap(Builder->createLexicalBlock( - unwrapDI(Scope), + unwrapDI(Scope), unwrapDI(File), Line, Col)); } - + extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable( DIBuilderRef Builder, unsigned Tag, @@ -720,45 +720,45 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable( bool AlwaysPreserve, unsigned Flags, unsigned ArgNo) { - return wrap(Builder->createLocalVariable(Tag, - unwrapDI(Scope), Name, - unwrapDI(File), - LineNo, + return wrap(Builder->createLocalVariable(Tag, + unwrapDI(Scope), Name, + unwrapDI(File), + LineNo, unwrapDI(Ty), AlwaysPreserve, Flags, ArgNo)); } extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType( DIBuilderRef Builder, - uint64_t Size, - uint64_t AlignInBits, - LLVMValueRef Ty, + uint64_t Size, + uint64_t AlignInBits, + LLVMValueRef Ty, LLVMValueRef Subscripts) { return wrap(Builder->createArrayType(Size, AlignInBits, - unwrapDI(Ty), + unwrapDI(Ty), unwrapDI(Subscripts))); } extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType( DIBuilderRef Builder, - uint64_t Size, - uint64_t AlignInBits, - LLVMValueRef Ty, + uint64_t Size, + uint64_t AlignInBits, + LLVMValueRef Ty, LLVMValueRef Subscripts) { return wrap(Builder->createVectorType(Size, AlignInBits, - unwrapDI(Ty), + unwrapDI(Ty), unwrapDI(Subscripts))); } extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange( - DIBuilderRef Builder, - int64_t Lo, + DIBuilderRef Builder, + int64_t Lo, int64_t Count) { return wrap(Builder->getOrCreateSubrange(Lo, Count)); } extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray( DIBuilderRef Builder, - LLVMValueRef* Ptr, + LLVMValueRef* Ptr, unsigned Count) { return wrap(Builder->getOrCreateArray( ArrayRef(reinterpret_cast(Ptr), Count))); @@ -770,8 +770,8 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( LLVMValueRef VarInfo, LLVMBasicBlockRef InsertAtEnd) { return wrap(Builder->insertDeclare( - unwrap(Val), - unwrapDI(VarInfo), + unwrap(Val), + unwrapDI(VarInfo), unwrap(InsertAtEnd))); } @@ -781,8 +781,8 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore( LLVMValueRef VarInfo, LLVMValueRef InsertBefore) { return wrap(Builder->insertDeclare( - unwrap(Val), - unwrapDI(VarInfo), + unwrap(Val), + unwrapDI(VarInfo), unwrap(InsertBefore))); } @@ -814,4 +814,28 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType( AlignInBits, unwrapDI(Elements), unwrapDI(ClassType))); +} + +extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType( + DIBuilderRef Builder, + LLVMValueRef Scope, + const char* Name, + LLVMValueRef File, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Flags, + LLVMValueRef Elements, + unsigned RunTimeLang) +{ + return wrap(Builder->createUnionType( + unwrapDI(Scope), + Name, + unwrapDI(File), + LineNumber, + SizeInBits, + AlignInBits, + Flags, + unwrapDI(Elements), + RunTimeLang)); } \ No newline at end of file diff --git a/src/test/debug-info/c-style-enum.rs b/src/test/debug-info/c-style-enum.rs index 408e98102663a..3071cb2d326c7 100644 --- a/src/test/debug-info/c-style-enum.rs +++ b/src/test/debug-info/c-style-enum.rs @@ -31,19 +31,25 @@ // debugger:print manual_one_million // check:$6 = OneMillion +// debugger:print single_variant +// check:$7 = TheOnlyVariant -enum AutoDiscriminator { +enum AutoDiscriminant { One, Two, Three } -enum ManualDiscriminator { +enum ManualDiscriminant { OneHundred = 100, OneThousand = 1000, OneMillion = 1000000 } +enum SingleVariant { + TheOnlyVariant +} + fn main() { let auto_one = One; @@ -54,6 +60,8 @@ fn main() { let manual_one_thousand = OneThousand; let manual_one_million = OneMillion; + let single_variant = TheOnlyVariant; + zzz(); } diff --git a/src/test/debug-info/nil-enum.rs b/src/test/debug-info/nil-enum.rs new file mode 100644 index 0000000000000..09f41ee9f4267 --- /dev/null +++ b/src/test/debug-info/nil-enum.rs @@ -0,0 +1,38 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print first +// check:$1 = {} + +// debugger:print second +// check:$2 = {} + +enum ANilEnum {} +enum AnotherNilEnum {} + +// I (mw) am not sure this test case makes much sense... +// Also, it relies on some implementation details: +// 1. That empty enums as well as '()' are represented as empty structs +// 2. That gdb prints the string "{}" for empty structs (which may change some time) +fn main() { + unsafe { + let first : ANilEnum = std::cast::transmute(()); + let second : AnotherNilEnum = std::cast::transmute(()); + + zzz(); + } +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs new file mode 100644 index 0000000000000..00144aa1bb537 --- /dev/null +++ b/src/test/debug-info/tuple-style-enum.rs @@ -0,0 +1,33 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print union on +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print case2 +// check:$1 = {Case1, 0, 1} + +enum Test { + Case1(i32, i64), + Case2(bool, i16, i32) +} + +fn main() { + + let case1 = Case1(110, 220); + let case2 = Case2(false, 2, 3); + + zzz(); +} + +fn zzz() {()} \ No newline at end of file From 7cf0aac6cf2435e068c4bd62cd34e06f8ef0bd91 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 4 Jul 2013 13:34:19 +0200 Subject: [PATCH 10/26] debuginfo: Better support for univariant tuple-style enums. --- src/librustc/middle/trans/debuginfo.rs | 17 +++++++++++++---- src/test/debug-info/tuple-style-enum.rs | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 86bdf509d6583..34ebdd81bc0c3 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -606,13 +606,22 @@ fn create_enum_md(cx: &mut CrateContext, return discriminant_type_md; } + let is_univariant = variants.len() == 1; + let variants_md = do variants.map |&vi| { let raw_types : &[ty::t] = vi.args; let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) }; - let arg_llvm_types = ~[discriminant_llvm_type] + do arg_types.map |&ty| { type_of::type_of(cx, ty) }; - let arg_names = ~[~""] + arg_types.map(|_| ~""); - let arg_md = ~[discriminant_type_md] + do arg_types.map |&ty| { get_or_create_type(cx, ty, span) }; + + let mut arg_llvm_types = do arg_types.map |&ty| { type_of::type_of(cx, ty) }; + let mut arg_names = arg_types.map(|_| ~""); + let mut arg_md = do arg_types.map |&ty| { get_or_create_type(cx, ty, span) }; + + if !is_univariant { + arg_llvm_types.insert(0, discriminant_llvm_type); + arg_names.insert(0, ~""); + arg_md.insert(0, discriminant_type_md); + } let variant_llvm_type = Type::struct_(arg_llvm_types, false); let variant_type_size = machine::llsize_of_alloc(cx, variant_llvm_type); @@ -646,7 +655,7 @@ fn create_enum_md(cx: &mut CrateContext, let enum_type_size = machine::llsize_of_alloc(cx, enum_llvm_type); let enum_type_align = machine::llalign_of_min(cx, enum_llvm_type); - return do "".as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateUnionType( + return do enum_name.as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateUnionType( DIB(cx), file_metadata, enum_name, diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs index 00144aa1bb537..5c12649dea7ce 100644 --- a/src/test/debug-info/tuple-style-enum.rs +++ b/src/test/debug-info/tuple-style-enum.rs @@ -14,19 +14,29 @@ // debugger:run // debugger:finish -// debugger:print case2 -// check:$1 = {Case1, 0, 1} +// d ebugger:print case2 +// c heck:$1 = {Case1, 0, 1} -enum Test { +// debugger:print univariant +// check:$1 = {{-1}} + + +enum Regular { Case1(i32, i64), Case2(bool, i16, i32) } +enum Univariant { + TheOnlyCase(i64) +} + fn main() { let case1 = Case1(110, 220); let case2 = Case2(false, 2, 3); + let univariant = TheOnlyCase(-1); + zzz(); } From 3b06df4e35bbde6975575cd137e6f5f65d475d86 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 8 Jul 2013 17:27:07 +0200 Subject: [PATCH 11/26] debuginfo: Added support for struct-style enums. --- src/librustc/metadata/decoder.rs | 15 +++-- src/librustc/middle/trans/debuginfo.rs | 8 ++- src/librustc/middle/trans/machine.rs | 39 ------------- src/librustc/middle/ty.rs | 23 ++++++-- src/librustc/middle/typeck/check/mod.rs | 37 ++++++------ src/test/debug-info/struct-style-enum.rs | 71 ++++++++++++++++++++++++ src/test/debug-info/tuple-style-enum.rs | 44 ++++++++++++--- 7 files changed, 161 insertions(+), 76 deletions(-) create mode 100644 src/test/debug-info/struct-style-enum.rs diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index caa170605dec3..e748ae89a9dc7 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -753,11 +753,16 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, Some(val) => { disr_val = val; } _ => { /* empty */ } } - infos.push(@ty::VariantInfo_{args: arg_tys, - ctor_ty: ctor_ty, name: name, - // I'm not even sure if we encode visibility - // for variants -- TEST -- tjc - id: *did, disr_val: disr_val, vis: ast::inherited}); + infos.push(@ty::VariantInfo_{ + args: arg_tys, + arg_names: None, + ctor_ty: ctor_ty, + name: name, + // I'm not even sure if we encode visibility + // for variants -- TEST -- tjc + id: *did, + disr_val: disr_val, + vis: ast::inherited}); disr_val += 1; } return infos; diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 34ebdd81bc0c3..3c163e149d2db 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -612,9 +612,13 @@ fn create_enum_md(cx: &mut CrateContext, let raw_types : &[ty::t] = vi.args; let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) }; - + let mut arg_llvm_types = do arg_types.map |&ty| { type_of::type_of(cx, ty) }; - let mut arg_names = arg_types.map(|_| ~""); + let mut arg_names = match vi.arg_names { + Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() }, + None => do arg_types.map |_| { ~"" } + }; + let mut arg_md = do arg_types.map |&ty| { get_or_create_type(cx, ty, span) }; if !is_univariant { diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index c0b57a2206537..0bf0a522a655f 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -119,42 +119,3 @@ pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> ui return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as uint; } } - -// Computes the size of the data part of an enum. -pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint { - if cx.enum_sizes.contains_key(&t) { - return cx.enum_sizes.get_copy(&t); - } - - debug!("static_size_of_enum %s", ty_to_str(cx.tcx, t)); - - match ty::get(t).sty { - ty::ty_enum(tid, ref substs) => { - // Compute max(variant sizes). - let mut max_size = 0; - let variants = ty::enum_variants(cx.tcx, tid); - for variants.iter().advance |variant| { - if variant.args.len() == 0 { - loop; - } - - let lltypes = variant.args.map(|&variant_arg| { - let substituted = ty::subst(cx.tcx, substs, variant_arg); - type_of::sizing_type_of(cx, substituted) - }); - - debug!("static_size_of_enum: variant %s type %s", - cx.tcx.sess.str_of(variant.name), - cx.tn.type_to_str(Type::struct_(lltypes, false))); - - let this_size = llsize_of_real(cx, Type::struct_(lltypes, false)); - if max_size < this_size { - max_size = this_size; - } - } - cx.enum_sizes.insert(t, max_size); - return max_size; - } - _ => cx.sess.bug("static_size_of_enum called on non-enum") - } -} diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 50f331f7e7d48..9438d60a48004 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3694,6 +3694,7 @@ fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option { #[deriving(Clone)] pub struct VariantInfo_ { args: ~[t], + arg_names: Option<~[ast::ident]>, ctor_ty: t, name: ast::ident, id: ast::def_id, @@ -3875,6 +3876,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { } @VariantInfo_{ args: arg_tys, + arg_names: None, ctor_ty: ctor_ty, name: variant.node.name, id: ast_util::local_def(variant.node.id), @@ -3883,13 +3885,21 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { } }, ast::struct_variant_kind(struct_def) => { - let arg_tys = - // Is this check needed for structs too, or are they always guaranteed - // to have a valid constructor function? - if struct_def.fields.len() > 0 { - ty_fn_args(ctor_ty).map(|a| *a) + + let fields : &[@struct_field] = struct_def.fields; + + let (arg_tys, arg_names) = + if fields.len() > 0 { + let arg_tys = ty_fn_args(ctor_ty).map(|a| *a); + let arg_names = do fields.map |field| { match field.node.kind { + named_field(ident, _visibility) => ident, + unnamed_field => cx.sess.bug( + "enum_variants: all fields in struct must have a name") + }}; + + (arg_tys, Some(arg_names)) } else { - ~[] + (~[], None) }; assert!(variant.node.disr_expr.is_none()); @@ -3897,6 +3907,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { @VariantInfo_{ args: arg_tys, + arg_names: arg_names, ctor_ty: ctor_ty, name: variant.node.name, id: ast_util::local_def(variant.node.id), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 4a9e0fddbe73a..0e1f8e617ff7e 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3177,29 +3177,34 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, let this_disr_val = *disr_val; *disr_val += 1; - let arg_tys = match v.node.kind { + let (arg_tys, arg_names) = match v.node.kind { ast::tuple_variant_kind(ref args) if args.len() > 0u => { - Some(ty::ty_fn_args(ctor_ty).map(|a| *a)) + (ty::ty_fn_args(ctor_ty).map(|a| *a), None) } ast::tuple_variant_kind(_) => { - Some(~[]) + (~[], None) } - ast::struct_variant_kind(_) => { - Some(ty::lookup_struct_fields( - ccx.tcx, local_def(v.node.id)).map(|cf| - ty::node_id_to_type(ccx.tcx, cf.id.node))) + ast::struct_variant_kind(struct_def) => { + let tys = ty::ty_fn_args(ctor_ty).map(|a| *a); + let names = do struct_def.fields.map |field| { match field.node.kind { + ast::named_field(ident, _visibility) => ident, + ast::unnamed_field => ccx.tcx.sess.bug( + "enum_variants: all fields in struct must have a name") + }}; + + (tys, Some(names)) } }; - match arg_tys { - None => {} - Some(arg_tys) => { - variants.push( - @VariantInfo_{args: arg_tys, ctor_ty: ctor_ty, - name: v.node.name, id: local_def(v.node.id), - disr_val: this_disr_val, vis: v.node.vis}); - } - } + variants.push(@VariantInfo_{ + args: arg_tys, + arg_names: arg_names, + ctor_ty: ctor_ty, + name: v.node.name, + id: local_def(v.node.id), + disr_val: this_disr_val, + vis: v.node.vis + }); } } diff --git a/src/test/debug-info/struct-style-enum.rs b/src/test/debug-info/struct-style-enum.rs new file mode 100644 index 0000000000000..2be15e0f80f2e --- /dev/null +++ b/src/test/debug-info/struct-style-enum.rs @@ -0,0 +1,71 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print union on +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print case1 +// check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}} + +// debugger:print case2 +// check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}} + +// debugger:print case3 +// 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}} + +// 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 +// datatype layout should be predictable as in this case. +enum Regular { + Case1 { a: u64, b: u16, c: u16, d: u16, e: u16}, + Case2 { a: u64, b: u32, c: u32}, + Case3 { a: u64, b: u64 } +} + +enum Univariant { + TheOnlyCase { a: i64 } +} + +fn main() { + + // In order to avoid endianess trouble all of the following test values consist of a single + // repeated byte. This way each interpretation of the union should look the same, no matter if + // this is a big or little endian machine. + + // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452 + // 0b01111100011111000111110001111100 = 2088533116 + // 0b0111110001111100 = 31868 + // 0b01111100 = 124 + let case1 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 }; + + // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 + // 0b00010001000100010001000100010001 = 286331153 + // 0b0001000100010001 = 4369 + // 0b00010001 = 17 + let case2 = Case2 { a: 0, b: 286331153, c: 286331153 }; + + // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897 + // 0b01011001010110010101100101011001 = 1499027801 + // 0b0101100101011001 = 22873 + // 0b01011001 = 89 + let case3 = Case3 { a: 0, b: 6438275382588823897 }; + + let univariant = TheOnlyCase { a: -1 }; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs index 5c12649dea7ce..43b97a9bbfc4c 100644 --- a/src/test/debug-info/tuple-style-enum.rs +++ b/src/test/debug-info/tuple-style-enum.rs @@ -14,16 +14,25 @@ // debugger:run // debugger:finish -// d ebugger:print case2 -// c heck:$1 = {Case1, 0, 1} +// debugger:print case1 +// check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}} -// debugger:print univariant -// check:$1 = {{-1}} +// debugger:print case2 +// check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}} + +// debugger:print case3 +// check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}} +// debugger:print univariant +// 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 +// datatype layout should be predictable as in this case. enum Regular { - Case1(i32, i64), - Case2(bool, i16, i32) + Case1(u64, u16, u16, u16, u16), + Case2(u64, u32, u32), + Case3(u64, u64) } enum Univariant { @@ -32,8 +41,27 @@ enum Univariant { fn main() { - let case1 = Case1(110, 220); - let case2 = Case2(false, 2, 3); + // In order to avoid endianess trouble all of the following test values consist of a single + // repeated byte. This way each interpretation of the union should look the same, no matter if + // this is a big or little endian machine. + + // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452 + // 0b01111100011111000111110001111100 = 2088533116 + // 0b0111110001111100 = 31868 + // 0b01111100 = 124 + let case1 = Case1(0, 31868, 31868, 31868, 31868); + + // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 + // 0b00010001000100010001000100010001 = 286331153 + // 0b0001000100010001 = 4369 + // 0b00010001 = 17 + let case2 = Case2(0, 286331153, 286331153); + + // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897 + // 0b01011001010110010101100101011001 = 1499027801 + // 0b0101100101011001 = 22873 + // 0b01011001 = 89 + let case3 = Case3(0, 6438275382588823897); let univariant = TheOnlyCase(-1); From 77a00cca0307ad4d7de084b45168387e8d82d92e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 9 Jul 2013 15:14:10 +0200 Subject: [PATCH 12/26] debuginfo: Fixes related to changed memory layout of unique allocations --- src/librustc/middle/trans/debuginfo.rs | 7 +++---- src/test/debug-info/box.rs | 4 ++-- src/test/debug-info/boxed-struct.rs | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 3c163e149d2db..8cabd5955323b 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -568,7 +568,6 @@ fn create_enum_md(cx: &mut CrateContext, assert!(Type::enum_discrim(cx) == cx.int_type); let discriminant_type_md = get_or_create_type(cx, ty::mk_int(), span); - let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); let enumerators : ~[(~str, int)] = variants @@ -971,8 +970,7 @@ fn get_or_create_type(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { ty::ty_enum(def_id, ref substs) => { create_enum_md(cx, t, def_id, substs, span) }, - ty::ty_box(ref mt) | - ty::ty_uniq(ref mt) => { + ty::ty_box(ref mt) => { let content_llvm_type = type_of::type_of(cx, mt.ty); let content_type_metadata = get_or_create_type(cx, mt.ty, span); @@ -998,7 +996,8 @@ fn get_or_create_type(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { } } }, - ty::ty_ptr(ref mt) | + ty::ty_uniq(ref mt) | + ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { let pointee = get_or_create_type(cx, mt.ty, span); create_pointer_type(cx, t, span, pointee) diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs index 543d8f1cdb7a4..4e10bf83bcb70 100644 --- a/src/test/debug-info/box.rs +++ b/src/test/debug-info/box.rs @@ -13,9 +13,9 @@ // debugger:break _zzz // debugger:run // debugger:finish -// debugger:print a->val +// debugger:print *a // check:$1 = 1 -// debugger:print b->val +// debugger:print *b // check:$2 = {2, 3.5} // debugger:print c->val // check:$3 = 4 diff --git a/src/test/debug-info/boxed-struct.rs b/src/test/debug-info/boxed-struct.rs index 16ffda35956d6..d06fcbbbab34b 100644 --- a/src/test/debug-info/boxed-struct.rs +++ b/src/test/debug-info/boxed-struct.rs @@ -13,13 +13,13 @@ // debugger:run // debugger:finish -// debugger:print unique->val +// debugger:print *unique // check:$1 = {x = 99, y = 999, z = 9999, w = 99999} // debugger:print managed->val // check:$2 = {x = 88, y = 888, z = 8888, w = 88888} -// debugger:print unique_dtor->val +// debugger:print *unique_dtor // check:$3 = {x = 77, y = 777, z = 7777, w = 77777} // debugger:print managed_dtor->val From 12d87d39c1baebcce28ebff095bc811cd3d7402f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 10 Jul 2013 17:28:28 +0200 Subject: [PATCH 13/26] Cleanup of ty::VariantInfo and related functions. --- src/librustc/metadata/csearch.rs | 2 +- src/librustc/metadata/decoder.rs | 6 +- src/librustc/middle/trans/base.rs | 4 +- src/librustc/middle/ty.rs | 144 +++++++++++++----------- src/librustc/middle/typeck/check/mod.rs | 119 ++++++++------------ 5 files changed, 131 insertions(+), 144 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index f336b0f4e4c5e..2934751eeafd7 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -90,7 +90,7 @@ pub fn maybe_get_item_ast(tcx: ty::ctxt, def: ast::def_id, } pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id) - -> ~[ty::VariantInfo] { + -> ~[@ty::VariantInfo] { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, def.crate); return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index e748ae89a9dc7..cf75bf45eaf0c 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -733,11 +733,11 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt, } pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, - tcx: ty::ctxt) -> ~[ty::VariantInfo] { + tcx: ty::ctxt) -> ~[@ty::VariantInfo] { let data = cdata.data; let items = reader::get_doc(reader::Doc(data), tag_items); let item = find_item(id, items); - let mut infos: ~[ty::VariantInfo] = ~[]; + let mut infos: ~[@ty::VariantInfo] = ~[]; let variant_ids = enum_variant_ids(item, cdata); let mut disr_val = 0; for variant_ids.iter().advance |did| { @@ -753,7 +753,7 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, Some(val) => { disr_val = val; } _ => { /* empty */ } } - infos.push(@ty::VariantInfo_{ + infos.push(@ty::VariantInfo{ args: arg_tys, arg_names: None, ctor_ty: ctor_ty, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 588b0b5c75f48..a68a8437e1bb7 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -671,7 +671,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, let _icx = push_ctxt("iter_structural_ty"); fn iter_variant(cx: block, repr: &adt::Repr, av: ValueRef, - variant: ty::VariantInfo, + variant: @ty::VariantInfo, tps: &[ty::t], f: val_and_ty_fn) -> block { let _icx = push_ctxt("iter_variant"); let tcx = cx.tcx(); @@ -2110,7 +2110,7 @@ pub fn trans_enum_variant_or_tuple_like_struct( } pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def, - id: ast::node_id, vi: @~[ty::VariantInfo], + id: ast::node_id, vi: @~[@ty::VariantInfo], i: &mut uint) { for enum_definition.variants.iter().advance |variant| { let disr_val = vi[*i].disr_val; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9438d60a48004..59d33fc086dd0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -50,6 +50,8 @@ use syntax::opt_vec; use syntax::abi::AbiSet; use syntax; +pub static INITIAL_DISCRIMINANT_VALUE: int = 0; + // Data types #[deriving(Eq, IterBytes)] @@ -282,7 +284,7 @@ struct ctxt_ { needs_unwind_cleanup_cache: @mut HashMap, tc_cache: @mut HashMap, ast_ty_to_ty_cache: @mut HashMap, - enum_var_cache: @mut HashMap, + enum_var_cache: @mut HashMap, ty_param_defs: @mut HashMap, adjustments: @mut HashMap, normalized_cache: @mut HashMap, @@ -3702,19 +3704,70 @@ pub struct VariantInfo_ { vis: visibility } -pub type VariantInfo = @VariantInfo_; +impl VariantInfo { + + /// Creates a new VariantInfo from the corresponding ast representation. + /// + /// Does not do any caching of the value in the type context. + pub fn from_ast_variant(cx: ctxt, + ast_variant: &ast::variant, + discriminant: int) -> VariantInfo { + + let ctor_ty = node_id_to_type(cx, ast_variant.node.id); + + match ast_variant.node.kind { + ast::tuple_variant_kind(ref args) => { + let arg_tys = if args.len() > 0 { ty_fn_args(ctor_ty).map(|a| *a) } else { ~[] }; + + return VariantInfo { + args: arg_tys, + arg_names: None, + ctor_ty: ctor_ty, + name: ast_variant.node.name, + id: ast_util::local_def(ast_variant.node.id), + disr_val: discriminant, + vis: ast_variant.node.vis + }; + }, + ast::struct_variant_kind(ref struct_def) => { + + let fields : &[@struct_field] = struct_def.fields; + + assert!(fields.len() > 0); + + let arg_tys = ty_fn_args(ctor_ty).map(|a| *a); + let arg_names = do fields.map |field| { + match field.node.kind { + named_field(ident, _visibility) => ident, + unnamed_field => cx.sess.bug( + "enum_variants: all fields in struct must have a name") + }}; + + return VariantInfo { + args: arg_tys, + arg_names: Some(arg_names), + ctor_ty: ctor_ty, + name: ast_variant.node.name, + id: ast_util::local_def(ast_variant.node.id), + disr_val: discriminant, + vis: ast_variant.node.vis + }; + } + } + } +} pub fn substd_enum_variants(cx: ctxt, id: ast::def_id, substs: &substs) - -> ~[VariantInfo] { + -> ~[@VariantInfo] { do enum_variants(cx, id).iter().transform |variant_info| { let substd_args = variant_info.args.iter() .transform(|aty| subst(cx, substs, *aty)).collect(); let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty); - @VariantInfo_ { + @VariantInfo { args: substd_args, ctor_ty: substd_ctor_ty, ..(**variant_info).clone() @@ -3832,7 +3885,7 @@ pub fn type_is_empty(cx: ctxt, t: t) -> bool { } } -pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { +pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] { match cx.enum_var_cache.find(&id) { Some(&variants) => return variants, _ => { /* fallthrough */ } @@ -3851,71 +3904,26 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { node: ast::item_enum(ref enum_definition, _), _ }, _) => { - let mut disr_val = -1; + let mut last_discriminant : Option = None; @enum_definition.variants.iter().transform(|variant| { - let ctor_ty = node_id_to_type(cx, variant.node.id); - - match variant.node.kind { - ast::tuple_variant_kind(ref args) => { - let arg_tys = if args.len() > 0u { - ty_fn_args(ctor_ty).map(|a| *a) } - else { - ~[] - }; - - match variant.node.disr_expr { - Some (ex) => { - disr_val = match const_eval::eval_const_expr(cx, - ex) { - const_eval::const_int(val) => val as int, - _ => cx.sess.bug("enum_variants: bad disr expr") - } - } - _ => disr_val += 1 - } - @VariantInfo_{ - args: arg_tys, - arg_names: None, - ctor_ty: ctor_ty, - name: variant.node.name, - id: ast_util::local_def(variant.node.id), - disr_val: disr_val, - vis: variant.node.vis - } + let mut discriminant = match last_discriminant { + Some(val) => val + 1, + None => INITIAL_DISCRIMINANT_VALUE + }; + + match variant.node.disr_expr { + Some(e) => match const_eval::eval_const_expr_partial(cx, e) { + Ok(const_eval::const_int(val)) => { discriminant = val as int; } + _ => {} }, - ast::struct_variant_kind(struct_def) => { - - let fields : &[@struct_field] = struct_def.fields; - - let (arg_tys, arg_names) = - if fields.len() > 0 { - let arg_tys = ty_fn_args(ctor_ty).map(|a| *a); - let arg_names = do fields.map |field| { match field.node.kind { - named_field(ident, _visibility) => ident, - unnamed_field => cx.sess.bug( - "enum_variants: all fields in struct must have a name") - }}; - - (arg_tys, Some(arg_names)) - } else { - (~[], None) - }; - - assert!(variant.node.disr_expr.is_none()); - disr_val += 1; - - @VariantInfo_{ - args: arg_tys, - arg_names: arg_names, - ctor_ty: ctor_ty, - name: variant.node.name, - id: ast_util::local_def(variant.node.id), - disr_val: disr_val, - vis: variant.node.vis - } - } - } + None => {} + }; + + let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant); + last_discriminant = Some(discriminant); + variant_info + }).collect() } _ => cx.sess.bug("enum_variants: id not bound to an enum") @@ -3930,7 +3938,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { pub fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id, variant_id: ast::def_id) - -> VariantInfo { + -> @VariantInfo { let variants = enum_variants(cx, enum_id); let mut i = 0; while i < variants.len() { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 0e1f8e617ff7e..319d94bae7038 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -81,7 +81,7 @@ use middle::const_eval; use middle::pat_util::pat_id_map; use middle::pat_util; use middle::lint::unreachable_code; -use middle::ty::{FnSig, VariantInfo_}; +use middle::ty::{FnSig, VariantInfo}; use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty}; use middle::ty::{substs, param_ty, ExprTyProvider}; use middle::ty; @@ -3133,87 +3133,66 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, vs: &[ast::variant], id: ast::node_id) { fn do_check(ccx: @mut CrateCtxt, - _sp: span, vs: &[ast::variant], - id: ast::node_id, - disr_vals: &mut ~[int], - disr_val: &mut int, - variants: &mut ~[ty::VariantInfo]) { + id: ast::node_id) + -> ~[@ty::VariantInfo] { + let rty = ty::node_id_to_type(ccx.tcx, id); - for vs.iter().advance |v| { - for v.node.disr_expr.iter().advance |e_ref| { - let e = *e_ref; - debug!("disr expr, checking %s", - pprust::expr_to_str(e, ccx.tcx.sess.intr())); - let declty = ty::mk_int(); - let fcx = blank_fn_ctxt(ccx, rty, e.id); - check_const_with_ty(fcx, e.span, e, declty); - // check_expr (from check_const pass) doesn't guarantee - // that the expression is in an form that eval_const_expr can - // handle, so we may still get an internal compiler error - - match const_eval::eval_const_expr_partial(&ccx.tcx, e) { - Ok(const_eval::const_int(val)) => { - *disr_val = val as int; - } - Ok(_) => { - ccx.tcx.sess.span_err(e.span, "expected signed integer \ - constant"); - } - Err(ref err) => { - ccx.tcx.sess.span_err(e.span, - fmt!("expected constant: %s", (*err))); + let mut variants : ~[@ty::VariantInfo] = ~[]; + let mut disr_vals: ~[int] = ~[]; + let mut prev_disr_val : Option = None; - } - } - } - if disr_vals.contains(&*disr_val) { - ccx.tcx.sess.span_err(v.span, - "discriminator value already exists"); - } - disr_vals.push(*disr_val); - let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id); + for vs.iter().advance |v| { - let this_disr_val = *disr_val; - *disr_val += 1; + // If the discriminant value is specified explicitly in the enum check whether the + // initialization expression is valid, otherwise use the last value plus one. + let mut current_disr_val = match prev_disr_val { + Some(prev_disr_val) => prev_disr_val + 1, + None => ty::INITIAL_DISCRIMINANT_VALUE + }; - let (arg_tys, arg_names) = match v.node.kind { - ast::tuple_variant_kind(ref args) if args.len() > 0u => { - (ty::ty_fn_args(ctor_ty).map(|a| *a), None) - } - ast::tuple_variant_kind(_) => { - (~[], None) - } - ast::struct_variant_kind(struct_def) => { - let tys = ty::ty_fn_args(ctor_ty).map(|a| *a); - let names = do struct_def.fields.map |field| { match field.node.kind { - ast::named_field(ident, _visibility) => ident, - ast::unnamed_field => ccx.tcx.sess.bug( - "enum_variants: all fields in struct must have a name") - }}; - - (tys, Some(names)) - } + match v.node.disr_expr { + Some(e) => { + debug!("disr expr, checking %s", pprust::expr_to_str(e, ccx.tcx.sess.intr())); + + let declty = ty::mk_int(); + let fcx = blank_fn_ctxt(ccx, rty, e.id); + check_const_with_ty(fcx, e.span, e, declty); + // check_expr (from check_const pass) doesn't guarantee + // that the expression is in an form that eval_const_expr can + // handle, so we may still get an internal compiler error + + match const_eval::eval_const_expr_partial(&ccx.tcx, e) { + Ok(const_eval::const_int(val)) => { current_disr_val = val as int; } + Ok(_) => { + ccx.tcx.sess.span_err(e.span, "expected signed integer constant"); + } + Err(ref err) => { + ccx.tcx.sess.span_err(e.span, fmt!("expected constant: %s", (*err))); + } + } + }, + None => () }; - variants.push(@VariantInfo_{ - args: arg_tys, - arg_names: arg_names, - ctor_ty: ctor_ty, - name: v.node.name, - id: local_def(v.node.id), - disr_val: this_disr_val, - vis: v.node.vis - }); + // Check for duplicate discriminator values + if disr_vals.contains(¤t_disr_val) { + ccx.tcx.sess.span_err(v.span, "discriminator value already exists"); + } + disr_vals.push(current_disr_val); + + let variant_info = @VariantInfo::from_ast_variant(ccx.tcx, v, current_disr_val); + prev_disr_val = Some(current_disr_val); + + variants.push(variant_info); } + + return variants; } let rty = ty::node_id_to_type(ccx.tcx, id); - let mut disr_vals: ~[int] = ~[]; - let mut disr_val = 0; - let mut variants = ~[]; - do_check(ccx, sp, vs, id, &mut disr_vals, &mut disr_val, &mut variants); + let variants = do_check(ccx, vs, id); // cache so that ty::enum_variants won't repeat this work ccx.tcx.enum_var_cache.insert(local_def(id), @variants); From a33d1b8f1dd9898858bb65bd32c633e3cd63be9d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 10 Jul 2013 18:35:38 +0200 Subject: [PATCH 14/26] debuginfo: Major code cleanup in debuginfo.rs --- src/librustc/middle/trans/base.rs | 6 +- src/librustc/middle/trans/debuginfo.rs | 517 +++++++++++++------------ 2 files changed, 266 insertions(+), 257 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a68a8437e1bb7..f6b5cffae7cd4 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1142,7 +1142,7 @@ pub fn trans_stmt(cx: block, s: &ast::stmt) -> block { bcx = init_local(bcx, *local); if cx.sess().opts.extra_debuginfo && fcx_has_nonzero_span(bcx.fcx) { - debuginfo::create_local_var(bcx, *local); + debuginfo::create_local_var_metadata(bcx, *local); } } ast::decl_item(i) => trans_item(cx.fcx.ccx, i) @@ -1774,7 +1774,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, bcx = _match::store_arg(bcx, args[arg_n].pat, llarg); if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) { - debuginfo::create_arg(bcx, &args[arg_n], args[arg_n].ty.span); + debuginfo::create_argument_metadata(bcx, &args[arg_n], args[arg_n].ty.span); } } @@ -1948,7 +1948,7 @@ pub fn trans_fn(ccx: @mut CrateContext, |fcx| { if ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) { - debuginfo::create_function(fcx); + debuginfo::create_function_metadata(fcx); } }, |_bcx| { }); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 8cabd5955323b..48ab05661781f 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -27,7 +27,7 @@ where possible. This will hopefully ease the adaption of this module to future L The public API of the module is a set of functions that will insert the correct metadata into the LLVM IR when called with the right parameters. The module is thus driven from an outside client with -functions like `debuginfo::create_local_var(bcx: block, local: @ast::local)`. +functions like `debuginfo::create_local_var_metadata(bcx: block, local: @ast::local)`. Internally the module will try to reuse already created metadata by utilizing a cache. All private state used by the module is stored within a DebugContext struct, which in turn is contained in the @@ -44,7 +44,7 @@ This file consists of three conceptual sections: use driver::session; use lib::llvm::llvm; -use lib::llvm::{ValueRef, ModuleRef, ContextRef}; +use lib::llvm::{ModuleRef, ContextRef}; use lib::llvm::debuginfo::*; use middle::trans::common::*; use middle::trans::machine; @@ -58,7 +58,6 @@ use std::hashmap::HashMap; use std::libc::{c_uint, c_ulonglong, c_longlong}; use std::ptr; use std::str::as_c_str; -use std::sys; use std::vec; use syntax::codemap::span; use syntax::{ast, codemap, ast_util, ast_map}; @@ -116,7 +115,7 @@ impl DebugContext { /// Create any deferred debug metadata nodes pub fn finalize(cx: @mut CrateContext) { debug!("finalize"); - create_compile_unit(cx); + create_compile_unit_metadata(cx); unsafe { llvm::LLVMDIBuilderFinalize(DIB(cx)); llvm::LLVMDIBuilderDispose(DIB(cx)); @@ -127,7 +126,7 @@ pub fn finalize(cx: @mut CrateContext) { /// /// Adds the created metadata nodes directly to the crate's IR. /// The return value should be ignored if called from outside of the debuginfo module. -pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { +pub fn create_local_var_metadata(bcx: block, local: @ast::local) -> DIVariable { let cx = bcx.ccx(); let ident = match local.node.pat.node { @@ -138,23 +137,32 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { return ptr::null(); } }; + let name: &str = cx.sess.str_of(ident); - debug!("create_local_var: %s", name); + debug!("create_local_var_metadata: %s", name); let loc = span_start(cx, local.span); let ty = node_id_type(bcx, local.node.id); - let tymd = get_or_create_type(cx, ty, local.node.ty.span); - let filemd = get_or_create_file(cx, loc.file.name); + let type_metadata = get_or_create_type_metadata(cx, ty, local.node.ty.span); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let context = match bcx.parent { - None => create_function(bcx.fcx), - Some(_) => get_or_create_block(bcx) + None => create_function_metadata(bcx.fcx), + Some(_) => get_or_create_block_metadata(bcx) }; - let var_md = do as_c_str(name) |name| { unsafe { + let var_metadata = do as_c_str(name) |name| { unsafe { llvm::LLVMDIBuilderCreateLocalVariable( - DIB(cx), AutoVariableTag as u32, - context, name, filemd, - loc.line as c_uint, tymd, false, 0, 0) + DIB(cx), + AutoVariableTag as u32, + context, + name, + file_metadata, + loc.line as c_uint, + type_metadata, + false, + 0, + 0) }}; // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc @@ -167,24 +175,25 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable { } }; - set_debug_location(cx, get_or_create_block(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, get_or_create_block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { - let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_md, bcx.llbb); + let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb); llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); } - return var_md; + return var_metadata; } /// Creates debug information for the given function argument. /// /// Adds the created metadata nodes directly to the crate's IR. /// The return value should be ignored if called from outside of the debuginfo module. -pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option { - debug!("create_arg"); +pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Option { + debug!("create_argument_metadata"); if true { - // XXX create_arg disabled for now because "node_id_type(bcx, arg.id)" below blows - // up: "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`" + // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below + // blows up: + // "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`" return None; } @@ -197,24 +206,24 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option } let ty = node_id_type(bcx, arg.id); - let tymd = get_or_create_type(cx, ty, arg.ty.span); - let filemd = get_or_create_file(cx, loc.file.name); - let context = create_function(fcx); + let type_metadata = get_or_create_type_metadata(cx, ty, arg.ty.span); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let context = create_function_metadata(fcx); match arg.pat.node { ast::pat_ident(_, ref path, _) => { // XXX: This is wrong; it should work for multiple bindings. let ident = path.idents.last(); let name: &str = cx.sess.str_of(*ident); - let mdnode = do as_c_str(name) |name| { unsafe { + let var_metadata = do as_c_str(name) |name| { unsafe { llvm::LLVMDIBuilderCreateLocalVariable( DIB(cx), ArgVariableTag as u32, context, name, - filemd, + file_metadata, loc.line as c_uint, - tymd, + type_metadata, false, 0, 0) @@ -222,13 +231,13 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option }}; let llptr = fcx.llargs.get_copy(&arg.id); - set_debug_location(cx, get_or_create_block(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, get_or_create_block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( - DIB(cx), llptr, mdnode, bcx.llbb); + DIB(cx), llptr, var_metadata, bcx.llbb); llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); } - return Some(mdnode); + return Some(var_metadata); } _ => { return None; @@ -245,14 +254,14 @@ pub fn update_source_pos(bcx: block, span: span) { } debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span)); let loc = span_start(bcx.ccx(), span); - set_debug_location(bcx.ccx(), get_or_create_block(bcx), loc.line, loc.col.to_uint()) + set_debug_location(bcx.ccx(), get_or_create_block_metadata(bcx), loc.line, loc.col.to_uint()) } /// Creates debug information for the given function. /// /// Adds the created metadata nodes directly to the crate's IR. /// The return value should be ignored if called from outside of the debuginfo module. -pub fn create_function(fcx: fn_ctxt) -> DISubprogram { +pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram { let cx = fcx.ccx; let fcx = &mut *fcx; let span = fcx.span.get(); @@ -264,7 +273,8 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => { (item.ident, ty, item.id) } - _ => fcx.ccx.sess.span_bug(item.span, "create_function: item bound to non-function") + _ => fcx.ccx.sess.span_bug(item.span, + "create_function_metadata: item bound to non-function") } } ast_map::node_method(@ast::method { decl: ast::fn_decl { output: ref ty, _ }, @@ -278,26 +288,28 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { (name, &decl.output, expr.id) } _ => fcx.ccx.sess.span_bug(expr.span, - "create_function: expected an expr_fn_block here") + "create_function_metadata: expected an expr_fn_block here") } } - _ => fcx.ccx.sess.bug("create_function: unexpected sort of node") + _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node") }; match dbg_cx(cx).created_functions.find(&id) { - Some(fn_md) => return *fn_md, + Some(fn_metadata) => return *fn_metadata, None => () } - debug!("create_function: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span)); + debug!("create_function_metadata: %s, %s", + cx.sess.str_of(ident), + cx.sess.codemap.span_to_str(span)); let loc = span_start(cx, span); - let file_md = get_or_create_file(cx, loc.file.name); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); - let ret_ty_md = if cx.sess.opts.extra_debuginfo { + let return_type_metadata = if cx.sess.opts.extra_debuginfo { match ret_ty.node { ast::ty_nil => ptr::null(), - _ => get_or_create_type(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) + _ => get_or_create_type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) } } else { ptr::null() @@ -306,19 +318,19 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { let fn_ty = unsafe { llvm::LLVMDIBuilderCreateSubroutineType( DIB(cx), - file_md, - create_DIArray(DIB(cx), [ret_ty_md])) + file_metadata, + create_DIArray(DIB(cx), [return_type_metadata])) }; - let fn_md = + let fn_metadata = do as_c_str(cx.sess.str_of(ident)) |name| { do as_c_str(cx.sess.str_of(ident)) |linkage| { unsafe { llvm::LLVMDIBuilderCreateFunction( DIB(cx), - file_md, + file_metadata, name, linkage, - file_md, + file_metadata, loc.line as c_uint, fn_ty, false, @@ -331,8 +343,8 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram { ptr::null()) }}}; - dbg_cx(cx).created_functions.insert(id, fn_md); - return fn_md; + dbg_cx(cx).created_functions.insert(id, fn_metadata); + return fn_metadata; } @@ -348,11 +360,11 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { }; } -fn create_compile_unit(cx: @mut CrateContext) { +fn create_compile_unit_metadata(cx: @mut CrateContext) { let dcx = dbg_cx(cx); let crate_name: &str = dcx.crate_file; - debug!("create_compile_unit: %?", crate_name); + debug!("create_compile_unit_metadata: %?", crate_name); let work_dir = cx.sess.working_dir.to_str(); let producer = fmt!("rustc version %s", env!("CFG_VERSION")); @@ -369,13 +381,13 @@ fn create_compile_unit(cx: @mut CrateContext) { }}}}}}; } -fn get_or_create_file(cx: &mut CrateContext, full_path: &str) -> DIFile { +fn get_or_create_file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile { match dbg_cx(cx).created_files.find_equiv(&full_path) { - Some(file_md) => return *file_md, + Some(file_metadata) => return *file_metadata, None => () } - debug!("get_or_create_file: %s", full_path); + debug!("get_or_create_file_metadata: %s", full_path); let work_dir = cx.sess.working_dir.to_str(); let file_name = @@ -385,19 +397,17 @@ fn get_or_create_file(cx: &mut CrateContext, full_path: &str) -> DIFile { full_path }; - let file_md = + let file_metadata = do as_c_str(file_name) |file_name| { do as_c_str(work_dir) |work_dir| { unsafe { llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir) }}}; - dbg_cx(cx).created_files.insert(full_path.to_owned(), file_md); - return file_md; + dbg_cx(cx).created_files.insert(full_path.to_owned(), file_metadata); + return file_metadata; } - - -fn get_or_create_block(bcx: block) -> DILexicalBlock { +fn get_or_create_block_metadata(bcx: block) -> DILexicalBlock { let mut bcx = bcx; let cx = bcx.ccx(); @@ -415,33 +425,31 @@ fn get_or_create_block(bcx: block) -> DILexicalBlock { None => () } - debug!("get_or_create_block: %s", bcx.sess().codemap.span_to_str(span)); + debug!("get_or_create_block_metadata: %s", bcx.sess().codemap.span_to_str(span)); let parent = match bcx.parent { - None => create_function(bcx.fcx), - Some(b) => get_or_create_block(b) + None => create_function_metadata(bcx.fcx), + Some(b) => get_or_create_block_metadata(b) }; let cx = bcx.ccx(); let loc = span_start(cx, span); - let file_md = get_or_create_file(cx, loc.file.name); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); - let block_md = unsafe { + let block_metadata = unsafe { llvm::LLVMDIBuilderCreateLexicalBlock( DIB(cx), - parent, file_md, + parent, file_metadata, loc.line as c_uint, loc.col.to_uint() as c_uint) }; - dbg_cx(cx).created_blocks.insert(id, block_md); + dbg_cx(cx).created_blocks.insert(id, block_metadata); - return block_md; + return block_metadata; } +fn create_basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { - -fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType { - - debug!("create_basic_type: %?", ty::get(t)); + debug!("create_basic_type_metadata: %?", ty::get(t)); let (name, encoding) = match ty::get(t).sty { ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned), @@ -466,11 +474,12 @@ fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType { ast::ty_f32 => (~"f32", DW_ATE_float), ast::ty_f64 => (~"f64", DW_ATE_float) }, - _ => cx.sess.bug("debuginfo::create_basic_type - t is invalid type") + _ => cx.sess.bug("debuginfo::create_basic_type_metadata - t is invalid type") }; - let (size, align) = size_and_align_of(cx, t); - let ty_md = do as_c_str(name) |name| { unsafe { + let llvm_type = type_of::type_of(cx, t); + let (size, align) = size_and_align_of(cx, llvm_type); + let ty_metadata = do as_c_str(name) |name| { unsafe { llvm::LLVMDIBuilderCreateBasicType( DIB(cx), name, @@ -479,38 +488,44 @@ fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType { encoding as c_uint) }}; - return ty_md; + return ty_metadata; } -fn create_pointer_type(cx: &mut CrateContext, t: ty::t, _span: span, pointee: DIType) -> DIType { - let (size, align) = size_and_align_of(cx, t); - let name = ty_to_str(cx.tcx, t); - let ptr_md = do as_c_str(name) |name| { unsafe { +fn create_pointer_type_metadata(cx: &mut CrateContext, + pointer_type: ty::t, + pointee_type_metadata: DIType) + -> DIType { + let pointer_llvm_type = type_of::type_of(cx, pointer_type); + let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type); + let name = ty_to_str(cx.tcx, pointer_type); + let ptr_metadata = do as_c_str(name) |name| { unsafe { llvm::LLVMDIBuilderCreatePointerType( DIB(cx), - pointee, - bytes_to_bits(size), - bytes_to_bits(align), + pointee_type_metadata, + bytes_to_bits(pointer_size), + bytes_to_bits(pointer_align), name) - }}; - return ptr_md; + }}; + return ptr_metadata; } -fn create_struct(cx: &mut CrateContext, - struct_type: ty::t, - fields: ~[ty::field], - span: span) - -> DICompositeType { +fn create_struct_metadata(cx: &mut CrateContext, + struct_type: ty::t, + fields: ~[ty::field], + span: span) + -> DICompositeType { let struct_name = ty_to_str(cx.tcx, struct_type); - debug!("create_struct: %s", struct_name); + debug!("create_struct_metadata: %s", struct_name); let struct_llvm_type = type_of::type_of(cx, struct_type); - let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty)); - let field_names = fields.map(|field| cx.sess.str_of(field.ident).to_owned()); - let field_types_metadata = fields.map(|field| get_or_create_type(cx, field.mt.ty, span)); + let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) }; + let field_names = do fields.map |field| { cx.sess.str_of(field.ident).to_owned() }; + let field_types_metadata = do fields.map |field| { + get_or_create_type_metadata(cx, field.mt.ty, span) + }; - return create_composite_type( + return create_composite_type_metadata( cx, struct_llvm_type, struct_name, @@ -520,22 +535,22 @@ fn create_struct(cx: &mut CrateContext, span); } -fn create_tuple(cx: &mut CrateContext, - tuple_type: ty::t, - component_types: &[ty::t], - span: span) - -> DICompositeType { +fn create_tuple_metadata(cx: &mut CrateContext, + tuple_type: ty::t, + component_types: &[ty::t], + span: span) + -> DICompositeType { let tuple_name = ty_to_str(cx.tcx, tuple_type); let tuple_llvm_type = type_of::type_of(cx, tuple_type); - // Create a vec of empty strings. A vec::build_n() function would be nice for this. - let mut component_names : ~[~str] = vec::with_capacity(component_types.len()); - component_names.grow_fn(component_types.len(), |_| ~""); - let component_llvm_types = component_types.map(|it| type_of::type_of(cx, *it)); - let component_types_metadata = component_types.map(|it| get_or_create_type(cx, *it, span)); + let component_names = do component_types.map |_| { ~"" }; + let component_llvm_types = do component_types.map |it| { type_of::type_of(cx, *it) }; + let component_types_metadata = do component_types.map |it| { + get_or_create_type_metadata(cx, *it, span) + }; - return create_composite_type( + return create_composite_type_metadata( cx, tuple_llvm_type, tuple_name, @@ -545,50 +560,50 @@ fn create_tuple(cx: &mut CrateContext, span); } -fn create_enum_md(cx: &mut CrateContext, - enum_type: ty::t, - enum_def_id: ast::def_id, - substs: &ty::substs, - span: span) - -> DIType { +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 name + // appropriate type name if ty::type_is_empty(cx.tcx, enum_type) { - return create_composite_type(cx, Type::nil(), enum_name, &[], &[], &[], span); + 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 = machine::llsize_of_alloc(cx, discriminant_llvm_type); - let discriminant_align = machine::llalign_of_min(cx, discriminant_llvm_type); + let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type); + assert!(Type::enum_discrim(cx) == cx.int_type); - let discriminant_type_md = get_or_create_type(cx, ty::mk_int(), span); + 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 variants : &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); - let enumerators : ~[(~str, int)] = variants + let enumerators_metadata : ~[DIDescriptor] = variants .iter() - .transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val)) - .collect(); + .transform(|v| { + let name : &str = cx.sess.str_of(v.name); + let discriminant_value = v.disr_val as c_ulonglong; - let enumerators_md : ~[DIDescriptor] = - do enumerators.iter().transform |&(name,value)| { do name.as_c_str |name| { unsafe { llvm::LLVMDIBuilderCreateEnumerator( DIB(cx), name, - value as c_ulonglong) + discriminant_value) }} - }.collect(); + }) + .collect(); let loc = span_start(cx, span); - let file_metadata = get_or_create_file(cx, loc.file.name); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); - let discriminant_type_md = do enum_name.as_c_str |enum_name| { unsafe { + let discriminant_type_metadata = do enum_name.as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateEnumerationType( DIB(cx), file_metadata, @@ -597,17 +612,17 @@ fn create_enum_md(cx: &mut CrateContext, loc.line as c_uint, bytes_to_bits(discriminant_size), bytes_to_bits(discriminant_align), - create_DIArray(DIB(cx), enumerators_md), - discriminant_type_md) + create_DIArray(DIB(cx), enumerators_metadata), + discriminant_type_metadata) }}; if ty::type_is_c_like_enum(cx.tcx, enum_type) { - return discriminant_type_md; + return discriminant_type_metadata; } let is_univariant = variants.len() == 1; - let variants_md = do variants.map |&vi| { + let variants_metadata = do variants.map |&vi| { let raw_types : &[ty::t] = vi.args; let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) }; @@ -618,25 +633,24 @@ fn create_enum_md(cx: &mut CrateContext, None => do arg_types.map |_| { ~"" } }; - let mut arg_md = do arg_types.map |&ty| { get_or_create_type(cx, ty, span) }; + let mut arg_metadata = do arg_types.map |&ty| { get_or_create_type_metadata(cx, ty, span) }; if !is_univariant { arg_llvm_types.insert(0, discriminant_llvm_type); arg_names.insert(0, ~""); - arg_md.insert(0, discriminant_type_md); + arg_metadata.insert(0, discriminant_type_metadata); } let variant_llvm_type = Type::struct_(arg_llvm_types, false); - let variant_type_size = machine::llsize_of_alloc(cx, variant_llvm_type); - let variant_type_align = machine::llalign_of_min(cx, variant_llvm_type); + let (variant_type_size, variant_type_align) = size_and_align_of(cx, variant_llvm_type); - let variant_type_md = create_composite_type( + let variant_type_metadata = create_composite_type_metadata( cx, variant_llvm_type, &"", arg_llvm_types, arg_names, - arg_md, + arg_metadata, span); do "".as_c_str |name| { unsafe { @@ -650,13 +664,12 @@ fn create_enum_md(cx: &mut CrateContext, bytes_to_bits(variant_type_align), bytes_to_bits(0), 0, - variant_type_md) + variant_type_metadata) }} }; let enum_llvm_type = type_of::type_of(cx, enum_type); - let enum_type_size = machine::llsize_of_alloc(cx, enum_llvm_type); - let enum_type_align = machine::llalign_of_min(cx, enum_llvm_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), @@ -667,7 +680,7 @@ fn create_enum_md(cx: &mut CrateContext, bytes_to_bits(enum_type_size), bytes_to_bits(enum_type_align), 0, // Flags - create_DIArray(DIB(cx), variants_md), + create_DIArray(DIB(cx), variants_metadata), 0) // RuntimeLang }}; } @@ -676,27 +689,25 @@ fn create_enum_md(cx: &mut CrateContext, /// Creates debug information for a composite type, that is, anything that results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn create_composite_type(cx: &mut CrateContext, - composite_llvm_type: Type, - composite_type_name: &str, - member_llvm_types: &[Type], - member_names: &[~str], - member_type_metadata: &[DIType], - span: span) - -> DICompositeType { +fn create_composite_type_metadata(cx: &mut CrateContext, + composite_llvm_type: Type, + composite_type_name: &str, + member_llvm_types: &[Type], + member_names: &[~str], + member_type_metadata: &[DIType], + span: span) + -> DICompositeType { let loc = span_start(cx, span); - let file_metadata = get_or_create_file(cx, loc.file.name); + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); - let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type); - let composite_align = machine::llalign_of_min(cx, composite_llvm_type); + let (composite_size, composite_align) = size_and_align_of(cx, composite_llvm_type); let member_metadata : ~[DIDescriptor] = member_llvm_types .iter() .enumerate() - .transform(|(i, member_llvm_type)| { - let member_size = machine::llsize_of_alloc(cx, *member_llvm_type); - let member_align = machine::llalign_of_min(cx, *member_llvm_type); + .transform(|(i, &member_llvm_type)| { + let (member_size, member_align) = size_and_align_of(cx, member_llvm_type); let member_offset = machine::llelement_offset(cx, composite_llvm_type, i); let member_name : &str = member_names[i]; @@ -733,26 +744,11 @@ fn create_composite_type(cx: &mut CrateContext, }}; } -// returns (void* type as a ValueRef, size in bytes, align in bytes) -fn voidptr(cx: &mut CrateContext) -> (DIDerivedType, uint, uint) { - let size = sys::size_of::(); - let align = sys::min_align_of::(); - let vp = do as_c_str("*void") |name| { unsafe { - llvm::LLVMDIBuilderCreatePointerType( - DIB(cx), - ptr::null(), - bytes_to_bits(size), - bytes_to_bits(align), - name) - }}; - return (vp, size, align); -} - -fn create_boxed_type(cx: &mut CrateContext, - content_llvm_type: Type, - content_type_metadata: DIType, - span: span) - -> DICompositeType { +fn create_boxed_type_metadata(cx: &mut CrateContext, + content_llvm_type: Type, + content_type_metadata: DIType, + span: span) + -> DICompositeType { let box_llvm_type = Type::box(cx, &content_llvm_type); let member_llvm_types = box_llvm_type.field_types(); @@ -764,14 +760,14 @@ fn create_boxed_type(cx: &mut CrateContext, let nil_pointer_type = ty::mk_nil_ptr(cx.tcx); let member_types_metadata = [ - get_or_create_type(cx, int_type, span), - get_or_create_type(cx, nil_pointer_type, span), - get_or_create_type(cx, nil_pointer_type, span), - get_or_create_type(cx, nil_pointer_type, span), + get_or_create_type_metadata(cx, int_type, span), + get_or_create_type_metadata(cx, nil_pointer_type, span), + get_or_create_type_metadata(cx, nil_pointer_type, span), + get_or_create_type_metadata(cx, nil_pointer_type, span), content_type_metadata ]; - return create_composite_type( + return create_composite_type_metadata( cx, box_llvm_type, "box name", @@ -795,12 +791,14 @@ fn create_boxed_type(cx: &mut CrateContext, } } -fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t, - len: uint, span: span) -> DIType { - debug!("create_fixed_vec: %?", ty::get(_vec_t)); - - let elem_ty_md = get_or_create_type(cx, elem_t, span); - let (size, align) = size_and_align_of(cx, elem_t); +fn create_fixed_vec_metadata(cx: &mut CrateContext, + element_type: ty::t, + len: uint, + span: span) + -> DIType { + let element_type_metadata = get_or_create_type_metadata(cx, element_type, span); + let element_llvm_type = type_of::type_of(cx, element_type); + let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type); let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange( DIB(cx), @@ -811,39 +809,41 @@ fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t, let subscripts = create_DIArray(DIB(cx), [subrange]); return unsafe { llvm::LLVMDIBuilderCreateArrayType( DIB(cx), - bytes_to_bits(size * len), - bytes_to_bits(align), - elem_ty_md, + bytes_to_bits(element_type_size * len), + bytes_to_bits(element_type_align), + element_type_metadata, subscripts )}; } -fn create_boxed_vec(cx: &mut CrateContext, - element_type: ty::t, - span: span) - -> DICompositeType { +fn create_boxed_vec_metadata(cx: &mut CrateContext, + element_type: ty::t, + span: span) + -> DICompositeType { - let element_type_metadata = get_or_create_type(cx, element_type, span); + let element_type_metadata = get_or_create_type_metadata(cx, element_type, span); let element_llvm_type = type_of::type_of(cx, element_type); + let (element_size, element_align) = size_and_align_of(cx, element_llvm_type); + let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type); let vec_type_name = &"vec"; let member_llvm_types = vec_llvm_type.field_types(); let member_names = &[~"fill", ~"alloc", ~"elements"]; - let int_type_md = get_or_create_type(cx, ty::mk_int(), span); - let array_type_md = unsafe { llvm::LLVMDIBuilderCreateArrayType( + let int_type_metadata = get_or_create_type_metadata(cx, ty::mk_int(), span); + let array_type_metadata = unsafe { llvm::LLVMDIBuilderCreateArrayType( DIB(cx), - bytes_to_bits(machine::llsize_of_alloc(cx, element_llvm_type)), - bytes_to_bits(machine::llalign_of_min(cx, element_llvm_type)), + bytes_to_bits(element_size), + bytes_to_bits(element_align), element_type_metadata, create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)])) }; // fill alloc elements - let member_type_metadata = &[int_type_md, int_type_md, array_type_md]; + let member_type_metadata = &[int_type_metadata, int_type_metadata, array_type_metadata]; - let vec_md = create_composite_type( + let vec_metadata = create_composite_type_metadata( cx, vec_llvm_type, vec_type_name, @@ -852,16 +852,16 @@ fn create_boxed_vec(cx: &mut CrateContext, member_type_metadata, span); - return create_boxed_type(cx, vec_llvm_type, vec_md, span); + return create_boxed_type_metadata(cx, vec_llvm_type, vec_metadata, span); } -fn create_vec_slice(cx: &mut CrateContext, - vec_type: ty::t, - element_type: ty::t, - span: span) - -> DICompositeType { +fn create_vec_slice_metadata(cx: &mut CrateContext, + vec_type: ty::t, + element_type: ty::t, + span: span) + -> DICompositeType { - debug!("create_vec_slice: %?", ty::get(vec_type)); + debug!("create_vec_slice_metadata: %?", ty::get(vec_type)); let slice_llvm_type = type_of::type_of(cx, vec_type); let slice_type_name = ty_to_str(cx.tcx, vec_type); @@ -874,11 +874,11 @@ fn create_vec_slice(cx: &mut CrateContext, let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const }); let member_type_metadata = &[ - get_or_create_type(cx, data_ptr_type, span), - get_or_create_type(cx, ty::mk_uint(), span) + get_or_create_type_metadata(cx, data_ptr_type, span), + get_or_create_type_metadata(cx, ty::mk_uint(), span) ]; - return create_composite_type( + return create_composite_type_metadata( cx, slice_llvm_type, slice_type_name, @@ -897,31 +897,38 @@ fn create_vec_slice(cx: &mut CrateContext, } } -fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t, - span: span) -> DICompositeType { - debug!("create_fn_ty: %?", ty::get(_fn_ty)); +fn create_bare_fn_metadata(cx: &mut CrateContext, + _fn_ty: ty::t, + inputs: ~[ty::t], + output: ty::t, + span: span) + -> DICompositeType { + + debug!("create_bare_fn_metadata: %?", ty::get(_fn_ty)); let loc = span_start(cx, span); - let file_md = get_or_create_file(cx, loc.file.name); - let (vp, _, _) = voidptr(cx); - let output_md = get_or_create_type(cx, output, span); - let output_ptr_md = create_pointer_type(cx, output, span, output_md); - let inputs_vals = do inputs.map |arg| { get_or_create_type(cx, *arg, span) }; - let members = ~[output_ptr_md, vp] + inputs_vals; + let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + + let nil_pointer_type_metadata = get_or_create_type_metadata(cx, ty::mk_nil_ptr(cx.tcx), span); + let output_metadata = get_or_create_type_metadata(cx, output, span); + let output_ptr_metadata = create_pointer_type_metadata(cx, output, output_metadata); + + let inputs_vals = do inputs.map |arg| { get_or_create_type_metadata(cx, *arg, span) }; + let members = ~[output_ptr_metadata, nil_pointer_type_metadata] + inputs_vals; return unsafe { llvm::LLVMDIBuilderCreateSubroutineType( DIB(cx), - file_md, + file_metadata, create_DIArray(DIB(cx), members)) }; } -fn create_unimpl_ty(cx: &mut CrateContext, t: ty::t) -> DIType { - debug!("create_unimpl_ty: %?", ty::get(t)); +fn create_unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { + debug!("create_unimplemented_type_metadata: %?", ty::get(t)); let name = ty_to_str(cx.tcx, t); - let md = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe { + let metadata = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe { llvm::LLVMDIBuilderCreateBasicType( DIB(cx), name, @@ -929,104 +936,107 @@ fn create_unimpl_ty(cx: &mut CrateContext, t: ty::t) -> DIType { 8_u64, DW_ATE_unsigned as c_uint) }}; - return md; + return metadata; } -fn get_or_create_type(cx: &mut CrateContext, t: ty::t, span: span) -> DIType { - let ty_id = ty::type_id(t); - match dbg_cx(cx).created_types.find(&ty_id) { - Some(ty_md) => return *ty_md, +fn get_or_create_type_metadata(cx: &mut CrateContext, + t: ty::t, + span: span) + -> DIType { + let type_id = ty::type_id(t); + match dbg_cx(cx).created_types.find(&type_id) { + Some(type_metadata) => return *type_metadata, None => () } - debug!("get_or_create_type: %?", ty::get(t)); + debug!("get_or_create_type_metadata: %?", ty::get(t)); let sty = copy ty::get(t).sty; - let ty_md = match sty { + let type_metadata = match sty { ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) => { - create_basic_type(cx, t, span) + create_basic_type_metadata(cx, t) }, ty::ty_estr(ref vstore) => { let i8_t = ty::mk_i8(); match *vstore { ty::vstore_fixed(len) => { - create_fixed_vec(cx, t, i8_t, len + 1, span) + create_fixed_vec_metadata(cx, i8_t, len + 1, span) }, ty::vstore_uniq | ty::vstore_box => { - let box_md = create_boxed_vec(cx, i8_t, span); - create_pointer_type(cx, t, span, box_md) + let box_metadata = create_boxed_vec_metadata(cx, i8_t, span); + create_pointer_type_metadata(cx, t, box_metadata) } ty::vstore_slice(_region) => { - create_vec_slice(cx, t, i8_t, span) + create_vec_slice_metadata(cx, t, i8_t, span) } } }, ty::ty_enum(def_id, ref substs) => { - create_enum_md(cx, t, def_id, substs, span) + create_enum_metadata(cx, t, def_id, substs, span) }, ty::ty_box(ref mt) => { let content_llvm_type = type_of::type_of(cx, mt.ty); - let content_type_metadata = get_or_create_type(cx, mt.ty, span); + let content_type_metadata = get_or_create_type_metadata(cx, mt.ty, span); - let box_metadata = create_boxed_type(cx, + let box_metadata = create_boxed_type_metadata(cx, content_llvm_type, content_type_metadata, span); - create_pointer_type(cx, t, span, box_metadata) + create_pointer_type_metadata(cx, t, box_metadata) }, ty::ty_evec(ref mt, ref vstore) => { match *vstore { ty::vstore_fixed(len) => { - create_fixed_vec(cx, t, mt.ty, len, span) + create_fixed_vec_metadata(cx, mt.ty, len, span) }, ty::vstore_uniq | ty::vstore_box => { - let box_md = create_boxed_vec(cx, mt.ty, span); - create_pointer_type(cx, t, span, box_md) + let box_metadata = create_boxed_vec_metadata(cx, mt.ty, span); + create_pointer_type_metadata(cx, t, box_metadata) }, ty::vstore_slice(_) => { - create_vec_slice(cx, t, mt.ty, span) + create_vec_slice_metadata(cx, t, mt.ty, span) } } }, ty::ty_uniq(ref mt) | ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { - let pointee = get_or_create_type(cx, mt.ty, span); - create_pointer_type(cx, t, span, pointee) + let pointee = get_or_create_type_metadata(cx, mt.ty, span); + create_pointer_type_metadata(cx, t, pointee) }, ty::ty_bare_fn(ref barefnty) => { let inputs = barefnty.sig.inputs.map(|a| *a); let output = barefnty.sig.output; - create_fn_ty(cx, t, inputs, output, span) + create_bare_fn_metadata(cx, t, inputs, output, span) }, ty::ty_closure(ref _closurety) => { cx.sess.span_note(span, "debuginfo for closure NYI"); - create_unimpl_ty(cx, t) + create_unimplemented_type_metadata(cx, t) }, ty::ty_trait(_did, ref _substs, ref _vstore, _, _bounds) => { cx.sess.span_note(span, "debuginfo for trait NYI"); - create_unimpl_ty(cx, t) + create_unimplemented_type_metadata(cx, t) }, ty::ty_struct(did, ref substs) => { let fields = ty::struct_fields(cx.tcx, did, substs); - create_struct(cx, t, fields, span) + create_struct_metadata(cx, t, fields, span) }, ty::ty_tup(ref elements) => { - create_tuple(cx, t, *elements, span) + create_tuple_metadata(cx, t, *elements, span) }, - _ => cx.sess.bug("debuginfo: unexpected type in get_or_create_type") + _ => cx.sess.bug("debuginfo: unexpected type in get_or_create_type_metadata") }; - dbg_cx(cx).created_types.insert(ty_id, ty_md); - return ty_md; + dbg_cx(cx).created_types.insert(type_id, type_metadata); + return type_metadata; } fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) { @@ -1062,9 +1072,8 @@ fn span_start(cx: &CrateContext, span: span) -> codemap::Loc { cx.sess.codemap.lookup_char_pos(span.lo) } -fn size_and_align_of(cx: &mut CrateContext, t: ty::t) -> (uint, uint) { - let llty = type_of::type_of(cx, t); - (machine::llsize_of_alloc(cx, llty), machine::llalign_of_min(cx, llty)) +fn size_and_align_of(cx: &mut CrateContext, llvm_type: Type) -> (uint, uint) { + (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type)) } fn bytes_to_bits(bytes: uint) -> c_ulonglong { From 70e5c08e39564b1ce69aeadb287fc4296ebdf04a Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 11 Jul 2013 10:17:31 +0200 Subject: [PATCH 15/26] debuginfo: Extended test suite with various tests for enums. --- src/test/debug-info/borrowed-enum.rs | 62 +++++++++++++++++++ src/test/debug-info/evec-in-struct.rs | 88 +++++++++++++++++++++++++++ src/test/debug-info/managed-enum.rs | 63 +++++++++++++++++++ src/test/debug-info/struct-in-enum.rs | 67 ++++++++++++++++++++ src/test/debug-info/unique-enum.rs | 63 +++++++++++++++++++ 5 files changed, 343 insertions(+) create mode 100644 src/test/debug-info/borrowed-enum.rs create mode 100644 src/test/debug-info/evec-in-struct.rs create mode 100644 src/test/debug-info/managed-enum.rs create mode 100644 src/test/debug-info/struct-in-enum.rs create mode 100644 src/test/debug-info/unique-enum.rs diff --git a/src/test/debug-info/borrowed-enum.rs b/src/test/debug-info/borrowed-enum.rs new file mode 100644 index 0000000000000..c73cddf0d89a7 --- /dev/null +++ b/src/test/debug-info/borrowed-enum.rs @@ -0,0 +1,62 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print *the_a_ref +// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}} + +// debugger:print *the_b_ref +// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}} + +// debugger:print *univariant_ref +// 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 +// datatype layout should be predictable as in this case. +enum ABC { + TheA { x: i64, y: i64 }, + TheB (i64, i32, i32), +} + +// This is a special case since it does not have the implicit discriminant field. +enum Univariant { + TheOnlyCase(i64) +} + +fn main() { + + // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452 + // 0b01111100011111000111110001111100 = 2088533116 + // 0b0111110001111100 = 31868 + // 0b01111100 = 124 + let the_a = TheA { x: 0, y: 8970181431921507452 }; + let the_a_ref : &ABC = &the_a; + + // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 + // 0b00010001000100010001000100010001 = 286331153 + // 0b0001000100010001 = 4369 + // 0b00010001 = 17 + let the_b = TheB (0, 286331153, 286331153); + let the_b_ref : &ABC = &the_b; + + let univariant = TheOnlyCase(4820353753753434); + let univariant_ref : &Univariant = &univariant; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/evec-in-struct.rs b/src/test/debug-info/evec-in-struct.rs new file mode 100644 index 0000000000000..7e42690548e70 --- /dev/null +++ b/src/test/debug-info/evec-in-struct.rs @@ -0,0 +1,88 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print no_padding1 +// check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// debugger:print no_padding2 +// check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} + +// debugger:print struct_internal_padding +// check:$3 = {x = {13, 14}, y = {15, 16}} + +// debugger:print single_vec +// check:$4 = {x = {17, 18, 19, 20, 21}} + +// debugger:print struct_padded_at_end +// check:$5 = {x = {22, 23}, y = {24, 25}} + +struct NoPadding1 { + x: [u32, ..3], + y: i32, + z: [f32, ..2] +} + +struct NoPadding2 { + x: [u32, ..3], + y: [[u32, ..2], ..2] +} + +struct StructInternalPadding { + x: [i16, ..2], + y: [i64, ..2] +} + +struct SingleVec { + x: [i16, ..5] +} + +struct StructPaddedAtEnd { + x: [i64, ..2], + y: [i16, ..2] +} + +fn main() { + + let no_padding1 = NoPadding1 { + x: [0, 1, 2], + y: -3, + z: [4.5, 5.5] + }; + + let no_padding2 = NoPadding2 { + x: [6, 7, 8], + y: [[9, 10], [11, 12]] + }; + + let struct_internal_padding = StructInternalPadding { + x: [13, 14], + y: [15, 16] + }; + + let single_vec = SingleVec { + x: [17, 18, 19, 20, 21] + }; + + let struct_padded_at_end = StructPaddedAtEnd { + x: [22, 23], + y: [24, 25] + }; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/managed-enum.rs b/src/test/debug-info/managed-enum.rs new file mode 100644 index 0000000000000..794a362e57310 --- /dev/null +++ b/src/test/debug-info/managed-enum.rs @@ -0,0 +1,63 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print the_a->val +// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}} + +// debugger:print the_b->val +// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}} + +// debugger:print univariant->val +// 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 +// datatype layout should be predictable as in this case. +enum ABC { + TheA { x: i64, y: i64 }, + TheB (i64, i32, i32), +} + +// This is a special case since it does not have the implicit discriminant field. +enum Univariant { + TheOnlyCase(i64) +} + +fn main() { + + // In order to avoid endianess trouble all of the following test values consist of a single + // repeated byte. This way each interpretation of the union should look the same, no matter if + // this is a big or little endian machine. + + // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452 + // 0b01111100011111000111110001111100 = 2088533116 + // 0b0111110001111100 = 31868 + // 0b01111100 = 124 + let the_a = @TheA { x: 0, y: 8970181431921507452 }; + + // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 + // 0b00010001000100010001000100010001 = 286331153 + // 0b0001000100010001 = 4369 + // 0b00010001 = 17 + let the_b = @TheB (0, 286331153, 286331153); + + let univariant = @TheOnlyCase(-9747455); + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/struct-in-enum.rs b/src/test/debug-info/struct-in-enum.rs new file mode 100644 index 0000000000000..c8ad621f6f0d4 --- /dev/null +++ b/src/test/debug-info/struct-in-enum.rs @@ -0,0 +1,67 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print union on +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print case1 +// check:$1 = {{Case1, 0, {x = 2088533116, y = 2088533116, z = 31868}}, {Case1, 0, 8970181431921507452, 31868}} + +// debugger:print case2 +// 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}}} + +struct Struct { + x: u32, + y: i32, + z: i16 +} + +// 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 +// datatype layout should be predictable as in this case. +enum Regular { + Case1(u64, Struct), + Case2(u64, u64, i16) +} + +enum Univariant { + TheOnlyCase(Struct) +} + +fn main() { + + // In order to avoid endianess trouble all of the following test values consist of a single + // repeated byte. This way each interpretation of the union should look the same, no matter if + // this is a big or little endian machine. + + // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452 + // 0b01111100011111000111110001111100 = 2088533116 + // 0b0111110001111100 = 31868 + // 0b01111100 = 124 + let case1 = Case1(0, Struct { x: 2088533116, y: 2088533116, z: 31868 }); + + // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 + // 0b00010001000100010001000100010001 = 286331153 + // 0b0001000100010001 = 4369 + // 0b00010001 = 17 + let case2 = Case2(0, 1229782938247303441, 4369); + + let univariant = TheOnlyCase(Struct { x: 123, y: 456, z: 789 }); + + zzz(); +} + +fn zzz() {()} diff --git a/src/test/debug-info/unique-enum.rs b/src/test/debug-info/unique-enum.rs new file mode 100644 index 0000000000000..c231ea5a42bb1 --- /dev/null +++ b/src/test/debug-info/unique-enum.rs @@ -0,0 +1,63 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print *the_a +// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}} + +// debugger:print *the_b +// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}} + +// debugger:print *univariant +// 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 +// datatype layout should be predictable as in this case. +enum ABC { + TheA { x: i64, y: i64 }, + TheB (i64, i32, i32), +} + +// This is a special case since it does not have the implicit discriminant field. +enum Univariant { + TheOnlyCase(i64) +} + +fn main() { + + // In order to avoid endianess trouble all of the following test values consist of a single + // repeated byte. This way each interpretation of the union should look the same, no matter if + // this is a big or little endian machine. + + // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452 + // 0b01111100011111000111110001111100 = 2088533116 + // 0b0111110001111100 = 31868 + // 0b01111100 = 124 + let the_a = ~TheA { x: 0, y: 8970181431921507452 }; + + // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 + // 0b00010001000100010001000100010001 = 286331153 + // 0b0001000100010001 = 4369 + // 0b00010001 = 17 + let the_b = ~TheB (0, 286331153, 286331153); + + let univariant = ~TheOnlyCase(123234); + + zzz(); +} + +fn zzz() {()} \ No newline at end of file From e0108a47abcd1977670aa2ca0e5e88321cf789bf Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 11 Jul 2013 12:51:47 +0200 Subject: [PATCH 16/26] 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 821242d64c96c..fd38ec39bb1bb 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 48ab05661781f..93a6ab4fcd905 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 c73cddf0d89a7..8c9a7799a293d 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 794a362e57310..1a3600a7d8cb3 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 c8ad621f6f0d4..6d4a40e193fa5 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 2be15e0f80f2e..972772b07d28a 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 43b97a9bbfc4c..66e64a1e20aa9 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 c231ea5a42bb1..443f641a85859 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 From 7af2e6ee451ffa9baacfc3eb04d45f7b3cee295d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 15 Jul 2013 12:14:49 +0200 Subject: [PATCH 17/26] debuginfo: Fixed unique pointers to data containing managed pointers. --- src/librustc/middle/trans/debuginfo.rs | 31 +++++++++---- .../debug-info/managed-box-within-unique.rs | 45 +++++++++++++++++++ 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 src/test/debug-info/managed-box-within-unique.rs diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 93a6ab4fcd905..1102428a53884 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -1137,15 +1137,7 @@ fn get_or_create_type_metadata(cx: &mut CrateContext, create_enum_metadata(cx, t, def_id, substs, span) }, ty::ty_box(ref mt) => { - let content_llvm_type = type_of::type_of(cx, mt.ty); - let content_type_metadata = get_or_create_type_metadata(cx, mt.ty, span); - - let box_metadata = create_boxed_type_metadata(cx, - content_llvm_type, - content_type_metadata, - span); - - create_pointer_type_metadata(cx, t, box_metadata) + create_pointer_to_box_metadata(cx, t, mt.ty) }, ty::ty_evec(ref mt, ref vstore) => { match *vstore { @@ -1162,6 +1154,9 @@ fn get_or_create_type_metadata(cx: &mut CrateContext, } } }, + ty::ty_uniq(ref mt) if ty::type_contents(cx.tcx, mt.ty).contains_managed() => { + create_pointer_to_box_metadata(cx, t, mt.ty) + }, ty::ty_uniq(ref mt) | ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { @@ -1193,6 +1188,24 @@ fn get_or_create_type_metadata(cx: &mut CrateContext, dbg_cx(cx).created_types.insert(type_id, type_metadata); return type_metadata; + + + fn create_pointer_to_box_metadata(cx: &mut CrateContext, + pointer_type: ty::t, + type_in_box: ty::t) + -> DIType { + let content_llvm_type = type_of::type_of(cx, type_in_box); + let content_type_metadata = get_or_create_type_metadata(cx, + type_in_box, + codemap::dummy_sp()); + + let box_metadata = create_boxed_type_metadata(cx, + content_llvm_type, + content_type_metadata, + codemap::dummy_sp()); + + create_pointer_type_metadata(cx, pointer_type, box_metadata) + } } fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) { diff --git a/src/test/debug-info/managed-box-within-unique.rs b/src/test/debug-info/managed-box-within-unique.rs new file mode 100644 index 0000000000000..411b6e0a7eece --- /dev/null +++ b/src/test/debug-info/managed-box-within-unique.rs @@ -0,0 +1,45 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print *ordinary_unique +// check:$1 = {-1, -2} + +// debugger:print managed_within_unique.val->x +// check:$2 = -3 + +// debugger:print managed_within_unique.val->y->val +// check:$3 = -4 + +struct ContainsManaged +{ + x: int, + y: @int +} + +fn main() { + + let ordinary_unique = ~(-1, -2); + + + // This is a special case: Normally values allocated in the exchange heap are not boxed, unless, + // however, if they contain managed pointers. + // This test case verifies that both cases are handled correctly. + let managed_within_unique = ~ContainsManaged { x: -3, y: @-4 }; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file From eed2d0e1f2f4c6743b33efa06d5028fcc33db3b1 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 15 Jul 2013 15:48:57 +0200 Subject: [PATCH 18/26] debuginfo: Added support for Option-like enums. --- src/librustc/middle/trans/debuginfo.rs | 4 +- src/test/debug-info/option-like-enum.rs | 69 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/test/debug-info/option-like-enum.rs diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 1102428a53884..2f9b9f19041ff 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -673,7 +673,9 @@ fn create_enum_metadata(cx: &mut CrateContext, 0) // RuntimeLang }}; } - _ => { return ptr::null(); } + adt::NullablePointer { nonnull: ref struct_def, nndiscr, _ } => { + return create_adt_struct_metadata(cx, struct_def, variants[nndiscr], None, span); + } } fn create_adt_struct_metadata(cx: &mut CrateContext, diff --git a/src/test/debug-info/option-like-enum.rs b/src/test/debug-info/option-like-enum.rs new file mode 100644 index 0000000000000..c909d6f54eb8e --- /dev/null +++ b/src/test/debug-info/option-like-enum.rs @@ -0,0 +1,69 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print some +// check:$1 = {0x12345678} + +// debugger:print none +// check:$2 = {0x0} + +// debugger:print full +// check:$3 = {454545, 0x87654321, 9988} + +// debugger:print empty +// check:$4 = {0, 0x0, 0} + +// debugger:print droid +// check:$5 = {id = 675675, range = 10000001, internals = 0x43218765} + +// debugger:print void_droid +// check:$6 = {id = 0, range = 0, internals = 0x0} + + +// If a struct has exactly two variants, one of them is empty, and the other one +// contains a non-nullable pointer, then this value is used as the discriminator. +// The test cases in this file make sure that something readable is generated for +// this kind of types. + +enum MoreFields<'self> { + Full(u32, &'self int, i16), + Empty +} + +enum NamedFields<'self> { + Droid { id: i32, range: i64, internals: &'self int }, + Void +} + +fn main() { + + let some : Option<&u32> = Some(unsafe { std::cast::transmute(0x12345678) }); + let none : Option<&u32> = None; + + let full = Full(454545, unsafe { std::cast::transmute(0x87654321) }, 9988); + + let int_val = 0; + let mut empty = Full(0, &int_val, 0); + empty = Empty; + + let droid = Droid { id: 675675, range: 10000001, internals: unsafe { std::cast::transmute(0x43218765) } }; + + let mut void_droid = Droid { id: 0, range: 0, internals: &int_val }; + void_droid = Void; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file From b2aeb4b04bccf915444fa2a49ee3f3c33dec7097 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 16 Jul 2013 12:17:55 +0200 Subject: [PATCH 19/26] debuginfo: Cleaned up style issues for pull request. --- src/librustc/lib/llvm.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 844 ++++++++++-------- src/librustc/middle/ty.rs | 18 +- src/librustc/middle/typeck/check/mod.rs | 6 +- src/test/debug-info/borrowed-basic.rs | 30 +- src/test/debug-info/borrowed-c-style-enum.rs | 6 +- src/test/debug-info/borrowed-enum.rs | 6 +- src/test/debug-info/borrowed-managed-basic.rs | 30 +- src/test/debug-info/borrowed-struct.rs | 20 +- src/test/debug-info/borrowed-tuple.rs | 10 +- src/test/debug-info/borrowed-unique-basic.rs | 30 +- src/test/debug-info/box.rs | 2 + src/test/debug-info/boxed-struct.rs | 2 + src/test/debug-info/boxed-vec.rs | 6 +- .../debug-info/c-style-enum-in-composite.rs | 2 + src/test/debug-info/c-style-enum.rs | 2 + src/test/debug-info/destructured-local.rs | 2 +- .../debug-info/managed-box-within-unique.rs | 2 + src/test/debug-info/nil-enum.rs | 6 +- src/test/debug-info/option-like-enum.rs | 6 +- src/test/debug-info/simple-tuple.rs | 14 +- src/test/debug-info/struct-in-enum.rs | 2 + src/test/debug-info/struct-style-enum.rs | 2 + src/test/debug-info/struct-with-destructor.rs | 10 +- src/test/debug-info/tuple-in-tuple.rs | 14 +- src/test/debug-info/tuple-style-enum.rs | 2 + src/test/debug-info/vec-slices.rs | 12 +- src/test/debug-info/vec.rs | 2 + 28 files changed, 589 insertions(+), 501 deletions(-) diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 1ce4108b3b55d..7acd9545efdd0 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -2127,7 +2127,7 @@ pub mod llvm { AlignInBits: c_ulonglong, Flags: c_uint , Elements: ValueRef, - RunTimeLang : c_uint) -> ValueRef; + RunTimeLang: c_uint) -> ValueRef; } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 2f9b9f19041ff..eea65a4c48add 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -65,8 +65,8 @@ use syntax::{ast, codemap, ast_util, ast_map}; static DW_LANG_RUST: int = 0x9000; -static AutoVariableTag: int = 256; -static ArgVariableTag: int = 257; +static DW_TAG_auto_variable: int = 0x100; +static DW_TAG_arg_variable: int = 0x101; static DW_ATE_boolean: int = 0x02; static DW_ATE_float: int = 0x04; @@ -116,7 +116,7 @@ impl DebugContext { /// Create any deferred debug metadata nodes pub fn finalize(cx: @mut CrateContext) { debug!("finalize"); - create_compile_unit_metadata(cx); + compile_unit_metadata(cx); unsafe { llvm::LLVMDIBuilderFinalize(DIB(cx)); llvm::LLVMDIBuilderDispose(DIB(cx)); @@ -144,27 +144,29 @@ pub fn create_local_var_metadata(bcx: block, local: @ast::local) -> DIVariable { let loc = span_start(cx, local.span); let ty = node_id_type(bcx, local.node.id); - let type_metadata = get_or_create_type_metadata(cx, ty, local.node.ty.span); - let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let type_metadata = type_metadata(cx, ty, local.node.ty.span); + let file_metadata = file_metadata(cx, loc.file.name); let context = match bcx.parent { None => create_function_metadata(bcx.fcx), - Some(_) => get_or_create_block_metadata(bcx) + Some(_) => block_metadata(bcx) }; - let var_metadata = do as_c_str(name) |name| { unsafe { - llvm::LLVMDIBuilderCreateLocalVariable( - DIB(cx), - AutoVariableTag as u32, - context, - name, - file_metadata, - loc.line as c_uint, - type_metadata, - false, - 0, - 0) - }}; + let var_metadata = do as_c_str(name) |name| { + unsafe { + llvm::LLVMDIBuilderCreateLocalVariable( + DIB(cx), + DW_TAG_auto_variable as u32, + context, + name, + file_metadata, + loc.line as c_uint, + type_metadata, + false, + 0, + 0) + } + }; // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) { @@ -176,7 +178,7 @@ pub fn create_local_var_metadata(bcx: block, local: @ast::local) -> DIVariable { } }; - set_debug_location(cx, get_or_create_block_metadata(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb); llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); @@ -207,8 +209,8 @@ pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Optio } let ty = node_id_type(bcx, arg.id); - let type_metadata = get_or_create_type_metadata(cx, ty, arg.ty.span); - let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let type_metadata = type_metadata(cx, ty, arg.ty.span); + let file_metadata = file_metadata(cx, loc.file.name); let context = create_function_metadata(fcx); match arg.pat.node { @@ -216,23 +218,25 @@ pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Optio // XXX: This is wrong; it should work for multiple bindings. let ident = path.idents.last(); let name: &str = cx.sess.str_of(*ident); - let var_metadata = do as_c_str(name) |name| { unsafe { - llvm::LLVMDIBuilderCreateLocalVariable( - DIB(cx), - ArgVariableTag as u32, - context, - name, - file_metadata, - loc.line as c_uint, - type_metadata, - false, - 0, - 0) + let var_metadata = do as_c_str(name) |name| { + unsafe { + llvm::LLVMDIBuilderCreateLocalVariable( + DIB(cx), + DW_TAG_arg_variable as u32, + context, + name, + file_metadata, + loc.line as c_uint, + type_metadata, + false, + 0, + 0) // XXX need to pass in a real argument number - }}; + } + }; let llptr = fcx.llargs.get_copy(&arg.id); - set_debug_location(cx, get_or_create_block_metadata(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( DIB(cx), llptr, var_metadata, bcx.llbb); @@ -255,7 +259,7 @@ pub fn update_source_pos(bcx: block, span: span) { } debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span)); let loc = span_start(bcx.ccx(), span); - set_debug_location(bcx.ccx(), get_or_create_block_metadata(bcx), loc.line, loc.col.to_uint()) + set_debug_location(bcx.ccx(), block_metadata(bcx), loc.line, loc.col.to_uint()) } /// Creates debug information for the given function. @@ -305,12 +309,12 @@ pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram { cx.sess.codemap.span_to_str(span)); let loc = span_start(cx, span); - let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let file_metadata = file_metadata(cx, loc.file.name); let return_type_metadata = if cx.sess.opts.extra_debuginfo { match ret_ty.node { ast::ty_nil => ptr::null(), - _ => get_or_create_type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) + _ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span) } } else { ptr::null() @@ -325,24 +329,26 @@ pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram { let fn_metadata = do as_c_str(cx.sess.str_of(ident)) |name| { - do as_c_str(cx.sess.str_of(ident)) |linkage| { unsafe { - llvm::LLVMDIBuilderCreateFunction( - DIB(cx), - file_metadata, - name, - linkage, - file_metadata, - loc.line as c_uint, - fn_ty, - false, - true, - loc.line as c_uint, - FlagPrototyped as c_uint, - cx.sess.opts.optimize != session::No, - fcx.llfn, - ptr::null(), - ptr::null()) - }}}; + do as_c_str(cx.sess.str_of(ident)) |linkage| { + unsafe { + llvm::LLVMDIBuilderCreateFunction( + DIB(cx), + file_metadata, + name, + linkage, + file_metadata, + loc.line as c_uint, + fn_ty, + false, + true, + loc.line as c_uint, + FlagPrototyped as c_uint, + cx.sess.opts.optimize != session::No, + fcx.llfn, + ptr::null(), + ptr::null()) + } + }}; dbg_cx(cx).created_functions.insert(id, fn_metadata); return fn_metadata; @@ -361,11 +367,11 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { }; } -fn create_compile_unit_metadata(cx: @mut CrateContext) { +fn compile_unit_metadata(cx: @mut CrateContext) { let dcx = dbg_cx(cx); let crate_name: &str = dcx.crate_file; - debug!("create_compile_unit_metadata: %?", crate_name); + debug!("compile_unit_metadata: %?", crate_name); let work_dir = cx.sess.working_dir.to_str(); let producer = fmt!("rustc version %s", env!("CFG_VERSION")); @@ -374,21 +380,23 @@ fn create_compile_unit_metadata(cx: @mut CrateContext) { do as_c_str(work_dir) |work_dir| { do as_c_str(producer) |producer| { do as_c_str("") |flags| { - do as_c_str("") |split_name| { unsafe { - llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder, - DW_LANG_RUST as c_uint, crate_name, work_dir, producer, - cx.sess.opts.optimize != session::No, - flags, 0, split_name); - }}}}}}; + do as_c_str("") |split_name| { + unsafe { + llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder, + DW_LANG_RUST as c_uint, crate_name, work_dir, producer, + cx.sess.opts.optimize != session::No, + flags, 0, split_name); + } + }}}}}; } -fn get_or_create_file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile { +fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile { match dbg_cx(cx).created_files.find_equiv(&full_path) { Some(file_metadata) => return *file_metadata, None => () } - debug!("get_or_create_file_metadata: %s", full_path); + debug!("file_metadata: %s", full_path); let work_dir = cx.sess.working_dir.to_str(); let file_name = @@ -400,15 +408,17 @@ fn get_or_create_file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile let file_metadata = do as_c_str(file_name) |file_name| { - do as_c_str(work_dir) |work_dir| { unsafe { - llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir) - }}}; + do as_c_str(work_dir) |work_dir| { + unsafe { + llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir) + } + }}; dbg_cx(cx).created_files.insert(full_path.to_owned(), file_metadata); return file_metadata; } -fn get_or_create_block_metadata(bcx: block) -> DILexicalBlock { +fn block_metadata(bcx: block) -> DILexicalBlock { let mut bcx = bcx; let cx = bcx.ccx(); @@ -426,15 +436,15 @@ fn get_or_create_block_metadata(bcx: block) -> DILexicalBlock { None => () } - debug!("get_or_create_block_metadata: %s", bcx.sess().codemap.span_to_str(span)); + debug!("block_metadata: %s", bcx.sess().codemap.span_to_str(span)); let parent = match bcx.parent { None => create_function_metadata(bcx.fcx), - Some(b) => get_or_create_block_metadata(b) + Some(b) => block_metadata(b) }; let cx = bcx.ccx(); let loc = span_start(cx, span); - let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let file_metadata = file_metadata(cx, loc.file.name); let block_metadata = unsafe { llvm::LLVMDIBuilderCreateLexicalBlock( @@ -448,9 +458,9 @@ fn get_or_create_block_metadata(bcx: block) -> DILexicalBlock { return block_metadata; } -fn create_basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { +fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { - debug!("create_basic_type_metadata: %?", ty::get(t)); + debug!("basic_type_metadata: %?", ty::get(t)); let (name, encoding) = match ty::get(t).sty { ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned), @@ -475,58 +485,62 @@ fn create_basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { ast::ty_f32 => (~"f32", DW_ATE_float), ast::ty_f64 => (~"f64", DW_ATE_float) }, - _ => cx.sess.bug("debuginfo::create_basic_type_metadata - t is invalid type") + _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type") }; let llvm_type = type_of::type_of(cx, t); let (size, align) = size_and_align_of(cx, llvm_type); - let ty_metadata = do as_c_str(name) |name| { unsafe { + let ty_metadata = do as_c_str(name) |name| { + unsafe { llvm::LLVMDIBuilderCreateBasicType( DIB(cx), name, bytes_to_bits(size), bytes_to_bits(align), encoding as c_uint) - }}; + } + }; return ty_metadata; } -fn create_pointer_type_metadata(cx: &mut CrateContext, - pointer_type: ty::t, - pointee_type_metadata: DIType) - -> DIType { +fn pointer_type_metadata(cx: &mut CrateContext, + pointer_type: ty::t, + pointee_type_metadata: DIType) + -> DIType { let pointer_llvm_type = type_of::type_of(cx, pointer_type); let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type); let name = ty_to_str(cx.tcx, pointer_type); - let ptr_metadata = do as_c_str(name) |name| { unsafe { - llvm::LLVMDIBuilderCreatePointerType( - DIB(cx), - pointee_type_metadata, - bytes_to_bits(pointer_size), - bytes_to_bits(pointer_align), - name) - }}; + let ptr_metadata = do as_c_str(name) |name| { + unsafe { + llvm::LLVMDIBuilderCreatePointerType( + DIB(cx), + pointee_type_metadata, + bytes_to_bits(pointer_size), + bytes_to_bits(pointer_align), + name) + } + }; return ptr_metadata; } -fn create_struct_metadata(cx: &mut CrateContext, - struct_type: ty::t, - fields: ~[ty::field], - span: span) - -> DICompositeType { +fn struct_metadata(cx: &mut CrateContext, + struct_type: ty::t, + fields: ~[ty::field], + span: span) + -> DICompositeType { let struct_name = ty_to_str(cx.tcx, struct_type); - debug!("create_struct_metadata: %s", struct_name); + debug!("struct_metadata: %s", struct_name); let struct_llvm_type = type_of::type_of(cx, struct_type); let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) }; let field_names = do fields.map |field| { cx.sess.str_of(field.ident).to_owned() }; let field_types_metadata = do fields.map |field| { - get_or_create_type_metadata(cx, field.mt.ty, span) + type_metadata(cx, field.mt.ty, span) }; - return create_composite_type_metadata( + return composite_type_metadata( cx, struct_llvm_type, struct_name, @@ -536,11 +550,11 @@ fn create_struct_metadata(cx: &mut CrateContext, span); } -fn create_tuple_metadata(cx: &mut CrateContext, - tuple_type: ty::t, - component_types: &[ty::t], - span: span) - -> DICompositeType { +fn tuple_metadata(cx: &mut CrateContext, + tuple_type: ty::t, + component_types: &[ty::t], + span: span) + -> DICompositeType { let tuple_name = ty_to_str(cx.tcx, tuple_type); let tuple_llvm_type = type_of::type_of(cx, tuple_type); @@ -548,10 +562,10 @@ fn create_tuple_metadata(cx: &mut CrateContext, let component_names = do component_types.map |_| { ~"" }; let component_llvm_types = do component_types.map |it| { type_of::type_of(cx, *it) }; let component_types_metadata = do component_types.map |it| { - get_or_create_type_metadata(cx, *it, span) + type_metadata(cx, *it, span) }; - return create_composite_type_metadata( + return composite_type_metadata( cx, tuple_llvm_type, tuple_name, @@ -564,19 +578,19 @@ fn create_tuple_metadata(cx: &mut CrateContext, // 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 { +fn 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); + return composite_type_metadata(cx, Type::nil(), enum_name, [], [], [], span); } // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be @@ -585,40 +599,44 @@ fn create_enum_metadata(cx: &mut CrateContext, 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 discriminant_type_metadata = type_metadata(cx, ty::mk_int(), span); - let variants : &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); + let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); - let enumerators_metadata : ~[DIDescriptor] = variants + let enumerators_metadata: ~[DIDescriptor] = variants .iter() .transform(|v| { - let name : &str = cx.sess.str_of(v.name); + 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) - }} + 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 file_metadata = 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 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); @@ -626,71 +644,75 @@ fn create_enum_metadata(cx: &mut CrateContext, adt::CEnum(*) => { return discriminant_type_metadata; } - adt::Univariant(ref struct_def, _destroyed_flag) => { + adt::Univariant(ref struct_def, _) => { assert!(variants.len() == 1); - return create_adt_struct_metadata(cx, struct_def, variants[0], None, span); + return adt_struct_metadata(cx, struct_def, variants[0], None, span); } adt::General(ref struct_defs) => { - let variants_member_metadata : ~[DIDescriptor] = do struct_defs + let variants_member_metadata: ~[DIDescriptor] = do struct_defs .iter() .enumerate() .transform |(i, struct_def)| { - let variant_type_metadata = create_adt_struct_metadata( + let variant_type_metadata = 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) - }} + 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 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 }}; } adt::NullablePointer { nonnull: ref struct_def, nndiscr, _ } => { - return create_adt_struct_metadata(cx, struct_def, variants[nndiscr], None, span); + return adt_struct_metadata(cx, struct_def, variants[nndiscr], None, span); } } - fn create_adt_struct_metadata(cx: &mut CrateContext, + fn 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() + 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) + _ => type_metadata(cx, ty, span) } }.collect(); @@ -699,14 +721,14 @@ fn create_enum_metadata(cx: &mut CrateContext, None => do variant_info.args.map |_| { ~"" } }; - if (discriminant_type_metadata.is_some()) { + 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); + let variant_name: &str = cx.sess.str_of(variant_info.name); - return create_composite_type_metadata( + return composite_type_metadata( cx, variant_llvm_type, variant_name, @@ -718,19 +740,19 @@ fn create_enum_metadata(cx: &mut CrateContext, } #[cfg(stage0)] -fn create_enum_metadata(cx: &mut CrateContext, - enum_type: ty::t, - enum_def_id: ast::def_id, - substs: &ty::substs, - span: span) - -> DIType { +fn 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); + return composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span); } // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be @@ -739,40 +761,44 @@ fn create_enum_metadata(cx: &mut CrateContext, 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 discriminant_type_metadata = type_metadata(cx, ty::mk_int(), span); - let variants : &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); + let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id); - let enumerators_metadata : ~[DIDescriptor] = variants + let enumerators_metadata: ~[DIDescriptor] = variants .iter() .transform(|v| { - let name : &str = cx.sess.str_of(v.name); + 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) - }} + 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 file_metadata = 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 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) + } + }; if ty::type_is_c_like_enum(cx.tcx, enum_type) { return discriminant_type_metadata; @@ -782,7 +808,7 @@ fn create_enum_metadata(cx: &mut CrateContext, let variants_metadata = do variants.map |&vi| { - let raw_types : &[ty::t] = vi.args; + let raw_types: &[ty::t] = vi.args; let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) }; let mut arg_llvm_types = do arg_types.map |&ty| { type_of::type_of(cx, ty) }; @@ -791,7 +817,7 @@ fn create_enum_metadata(cx: &mut CrateContext, None => do arg_types.map |_| { ~"" } }; - let mut arg_metadata = do arg_types.map |&ty| { get_or_create_type_metadata(cx, ty, span) }; + let mut arg_metadata = do arg_types.map |&ty| { type_metadata(cx, ty, span) }; if !is_univariant { arg_llvm_types.insert(0, discriminant_llvm_type); @@ -802,7 +828,7 @@ fn create_enum_metadata(cx: &mut CrateContext, let variant_llvm_type = Type::struct_(arg_llvm_types, false); let (variant_type_size, variant_type_align) = size_and_align_of(cx, variant_llvm_type); - let variant_type_metadata = create_composite_type_metadata( + let variant_type_metadata = composite_type_metadata( cx, variant_llvm_type, &"", @@ -811,135 +837,150 @@ fn create_enum_metadata(cx: &mut CrateContext, arg_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(variant_type_size), - bytes_to_bits(variant_type_align), - bytes_to_bits(0), - 0, - variant_type_metadata) - }} + do "".as_c_str |name| { + unsafe { + llvm::LLVMDIBuilderCreateMemberType( + DIB(cx), + file_metadata, + name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(variant_type_size), + bytes_to_bits(variant_type_align), + bytes_to_bits(0), + 0, + variant_type_metadata) + } + } }; 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_metadata), - 0) // RuntimeLang - }}; + 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_metadata), + 0) // RuntimeLang + } + }; } /// Creates debug information for a composite type, that is, anything that results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn create_composite_type_metadata(cx: &mut CrateContext, - composite_llvm_type: Type, - composite_type_name: &str, - member_llvm_types: &[Type], - member_names: &[~str], - member_type_metadata: &[DIType], - span: span) - -> DICompositeType { +fn composite_type_metadata(cx: &mut CrateContext, + composite_llvm_type: Type, + composite_type_name: &str, + member_llvm_types: &[Type], + member_names: &[~str], + member_type_metadata: &[DIType], + span: span) + -> DICompositeType { let loc = span_start(cx, span); - let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let file_metadata = file_metadata(cx, loc.file.name); let (composite_size, composite_align) = size_and_align_of(cx, composite_llvm_type); - let member_metadata : ~[DIDescriptor] = member_llvm_types + let member_metadata: ~[DIDescriptor] = member_llvm_types .iter() .enumerate() .transform(|(i, &member_llvm_type)| { let (member_size, member_align) = size_and_align_of(cx, member_llvm_type); let member_offset = machine::llelement_offset(cx, composite_llvm_type, i); - let member_name : &str = member_names[i]; - - do member_name.as_c_str |member_name| { unsafe { - llvm::LLVMDIBuilderCreateMemberType( - DIB(cx), - file_metadata, - member_name, - file_metadata, - loc.line as c_uint, - bytes_to_bits(member_size), - bytes_to_bits(member_align), - bytes_to_bits(member_offset), - 0, - member_type_metadata[i]) - }} + let member_name: &str = member_names[i]; + + do member_name.as_c_str |member_name| { + unsafe { + llvm::LLVMDIBuilderCreateMemberType( + DIB(cx), + file_metadata, + member_name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(member_size), + bytes_to_bits(member_align), + bytes_to_bits(member_offset), + 0, + member_type_metadata[i]) + } + } }) .collect(); - return do composite_type_name.as_c_str |name| { unsafe { - llvm::LLVMDIBuilderCreateStructType( - DIB(cx), - file_metadata, - name, - file_metadata, - loc.line as c_uint, - bytes_to_bits(composite_size), - bytes_to_bits(composite_align), - 0, - ptr::null(), - create_DIArray(DIB(cx), member_metadata), - 0, - ptr::null()) - }}; + return do composite_type_name.as_c_str |name| { + unsafe { + llvm::LLVMDIBuilderCreateStructType( + DIB(cx), + file_metadata, + name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(composite_size), + bytes_to_bits(composite_align), + 0, + ptr::null(), + create_DIArray(DIB(cx), member_metadata), + 0, + ptr::null()) + } + }; } -fn create_boxed_type_metadata(cx: &mut CrateContext, - content_llvm_type: Type, - content_type_metadata: DIType, - span: span) - -> DICompositeType { +fn boxed_type_metadata(cx: &mut CrateContext, + content_type_name: Option<&str>, + content_llvm_type: Type, + content_type_metadata: DIType, + span: span) + -> DICompositeType { + + let box_type_name = match content_type_name { + Some(content_type_name) => fmt!("Boxed<%s>", content_type_name), + None => ~"BoxedType" + }; let box_llvm_type = Type::box(cx, &content_llvm_type); let member_llvm_types = box_llvm_type.field_types(); let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"]; - assert!(box_layout_is_as_expected(cx, member_llvm_types, content_llvm_type)); + assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type)); let int_type = ty::mk_int(); let nil_pointer_type = ty::mk_nil_ptr(cx.tcx); let member_types_metadata = [ - get_or_create_type_metadata(cx, int_type, span), - get_or_create_type_metadata(cx, nil_pointer_type, span), - get_or_create_type_metadata(cx, nil_pointer_type, span), - get_or_create_type_metadata(cx, nil_pointer_type, span), + type_metadata(cx, int_type, span), + type_metadata(cx, nil_pointer_type, span), + type_metadata(cx, nil_pointer_type, span), + type_metadata(cx, nil_pointer_type, span), content_type_metadata ]; - return create_composite_type_metadata( + return composite_type_metadata( cx, box_llvm_type, - "box name", + box_type_name, member_llvm_types, member_names, member_types_metadata, span); // Unfortunately, we cannot assert anything but the correct types here---and not whether the - // 'next' and 'prev' pointers are in the order. - fn box_layout_is_as_expected(cx: &CrateContext, - member_llvm_types: &[Type], - content_llvm_type: Type) - -> bool { + // 'next' and 'prev' pointers are in the correct order. + fn box_layout_is_correct(cx: &CrateContext, + member_llvm_types: &[Type], + content_llvm_type: Type) + -> bool { member_llvm_types.len() == 5 && member_llvm_types[0] == cx.int_type && member_llvm_types[1] == cx.tydesc_type.ptr_to() && @@ -949,59 +990,62 @@ fn create_boxed_type_metadata(cx: &mut CrateContext, } } -fn create_fixed_vec_metadata(cx: &mut CrateContext, - element_type: ty::t, - len: uint, - span: span) - -> DIType { - let element_type_metadata = get_or_create_type_metadata(cx, element_type, span); +fn fixed_vec_metadata(cx: &mut CrateContext, + element_type: ty::t, + len: uint, + span: span) + -> DIType { + let element_type_metadata = type_metadata(cx, element_type, span); let element_llvm_type = type_of::type_of(cx, element_type); let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type); - let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange( + let subrange = unsafe { + llvm::LLVMDIBuilderGetOrCreateSubrange( DIB(cx), 0, - len as c_longlong - )}; + len as c_longlong) + }; let subscripts = create_DIArray(DIB(cx), [subrange]); - return unsafe { llvm::LLVMDIBuilderCreateArrayType( + return unsafe { + llvm::LLVMDIBuilderCreateArrayType( DIB(cx), bytes_to_bits(element_type_size * len), bytes_to_bits(element_type_align), element_type_metadata, - subscripts - )}; + subscripts) + }; } -fn create_boxed_vec_metadata(cx: &mut CrateContext, - element_type: ty::t, - span: span) - -> DICompositeType { +fn boxed_vec_metadata(cx: &mut CrateContext, + element_type: ty::t, + span: span) + -> DICompositeType { - let element_type_metadata = get_or_create_type_metadata(cx, element_type, span); + let element_type_metadata = type_metadata(cx, element_type, span); let element_llvm_type = type_of::type_of(cx, element_type); let (element_size, element_align) = size_and_align_of(cx, element_llvm_type); let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type); - let vec_type_name = &"vec"; + let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type)); let member_llvm_types = vec_llvm_type.field_types(); let member_names = &[~"fill", ~"alloc", ~"elements"]; - let int_type_metadata = get_or_create_type_metadata(cx, ty::mk_int(), span); - let array_type_metadata = unsafe { llvm::LLVMDIBuilderCreateArrayType( - DIB(cx), - bytes_to_bits(element_size), - bytes_to_bits(element_align), - element_type_metadata, - create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)])) + let int_type_metadata = type_metadata(cx, ty::mk_int(), span); + let array_type_metadata = unsafe { + llvm::LLVMDIBuilderCreateArrayType( + DIB(cx), + bytes_to_bits(element_size), + bytes_to_bits(element_align), + element_type_metadata, + create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)])) }; - // fill alloc elements + // fill alloc elements let member_type_metadata = &[int_type_metadata, int_type_metadata, array_type_metadata]; - let vec_metadata = create_composite_type_metadata( + let vec_metadata = composite_type_metadata( cx, vec_llvm_type, vec_type_name, @@ -1010,16 +1054,21 @@ fn create_boxed_vec_metadata(cx: &mut CrateContext, member_type_metadata, span); - return create_boxed_type_metadata(cx, vec_llvm_type, vec_metadata, span); + return boxed_type_metadata( + cx, + Some(vec_type_name), + vec_llvm_type, + vec_metadata, + span); } -fn create_vec_slice_metadata(cx: &mut CrateContext, - vec_type: ty::t, - element_type: ty::t, - span: span) - -> DICompositeType { +fn vec_slice_metadata(cx: &mut CrateContext, + vec_type: ty::t, + element_type: ty::t, + span: span) + -> DICompositeType { - debug!("create_vec_slice_metadata: %?", ty::get(vec_type)); + debug!("vec_slice_metadata: %?", ty::get(vec_type)); let slice_llvm_type = type_of::type_of(cx, vec_type); let slice_type_name = ty_to_str(cx.tcx, vec_type); @@ -1027,16 +1076,14 @@ fn create_vec_slice_metadata(cx: &mut CrateContext, let member_llvm_types = slice_llvm_type.field_types(); let member_names = &[~"data_ptr", ~"size_in_bytes"]; - assert!(slice_layout_is_as_expected(cx, member_llvm_types, element_type)); + assert!(slice_layout_is_correct(cx, member_llvm_types, element_type)); - let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const }); + let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_imm }); - let member_type_metadata = &[ - get_or_create_type_metadata(cx, data_ptr_type, span), - get_or_create_type_metadata(cx, ty::mk_uint(), span) - ]; + let member_type_metadata = &[type_metadata(cx, data_ptr_type, span), + type_metadata(cx, ty::mk_uint(), span)]; - return create_composite_type_metadata( + return composite_type_metadata( cx, slice_llvm_type, slice_type_name, @@ -1045,33 +1092,33 @@ fn create_vec_slice_metadata(cx: &mut CrateContext, member_type_metadata, span); - fn slice_layout_is_as_expected(cx: &mut CrateContext, - member_llvm_types: &[Type], - element_type: ty::t) - -> bool { + fn slice_layout_is_correct(cx: &mut CrateContext, + member_llvm_types: &[Type], + element_type: ty::t) + -> bool { member_llvm_types.len() == 2 && member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() && member_llvm_types[1] == cx.int_type } } -fn create_bare_fn_metadata(cx: &mut CrateContext, - _fn_ty: ty::t, - inputs: ~[ty::t], - output: ty::t, - span: span) - -> DICompositeType { +fn bare_fn_metadata(cx: &mut CrateContext, + _fn_ty: ty::t, + inputs: ~[ty::t], + output: ty::t, + span: span) + -> DICompositeType { - debug!("create_bare_fn_metadata: %?", ty::get(_fn_ty)); + debug!("bare_fn_metadata: %?", ty::get(_fn_ty)); let loc = span_start(cx, span); - let file_metadata = get_or_create_file_metadata(cx, loc.file.name); + let file_metadata = file_metadata(cx, loc.file.name); - let nil_pointer_type_metadata = get_or_create_type_metadata(cx, ty::mk_nil_ptr(cx.tcx), span); - let output_metadata = get_or_create_type_metadata(cx, output, span); - let output_ptr_metadata = create_pointer_type_metadata(cx, output, output_metadata); + let nil_pointer_type_metadata = type_metadata(cx, ty::mk_nil_ptr(cx.tcx), span); + let output_metadata = type_metadata(cx, output, span); + let output_ptr_metadata = pointer_type_metadata(cx, output, output_metadata); - let inputs_vals = do inputs.map |arg| { get_or_create_type_metadata(cx, *arg, span) }; + let inputs_vals = do inputs.map |arg| { type_metadata(cx, *arg, span) }; let members = ~[output_ptr_metadata, nil_pointer_type_metadata] + inputs_vals; return unsafe { @@ -1082,32 +1129,57 @@ fn create_bare_fn_metadata(cx: &mut CrateContext, }; } -fn create_unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { - debug!("create_unimplemented_type_metadata: %?", ty::get(t)); +fn unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { + debug!("unimplemented_type_metadata: %?", ty::get(t)); let name = ty_to_str(cx.tcx, t); - let metadata = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe { - llvm::LLVMDIBuilderCreateBasicType( - DIB(cx), - name, - 0_u64, - 8_u64, - DW_ATE_unsigned as c_uint) - }}; + let metadata = do as_c_str(fmt!("NYI<%s>", name)) |name| { + unsafe { + llvm::LLVMDIBuilderCreateBasicType( + DIB(cx), + name, + 0_u64, + 8_u64, + DW_ATE_unsigned as c_uint) + } + }; + return metadata; } -fn get_or_create_type_metadata(cx: &mut CrateContext, - t: ty::t, - span: span) - -> DIType { +fn type_metadata(cx: &mut CrateContext, + t: ty::t, + span: span) + -> DIType { let type_id = ty::type_id(t); match dbg_cx(cx).created_types.find(&type_id) { Some(type_metadata) => return *type_metadata, None => () } - debug!("get_or_create_type_metadata: %?", ty::get(t)); + fn create_pointer_to_box_metadata(cx: &mut CrateContext, + pointer_type: ty::t, + type_in_box: ty::t) + -> DIType { + + let content_type_name: &str = ty_to_str(cx.tcx, type_in_box); + let content_llvm_type = type_of::type_of(cx, type_in_box); + let content_type_metadata = type_metadata( + cx, + type_in_box, + codemap::dummy_sp()); + + let box_metadata = boxed_type_metadata( + cx, + Some(content_type_name), + content_llvm_type, + content_type_metadata, + codemap::dummy_sp()); + + pointer_type_metadata(cx, pointer_type, box_metadata) + } + + debug!("type_metadata: %?", ty::get(t)); let sty = copy ty::get(t).sty; let type_metadata = match sty { @@ -1117,26 +1189,26 @@ fn get_or_create_type_metadata(cx: &mut CrateContext, ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) => { - create_basic_type_metadata(cx, t) + basic_type_metadata(cx, t) }, ty::ty_estr(ref vstore) => { let i8_t = ty::mk_i8(); match *vstore { ty::vstore_fixed(len) => { - create_fixed_vec_metadata(cx, i8_t, len + 1, span) + fixed_vec_metadata(cx, i8_t, len + 1, span) }, ty::vstore_uniq | ty::vstore_box => { - let box_metadata = create_boxed_vec_metadata(cx, i8_t, span); - create_pointer_type_metadata(cx, t, box_metadata) + let box_metadata = boxed_vec_metadata(cx, i8_t, span); + pointer_type_metadata(cx, t, box_metadata) } ty::vstore_slice(_region) => { - create_vec_slice_metadata(cx, t, i8_t, span) + vec_slice_metadata(cx, t, i8_t, span) } } }, ty::ty_enum(def_id, ref substs) => { - create_enum_metadata(cx, t, def_id, substs, span) + enum_metadata(cx, t, def_id, substs, span) }, ty::ty_box(ref mt) => { create_pointer_to_box_metadata(cx, t, mt.ty) @@ -1144,15 +1216,15 @@ fn get_or_create_type_metadata(cx: &mut CrateContext, ty::ty_evec(ref mt, ref vstore) => { match *vstore { ty::vstore_fixed(len) => { - create_fixed_vec_metadata(cx, mt.ty, len, span) + fixed_vec_metadata(cx, mt.ty, len, span) }, ty::vstore_uniq | ty::vstore_box => { - let box_metadata = create_boxed_vec_metadata(cx, mt.ty, span); - create_pointer_type_metadata(cx, t, box_metadata) + let box_metadata = boxed_vec_metadata(cx, mt.ty, span); + pointer_type_metadata(cx, t, box_metadata) }, ty::vstore_slice(_) => { - create_vec_slice_metadata(cx, t, mt.ty, span) + vec_slice_metadata(cx, t, mt.ty, span) } } }, @@ -1162,52 +1234,34 @@ fn get_or_create_type_metadata(cx: &mut CrateContext, ty::ty_uniq(ref mt) | ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { - let pointee = get_or_create_type_metadata(cx, mt.ty, span); - create_pointer_type_metadata(cx, t, pointee) + let pointee = type_metadata(cx, mt.ty, span); + pointer_type_metadata(cx, t, pointee) }, ty::ty_bare_fn(ref barefnty) => { let inputs = barefnty.sig.inputs.map(|a| *a); let output = barefnty.sig.output; - create_bare_fn_metadata(cx, t, inputs, output, span) + bare_fn_metadata(cx, t, inputs, output, span) }, ty::ty_closure(ref _closurety) => { cx.sess.span_note(span, "debuginfo for closure NYI"); - create_unimplemented_type_metadata(cx, t) + unimplemented_type_metadata(cx, t) }, ty::ty_trait(_did, ref _substs, ref _vstore, _, _bounds) => { cx.sess.span_note(span, "debuginfo for trait NYI"); - create_unimplemented_type_metadata(cx, t) + unimplemented_type_metadata(cx, t) }, ty::ty_struct(did, ref substs) => { let fields = ty::struct_fields(cx.tcx, did, substs); - create_struct_metadata(cx, t, fields, span) + struct_metadata(cx, t, fields, span) }, ty::ty_tup(ref elements) => { - create_tuple_metadata(cx, t, *elements, span) + tuple_metadata(cx, t, *elements, span) }, - _ => cx.sess.bug("debuginfo: unexpected type in get_or_create_type_metadata") + _ => cx.sess.bug("debuginfo: unexpected type in type_metadata") }; dbg_cx(cx).created_types.insert(type_id, type_metadata); return type_metadata; - - - fn create_pointer_to_box_metadata(cx: &mut CrateContext, - pointer_type: ty::t, - type_in_box: ty::t) - -> DIType { - let content_llvm_type = type_of::type_of(cx, type_in_box); - let content_type_metadata = get_or_create_type_metadata(cx, - type_in_box, - codemap::dummy_sp()); - - let box_metadata = create_boxed_type_metadata(cx, - content_llvm_type, - content_type_metadata, - codemap::dummy_sp()); - - create_pointer_type_metadata(cx, pointer_type, box_metadata) - } } fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 59d33fc086dd0..6c1d8b966e5a3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3731,17 +3731,18 @@ impl VariantInfo { }, ast::struct_variant_kind(ref struct_def) => { - let fields : &[@struct_field] = struct_def.fields; + let fields: &[@struct_field] = struct_def.fields; assert!(fields.len() > 0); let arg_tys = ty_fn_args(ctor_ty).map(|a| *a); let arg_names = do fields.map |field| { match field.node.kind { - named_field(ident, _visibility) => ident, + named_field(ident, _) => ident, unnamed_field => cx.sess.bug( "enum_variants: all fields in struct must have a name") - }}; + } + }; return VariantInfo { args: arg_tys, @@ -3904,7 +3905,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] { node: ast::item_enum(ref enum_definition, _), _ }, _) => { - let mut last_discriminant : Option = None; + let mut last_discriminant: Option = None; @enum_definition.variants.iter().transform(|variant| { let mut discriminant = match last_discriminant { @@ -3914,8 +3915,13 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] { match variant.node.disr_expr { Some(e) => match const_eval::eval_const_expr_partial(cx, e) { - Ok(const_eval::const_int(val)) => { discriminant = val as int; } - _ => {} + Ok(const_eval::const_int(val)) => discriminant = val as int, + Ok(_) => { + cx.sess.span_err(e.span, "expected signed integer constant"); + } + Err(ref err) => { + cx.sess.span_err(e.span, fmt!("expected constant: %s", (*err))); + } }, None => {} }; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 319d94bae7038..fa24c8c6d0983 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3138,9 +3138,9 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, -> ~[@ty::VariantInfo] { let rty = ty::node_id_to_type(ccx.tcx, id); - let mut variants : ~[@ty::VariantInfo] = ~[]; + let mut variants: ~[@ty::VariantInfo] = ~[]; let mut disr_vals: ~[int] = ~[]; - let mut prev_disr_val : Option = None; + let mut prev_disr_val: Option = None; for vs.iter().advance |v| { @@ -3163,7 +3163,7 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, // handle, so we may still get an internal compiler error match const_eval::eval_const_expr_partial(&ccx.tcx, e) { - Ok(const_eval::const_int(val)) => { current_disr_val = val as int; } + Ok(const_eval::const_int(val)) => current_disr_val = val as int, Ok(_) => { ccx.tcx.sess.span_err(e.span, "expected signed integer constant"); } diff --git a/src/test/debug-info/borrowed-basic.rs b/src/test/debug-info/borrowed-basic.rs index 8e46816d41c35..7610301f6f035 100644 --- a/src/test/debug-info/borrowed-basic.rs +++ b/src/test/debug-info/borrowed-basic.rs @@ -64,49 +64,49 @@ fn main() { let bool_val: bool = true; - let bool_ref : &bool = &bool_val; + let bool_ref: &bool = &bool_val; let int_val: int = -1; - let int_ref : &int = &int_val; + let int_ref: &int = &int_val; let char_val: char = 'a'; - let char_ref : &char = &char_val; + let char_ref: &char = &char_val; let i8_val: i8 = 68; - let i8_ref : &i8 = &i8_val; + let i8_ref: &i8 = &i8_val; let i16_val: i16 = -16; - let i16_ref : &i16 = &i16_val; + let i16_ref: &i16 = &i16_val; let i32_val: i32 = -32; - let i32_ref : &i32 = &i32_val; + let i32_ref: &i32 = &i32_val; let uint_val: i64 = -64; - let i64_ref : &i64 = &uint_val; + let i64_ref: &i64 = &uint_val; let uint_val: uint = 1; - let uint_ref : &uint = &uint_val; + let uint_ref: &uint = &uint_val; let u8_val: u8 = 100; - let u8_ref : &u8 = &u8_val; + let u8_ref: &u8 = &u8_val; let u16_val: u16 = 16; - let u16_ref : &u16 = &u16_val; + let u16_ref: &u16 = &u16_val; let u32_val: u32 = 32; - let u32_ref : &u32 = &u32_val; + let u32_ref: &u32 = &u32_val; let u64_val: u64 = 64; - let u64_ref : &u64 = &u64_val; + let u64_ref: &u64 = &u64_val; let float_val: float = 1.5; - let float_ref : &float = &float_val; + let float_ref: &float = &float_val; let f32_val: f32 = 2.5; - let f32_ref : &f32 = &f32_val; + let f32_ref: &f32 = &f32_val; let f64_val: f64 = 3.5; - let f64_ref : &f64 = &f64_val; + let f64_ref: &f64 = &f64_val; zzz(); } diff --git a/src/test/debug-info/borrowed-c-style-enum.rs b/src/test/debug-info/borrowed-c-style-enum.rs index 2ca4c5a4397f7..70c85258c7921 100644 --- a/src/test/debug-info/borrowed-c-style-enum.rs +++ b/src/test/debug-info/borrowed-c-style-enum.rs @@ -28,13 +28,13 @@ enum ABC { TheA, TheB, TheC } fn main() { let the_a = TheA; - let the_a_ref : &ABC = &the_a; + let the_a_ref: &ABC = &the_a; let the_b = TheB; - let the_b_ref : &ABC = &the_b; + let the_b_ref: &ABC = &the_b; let the_c = TheC; - let the_c_ref : &ABC = &the_c; + let the_c_ref: &ABC = &the_c; zzz(); } diff --git a/src/test/debug-info/borrowed-enum.rs b/src/test/debug-info/borrowed-enum.rs index 8c9a7799a293d..38aa9c3881000 100644 --- a/src/test/debug-info/borrowed-enum.rs +++ b/src/test/debug-info/borrowed-enum.rs @@ -44,17 +44,17 @@ fn main() { // 0b0111110001111100 = 31868 // 0b01111100 = 124 let the_a = TheA { x: 0, y: 8970181431921507452 }; - let the_a_ref : &ABC = &the_a; + let the_a_ref: &ABC = &the_a; // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 // 0b00010001000100010001000100010001 = 286331153 // 0b0001000100010001 = 4369 // 0b00010001 = 17 let the_b = TheB (0, 286331153, 286331153); - let the_b_ref : &ABC = &the_b; + let the_b_ref: &ABC = &the_b; let univariant = TheOnlyCase(4820353753753434); - let univariant_ref : &Univariant = &univariant; + let univariant_ref: &Univariant = &univariant; zzz(); } diff --git a/src/test/debug-info/borrowed-managed-basic.rs b/src/test/debug-info/borrowed-managed-basic.rs index e3951c94b6f86..9087bb36fa5d6 100644 --- a/src/test/debug-info/borrowed-managed-basic.rs +++ b/src/test/debug-info/borrowed-managed-basic.rs @@ -65,49 +65,49 @@ fn main() { let bool_box: @bool = @true; - let bool_ref : &bool = bool_box; + let bool_ref: &bool = bool_box; let int_box: @int = @-1; - let int_ref : &int = int_box; + let int_ref: &int = int_box; let char_box: @char = @'a'; - let char_ref : &char = char_box; + let char_ref: &char = char_box; let i8_box: @i8 = @68; - let i8_ref : &i8 = i8_box; + let i8_ref: &i8 = i8_box; let i16_box: @i16 = @-16; - let i16_ref : &i16 = i16_box; + let i16_ref: &i16 = i16_box; let i32_box: @i32 = @-32; - let i32_ref : &i32 = i32_box; + let i32_ref: &i32 = i32_box; let i64_box: @i64 = @-64; - let i64_ref : &i64 = i64_box; + let i64_ref: &i64 = i64_box; let uint_box: @uint = @1; - let uint_ref : &uint = uint_box; + let uint_ref: &uint = uint_box; let u8_box: @u8 = @100; - let u8_ref : &u8 = u8_box; + let u8_ref: &u8 = u8_box; let u16_box: @u16 = @16; - let u16_ref : &u16 = u16_box; + let u16_ref: &u16 = u16_box; let u32_box: @u32 = @32; - let u32_ref : &u32 = u32_box; + let u32_ref: &u32 = u32_box; let u64_box: @u64 = @64; - let u64_ref : &u64 = u64_box; + let u64_ref: &u64 = u64_box; let float_box: @float = @1.5; - let float_ref : &float = float_box; + let float_ref: &float = float_box; let f32_box: @f32 = @2.5; - let f32_ref : &f32 = f32_box; + let f32_ref: &f32 = f32_box; let f64_box: @f64 = @3.5; - let f64_ref : &f64 = f64_box; + let f64_ref: &f64 = f64_box; zzz(); } diff --git a/src/test/debug-info/borrowed-struct.rs b/src/test/debug-info/borrowed-struct.rs index 646109ff1c438..8b6eca3e37f79 100644 --- a/src/test/debug-info/borrowed-struct.rs +++ b/src/test/debug-info/borrowed-struct.rs @@ -54,20 +54,20 @@ struct SomeStruct { fn main() { let stack_val: SomeStruct = SomeStruct { x: 10, y: 23.5 }; - let stack_val_ref : &SomeStruct = &stack_val; - let stack_val_interior_ref_1 : &int = &stack_val.x; - let stack_val_interior_ref_2 : &f64 = &stack_val.y; - let ref_to_unnamed : &SomeStruct = &SomeStruct { x: 11, y: 24.5 }; + let stack_val_ref: &SomeStruct = &stack_val; + let stack_val_interior_ref_1: &int = &stack_val.x; + let stack_val_interior_ref_2: &f64 = &stack_val.y; + let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 }; let managed_val = @SomeStruct { x: 12, y: 25.5 }; - let managed_val_ref : &SomeStruct = managed_val; - let managed_val_interior_ref_1 : &int = &managed_val.x; - let managed_val_interior_ref_2 : &f64 = &managed_val.y; + let managed_val_ref: &SomeStruct = managed_val; + let managed_val_interior_ref_1: &int = &managed_val.x; + let managed_val_interior_ref_2: &f64 = &managed_val.y; let unique_val = ~SomeStruct { x: 13, y: 26.5 }; - let unique_val_ref : &SomeStruct = unique_val; - let unique_val_interior_ref_1 : &int = &unique_val.x; - let unique_val_interior_ref_2 : &f64 = &unique_val.y; + let unique_val_ref: &SomeStruct = unique_val; + let unique_val_interior_ref_1: &int = &unique_val.x; + let unique_val_interior_ref_2: &f64 = &unique_val.y; zzz(); } diff --git a/src/test/debug-info/borrowed-tuple.rs b/src/test/debug-info/borrowed-tuple.rs index 58c753bb30a92..da199941c8419 100644 --- a/src/test/debug-info/borrowed-tuple.rs +++ b/src/test/debug-info/borrowed-tuple.rs @@ -29,14 +29,14 @@ fn main() { let stack_val: (i16, f32) = (-14, -19f32); - let stack_val_ref : &(i16, f32) = &stack_val; - let ref_to_unnamed : &(i16, f32) = &(-15, -20f32); + let stack_val_ref: &(i16, f32) = &stack_val; + let ref_to_unnamed: &(i16, f32) = &(-15, -20f32); - let managed_val : @(i16, f32) = @(-16, -21f32); - let managed_val_ref : &(i16, f32) = managed_val; + let managed_val: @(i16, f32) = @(-16, -21f32); + let managed_val_ref: &(i16, f32) = managed_val; let unique_val: ~(i16, f32) = ~(-17, -22f32); - let unique_val_ref : &(i16, f32) = unique_val; + let unique_val_ref: &(i16, f32) = unique_val; zzz(); } diff --git a/src/test/debug-info/borrowed-unique-basic.rs b/src/test/debug-info/borrowed-unique-basic.rs index f9ce1728930ed..52f5a2cba1ebe 100644 --- a/src/test/debug-info/borrowed-unique-basic.rs +++ b/src/test/debug-info/borrowed-unique-basic.rs @@ -65,49 +65,49 @@ fn main() { let bool_box: ~bool = ~true; - let bool_ref : &bool = bool_box; + let bool_ref: &bool = bool_box; let int_box: ~int = ~-1; - let int_ref : &int = int_box; + let int_ref: &int = int_box; let char_box: ~char = ~'a'; - let char_ref : &char = char_box; + let char_ref: &char = char_box; let i8_box: ~i8 = ~68; - let i8_ref : &i8 = i8_box; + let i8_ref: &i8 = i8_box; let i16_box: ~i16 = ~-16; - let i16_ref : &i16 = i16_box; + let i16_ref: &i16 = i16_box; let i32_box: ~i32 = ~-32; - let i32_ref : &i32 = i32_box; + let i32_ref: &i32 = i32_box; let i64_box: ~i64 = ~-64; - let i64_ref : &i64 = i64_box; + let i64_ref: &i64 = i64_box; let uint_box: ~uint = ~1; - let uint_ref : &uint = uint_box; + let uint_ref: &uint = uint_box; let u8_box: ~u8 = ~100; - let u8_ref : &u8 = u8_box; + let u8_ref: &u8 = u8_box; let u16_box: ~u16 = ~16; - let u16_ref : &u16 = u16_box; + let u16_ref: &u16 = u16_box; let u32_box: ~u32 = ~32; - let u32_ref : &u32 = u32_box; + let u32_ref: &u32 = u32_box; let u64_box: ~u64 = ~64; - let u64_ref : &u64 = u64_box; + let u64_ref: &u64 = u64_box; let float_box: ~float = ~1.5; - let float_ref : &float = float_box; + let float_ref: &float = float_box; let f32_box: ~f32 = ~2.5; - let f32_ref : &f32 = f32_box; + let f32_ref: &f32 = f32_box; let f64_box: ~f64 = ~3.5; - let f64_ref : &f64 = f64_box; + let f64_ref: &f64 = f64_box; zzz(); } diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs index 4e10bf83bcb70..c63cffd7b74bb 100644 --- a/src/test/debug-info/box.rs +++ b/src/test/debug-info/box.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break _zzz diff --git a/src/test/debug-info/boxed-struct.rs b/src/test/debug-info/boxed-struct.rs index d06fcbbbab34b..86162f0fa04cd 100644 --- a/src/test/debug-info/boxed-struct.rs +++ b/src/test/debug-info/boxed-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/boxed-vec.rs b/src/test/debug-info/boxed-vec.rs index aeb081981c2d5..964ca689e8af1 100644 --- a/src/test/debug-info/boxed-vec.rs +++ b/src/test/debug-info/boxed-vec.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run @@ -25,8 +27,8 @@ fn main() { - let managed : @[i64] = @[7, 8, 9]; - let unique : ~[i64] = ~[10, 11, 12, 13]; + let managed: @[i64] = @[7, 8, 9]; + let unique: ~[i64] = ~[10, 11, 12, 13]; zzz(); } diff --git a/src/test/debug-info/c-style-enum-in-composite.rs b/src/test/debug-info/c-style-enum-in-composite.rs index 601d8ed441c13..47e433ea814ab 100644 --- a/src/test/debug-info/c-style-enum-in-composite.rs +++ b/src/test/debug-info/c-style-enum-in-composite.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/c-style-enum.rs b/src/test/debug-info/c-style-enum.rs index 3071cb2d326c7..d7cce4e6f3fb5 100644 --- a/src/test/debug-info/c-style-enum.rs +++ b/src/test/debug-info/c-style-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs index ad4774c06ffa7..207899fe3b510 100644 --- a/src/test/debug-info/destructured-local.rs +++ b/src/test/debug-info/destructured-local.rs @@ -22,7 +22,7 @@ // check:$2 = false fn main() { - let (a, b) : (int, bool) = (9898, false); + let (a, b): (int, bool) = (9898, false); zzz(); } diff --git a/src/test/debug-info/managed-box-within-unique.rs b/src/test/debug-info/managed-box-within-unique.rs index 411b6e0a7eece..3eb1c2ef01e55 100644 --- a/src/test/debug-info/managed-box-within-unique.rs +++ b/src/test/debug-info/managed-box-within-unique.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break zzz diff --git a/src/test/debug-info/nil-enum.rs b/src/test/debug-info/nil-enum.rs index 09f41ee9f4267..d3afd4b11f9cd 100644 --- a/src/test/debug-info/nil-enum.rs +++ b/src/test/debug-info/nil-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run @@ -28,8 +30,8 @@ enum AnotherNilEnum {} // 2. That gdb prints the string "{}" for empty structs (which may change some time) fn main() { unsafe { - let first : ANilEnum = std::cast::transmute(()); - let second : AnotherNilEnum = std::cast::transmute(()); + let first: ANilEnum = std::cast::transmute(()); + let second: AnotherNilEnum = std::cast::transmute(()); zzz(); } diff --git a/src/test/debug-info/option-like-enum.rs b/src/test/debug-info/option-like-enum.rs index c909d6f54eb8e..6d3b157d63e80 100644 --- a/src/test/debug-info/option-like-enum.rs +++ b/src/test/debug-info/option-like-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run @@ -49,8 +51,8 @@ enum NamedFields<'self> { fn main() { - let some : Option<&u32> = Some(unsafe { std::cast::transmute(0x12345678) }); - let none : Option<&u32> = None; + let some: Option<&u32> = Some(unsafe { std::cast::transmute(0x12345678) }); + let none: Option<&u32> = None; let full = Full(454545, unsafe { std::cast::transmute(0x87654321) }, 9988); diff --git a/src/test/debug-info/simple-tuple.rs b/src/test/debug-info/simple-tuple.rs index 84c736fab6b01..f45294221af16 100644 --- a/src/test/debug-info/simple-tuple.rs +++ b/src/test/debug-info/simple-tuple.rs @@ -35,15 +35,15 @@ fn main() { - let noPadding8 : (i8, u8) = (-100, 100); - let noPadding16 : (i16, i16, u16) = (0, 1, 2); - let noPadding32 : (i32, f32, u32) = (3, 4.5, 5); - let noPadding64 : (i64, f64, u64) = (6, 7.5, 8); + let noPadding8: (i8, u8) = (-100, 100); + let noPadding16: (i16, i16, u16) = (0, 1, 2); + let noPadding32: (i32, f32, u32) = (3, 4.5, 5); + let noPadding64: (i64, f64, u64) = (6, 7.5, 8); - let internalPadding1 : (i16, i32) = (9, 10); - let internalPadding2 : (i16, i32, u32, u64) = (11, 12, 13, 14); + let internalPadding1: (i16, i32) = (9, 10); + let internalPadding2: (i16, i32, u32, u64) = (11, 12, 13, 14); - let paddingAtEnd : (i32, i16) = (15, 16); + let paddingAtEnd: (i32, i16) = (15, 16); zzz(); } diff --git a/src/test/debug-info/struct-in-enum.rs b/src/test/debug-info/struct-in-enum.rs index 6d4a40e193fa5..1002266a1a985 100644 --- a/src/test/debug-info/struct-in-enum.rs +++ b/src/test/debug-info/struct-in-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print union on // debugger:break zzz diff --git a/src/test/debug-info/struct-style-enum.rs b/src/test/debug-info/struct-style-enum.rs index 972772b07d28a..61bbd2e215ff6 100644 --- a/src/test/debug-info/struct-style-enum.rs +++ b/src/test/debug-info/struct-style-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print union on // debugger:break zzz diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs index 87e61ebe373f2..ba28153ebafd5 100644 --- a/src/test/debug-info/struct-with-destructor.rs +++ b/src/test/debug-info/struct-with-destructor.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run @@ -29,13 +31,13 @@ struct NoDestructor { - x : i32, - y : i64 + x: i32, + y: i64 } struct WithDestructor { - x : i32, - y : i64 + x: i32, + y: i64 } impl Drop for WithDestructor { diff --git a/src/test/debug-info/tuple-in-tuple.rs b/src/test/debug-info/tuple-in-tuple.rs index 13f8719694e5f..9c6805dae67d3 100644 --- a/src/test/debug-info/tuple-in-tuple.rs +++ b/src/test/debug-info/tuple-in-tuple.rs @@ -34,15 +34,15 @@ // check:$7 = {{21, 22}, 23} fn main() { - let no_padding1 : ((u32, u32), u32, u32) = ((0, 1), 2, 3); - let no_padding2 : (u32, (u32, u32), u32) = (4, (5, 6), 7); - let no_padding3 : (u32, u32, (u32, u32)) = (8, 9, (10, 11)); + let no_padding1: ((u32, u32), u32, u32) = ((0, 1), 2, 3); + let no_padding2: (u32, (u32, u32), u32) = (4, (5, 6), 7); + let no_padding3: (u32, u32, (u32, u32)) = (8, 9, (10, 11)); - let internal_padding1 : (i16, (i32, i32)) = (12, (13, 14)); - let internal_padding2 : (i16, (i16, i32)) = (15, (16, 17)); + let internal_padding1: (i16, (i32, i32)) = (12, (13, 14)); + let internal_padding2: (i16, (i16, i32)) = (15, (16, 17)); - let padding_at_end1 : (i32, (i32, i16)) = (18, (19, 20)); - let padding_at_end2 : ((i32, i16), i32) = ((21, 22), 23); + let padding_at_end1: (i32, (i32, i16)) = (18, (19, 20)); + let padding_at_end2: ((i32, i16), i32) = ((21, 22), 23); zzz(); } diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs index 66e64a1e20aa9..ba1d02bb62a3c 100644 --- a/src/test/debug-info/tuple-style-enum.rs +++ b/src/test/debug-info/tuple-style-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print union on // debugger:break zzz diff --git a/src/test/debug-info/vec-slices.rs b/src/test/debug-info/vec-slices.rs index a7e47f992fc90..4691de0491721 100644 --- a/src/test/debug-info/vec-slices.rs +++ b/src/test/debug-info/vec-slices.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break zzz @@ -52,14 +54,14 @@ struct AStruct { } fn main() { - let empty : &[i64] = &[]; - let singleton : &[i64] = &[1]; - let multiple : &[i64] = &[2, 3, 4, 5]; + let empty: &[i64] = &[]; + let singleton: &[i64] = &[1]; + let multiple: &[i64] = &[2, 3, 4, 5]; let slice_of_slice = multiple.slice(1,3); - let padded_tuple : &[(i32, i16)] = &[(6, 7), (8, 9)]; + let padded_tuple: &[(i32, i16)] = &[(6, 7), (8, 9)]; - let padded_struct : &[AStruct] = &[ + let padded_struct: &[AStruct] = &[ AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 } ]; diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs index a9aca58fad7f7..57130b45eae30 100644 --- a/src/test/debug-info/vec.rs +++ b/src/test/debug-info/vec.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break zzz From e9baeab695ffb0483ce6bef872f5d85c636dd04a Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 16 Jul 2013 13:28:13 +0200 Subject: [PATCH 20/26] debuginfo: Adapted DI generation to new memory layout of unique vecs. --- src/librustc/middle/trans/debuginfo.rs | 52 +++++++++++++------ src/test/debug-info/boxed-vec.rs | 4 +- .../managed-pointer-within-unique-vec.rs | 37 +++++++++++++ ...ue.rs => managed-pointer-within-unique.rs} | 0 4 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 src/test/debug-info/managed-pointer-within-unique-vec.rs rename src/test/debug-info/{managed-box-within-unique.rs => managed-pointer-within-unique.rs} (100%) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index eea65a4c48add..2489f4f823516 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -581,7 +581,8 @@ fn tuple_metadata(cx: &mut CrateContext, fn enum_metadata(cx: &mut CrateContext, enum_type: ty::t, enum_def_id: ast::def_id, - substs: &ty::substs, + // _substs is only needed in the other version. Will go away with new snapshot. + _substs: &ty::substs, span: span) -> DIType { @@ -1017,10 +1018,10 @@ fn fixed_vec_metadata(cx: &mut CrateContext, }; } -fn boxed_vec_metadata(cx: &mut CrateContext, - element_type: ty::t, - span: span) - -> DICompositeType { +fn vec_metadata(cx: &mut CrateContext, + element_type: ty::t, + span: span) + -> DICompositeType { let element_type_metadata = type_metadata(cx, element_type, span); let element_llvm_type = type_of::type_of(cx, element_type); @@ -1045,7 +1046,7 @@ fn boxed_vec_metadata(cx: &mut CrateContext, // fill alloc elements let member_type_metadata = &[int_type_metadata, int_type_metadata, array_type_metadata]; - let vec_metadata = composite_type_metadata( + return composite_type_metadata( cx, vec_llvm_type, vec_type_name, @@ -1053,6 +1054,17 @@ fn boxed_vec_metadata(cx: &mut CrateContext, member_names, member_type_metadata, span); +} + +fn boxed_vec_metadata(cx: &mut CrateContext, + element_type: ty::t, + span: span) + -> DICompositeType { + + let element_llvm_type = type_of::type_of(cx, element_type); + let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type); + let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type)); + let vec_metadata = vec_metadata(cx, element_type, span); return boxed_type_metadata( cx, @@ -1197,10 +1209,13 @@ fn type_metadata(cx: &mut CrateContext, ty::vstore_fixed(len) => { fixed_vec_metadata(cx, i8_t, len + 1, span) }, - ty::vstore_uniq | + ty::vstore_uniq => { + let vec_metadata = vec_metadata(cx, i8_t, span); + pointer_type_metadata(cx, t, vec_metadata) + } ty::vstore_box => { - let box_metadata = boxed_vec_metadata(cx, i8_t, span); - pointer_type_metadata(cx, t, box_metadata) + let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, span); + pointer_type_metadata(cx, t, boxed_vec_metadata) } ty::vstore_slice(_region) => { vec_slice_metadata(cx, t, i8_t, span) @@ -1217,12 +1232,19 @@ fn type_metadata(cx: &mut CrateContext, match *vstore { ty::vstore_fixed(len) => { fixed_vec_metadata(cx, mt.ty, len, span) - }, - ty::vstore_uniq | - ty::vstore_box => { - let box_metadata = boxed_vec_metadata(cx, mt.ty, span); - pointer_type_metadata(cx, t, box_metadata) - }, + } + ty::vstore_uniq if ty::type_contents(cx.tcx, mt.ty).contains_managed() => { + let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span); + pointer_type_metadata(cx, t, boxed_vec_metadata) + } + ty::vstore_uniq => { + let vec_metadata = vec_metadata(cx, mt.ty, span); + pointer_type_metadata(cx, t, vec_metadata) + } + ty::vstore_box => { + let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span); + pointer_type_metadata(cx, t, boxed_vec_metadata) + } ty::vstore_slice(_) => { vec_slice_metadata(cx, t, mt.ty, span) } diff --git a/src/test/debug-info/boxed-vec.rs b/src/test/debug-info/boxed-vec.rs index 964ca689e8af1..8abead6519697 100644 --- a/src/test/debug-info/boxed-vec.rs +++ b/src/test/debug-info/boxed-vec.rs @@ -20,9 +20,9 @@ // debugger:print *((uint64_t[3]*)(managed->val.elements)) // check:$2 = {7, 8, 9} -// debugger:print unique->val.fill +// debugger:print unique->fill // check:$3 = 32 -// debugger:print *((uint64_t[4]*)(unique->val.elements)) +// debugger:print *((uint64_t[4]*)(unique->elements)) // check:$4 = {10, 11, 12, 13} fn main() { diff --git a/src/test/debug-info/managed-pointer-within-unique-vec.rs b/src/test/debug-info/managed-pointer-within-unique-vec.rs new file mode 100644 index 0000000000000..e42631599a9b9 --- /dev/null +++ b/src/test/debug-info/managed-pointer-within-unique-vec.rs @@ -0,0 +1,37 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249 + +// compile-flags:-Z extra-debug-info +// debugger:break zzz +// debugger:run +// debugger:finish + +// debugger:print unique->val.elements[0]->val +// check:$1 = 10 + +// debugger:print unique->val.elements[1]->val +// check:$2 = 11 + +// debugger:print unique->val.elements[2]->val +// check:$3 = 12 + +// debugger:print unique->val.elements[3]->val +// check:$4 = 13 + +fn main() { + + let unique: ~[@i64] = ~[@10, @11, @12, @13]; + + zzz(); +} + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/managed-box-within-unique.rs b/src/test/debug-info/managed-pointer-within-unique.rs similarity index 100% rename from src/test/debug-info/managed-box-within-unique.rs rename to src/test/debug-info/managed-pointer-within-unique.rs From a1c5c798c7b8d7b556144ed3ba286936fb8ba639 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 17 Jul 2013 10:18:02 +0200 Subject: [PATCH 21/26] debuginfo: Added some documenting comments to debuginfo.rs --- src/librustc/middle/trans/debuginfo.rs | 53 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 2489f4f823516..cb76d27b8b0d3 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -27,11 +27,18 @@ where possible. This will hopefully ease the adaption of this module to future L The public API of the module is a set of functions that will insert the correct metadata into the LLVM IR when called with the right parameters. The module is thus driven from an outside client with -functions like `debuginfo::create_local_var_metadata(bcx: block, local: @ast::local)`. +functions like `debuginfo::local_var_metadata(bcx: block, local: &ast::local)`. -Internally the module will try to reuse already created metadata by utilizing a cache. All private -state used by the module is stored within a DebugContext struct, which in turn is contained in the -CrateContext. +Internally the module will try to reuse already created metadata by utilizing a cache. The way to +get a shared metadata node when needed is thus to just call the corresponding function in this +module: + + let file_metadata = file_metadata(crate_context, path); + +The function will take care of probing the cache for an existing node for that exact file path. + +All private state used by the module is stored within a DebugContext struct, which in turn is +contained in the CrateContext. This file consists of three conceptual sections: @@ -149,7 +156,7 @@ pub fn create_local_var_metadata(bcx: block, local: @ast::local) -> DIVariable { let context = match bcx.parent { None => create_function_metadata(bcx.fcx), - Some(_) => block_metadata(bcx) + Some(_) => lexical_block_metadata(bcx) }; let var_metadata = do as_c_str(name) |name| { @@ -178,7 +185,7 @@ pub fn create_local_var_metadata(bcx: block, local: @ast::local) -> DIVariable { } }; - set_debug_location(cx, block_metadata(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb); llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); @@ -236,7 +243,7 @@ pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Optio }; let llptr = fcx.llargs.get_copy(&arg.id); - set_debug_location(cx, block_metadata(bcx), loc.line, loc.col.to_uint()); + set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( DIB(cx), llptr, var_metadata, bcx.llbb); @@ -259,7 +266,7 @@ pub fn update_source_pos(bcx: block, span: span) { } debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span)); let loc = span_start(bcx.ccx(), span); - set_debug_location(bcx.ccx(), block_metadata(bcx), loc.line, loc.col.to_uint()) + set_debug_location(bcx.ccx(), lexical_block_metadata(bcx), loc.line, loc.col.to_uint()) } /// Creates debug information for the given function. @@ -418,44 +425,50 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile { return file_metadata; } -fn block_metadata(bcx: block) -> DILexicalBlock { - let mut bcx = bcx; +/// Get or create the lexical block metadata node for the given LLVM basic block. +fn lexical_block_metadata(bcx: block) -> DILexicalBlock { let cx = bcx.ccx(); + let mut bcx = bcx; + // Search up the tree of basic blocks until we find one that knows the containing lexical block. while bcx.node_info.is_none() { match bcx.parent { - Some(b) => bcx = b, - None => fail!() + Some(b) => bcx = b, + None => cx.sess.bug("debuginfo: Could not find lexical block for LLVM basic block.") } } + let span = bcx.node_info.get().span; let id = bcx.node_info.get().id; + // Check whether we already have a cache entry for this node id match dbg_cx(cx).created_blocks.find(&id) { Some(block) => return *block, None => () } - debug!("block_metadata: %s", bcx.sess().codemap.span_to_str(span)); + debug!("lexical_block_metadata: %s", bcx.sess().codemap.span_to_str(span)); let parent = match bcx.parent { None => create_function_metadata(bcx.fcx), - Some(b) => block_metadata(b) + Some(b) => lexical_block_metadata(b) }; - let cx = bcx.ccx(); + let loc = span_start(cx, span); let file_metadata = file_metadata(cx, loc.file.name); - let block_metadata = unsafe { + let lexical_block_metadata = unsafe { llvm::LLVMDIBuilderCreateLexicalBlock( DIB(cx), - parent, file_metadata, - loc.line as c_uint, loc.col.to_uint() as c_uint) + parent, + file_metadata, + loc.line as c_uint, + loc.col.to_uint() as c_uint) }; - dbg_cx(cx).created_blocks.insert(id, block_metadata); + dbg_cx(cx).created_blocks.insert(id, lexical_block_metadata); - return block_metadata; + return lexical_block_metadata; } fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { From 72cf2ee1368d385fa13772fd70b7a9e748aaec6b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 11 Jul 2013 18:00:21 +0200 Subject: [PATCH 22/26] debuginfo: Implemented trait_method branch in create_function_metadata(). --- src/librustc/middle/trans/debuginfo.rs | 56 ++++++++++++++++---------- src/test/run-pass/issue-7712.rs | 27 +++++++++++++ 2 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 src/test/run-pass/issue-7712.rs diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index cb76d27b8b0d3..9684dbd6bf97a 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -280,30 +280,42 @@ pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram { let fnitem = cx.tcx.items.get_copy(&fcx.id); let (ident, ret_ty, id) = match fnitem { - ast_map::node_item(ref item, _) => { - match item.node { - ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => { - (item.ident, ty, item.id) - } - _ => fcx.ccx.sess.span_bug(item.span, - "create_function_metadata: item bound to non-function") + ast_map::node_item(ref item, _) => { + match item.node { + ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => { + (item.ident, ty, item.id) + } + _ => fcx.ccx.sess.span_bug(item.span, + "create_function_metadata: item bound to non-function") + } } - } - ast_map::node_method(@ast::method { decl: ast::fn_decl { output: ref ty, _ }, - id: id, ident: ident, _}, _, _) => { - (ident, ty, id) - } - ast_map::node_expr(ref expr) => { - match expr.node { - ast::expr_fn_block(ref decl, _) => { - let name = gensym_name("fn"); - (name, &decl.output, expr.id) - } - _ => fcx.ccx.sess.span_bug(expr.span, - "create_function_metadata: expected an expr_fn_block here") + ast_map::node_method(@ast::method { decl: ast::fn_decl { output: ref ty, _ }, + id: id, ident: ident, _}, _, _) => { + (ident, ty, id) } - } - _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node") + ast_map::node_expr(ref expr) => { + match expr.node { + ast::expr_fn_block(ref decl, _) => { + let name = gensym_name("fn"); + (name, &decl.output, expr.id) + } + _ => fcx.ccx.sess.span_bug(expr.span, + "create_function_metadata: expected an expr_fn_block here") + } + } + ast_map::node_trait_method( + @ast::provided( + @ast::method { + decl: ast::fn_decl { output: ref ty, _ }, + id: id, + ident: ident, + _} + ), + _def_id, + _path) => { + (ident, ty, id) + } + _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node") }; match dbg_cx(cx).created_functions.find(&id) { diff --git a/src/test/run-pass/issue-7712.rs b/src/test/run-pass/issue-7712.rs new file mode 100644 index 0000000000000..d4faae415d202 --- /dev/null +++ b/src/test/run-pass/issue-7712.rs @@ -0,0 +1,27 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z debug-info + +#[allow(default_methods)]; + +pub trait TraitWithDefaultMethod { + pub fn method(self) { + () + } +} + +struct MyStruct; + +impl TraitWithDefaultMethod for MyStruct { } + +fn main() { + MyStruct.method(); +} \ No newline at end of file From d8c27c3446582a318b35103e6ec3594c53f196b1 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 17 Jul 2013 17:51:33 +0200 Subject: [PATCH 23/26] debuginfo: Fixed issue 7712. --- src/librustc/middle/trans/debuginfo.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 9684dbd6bf97a..b4e168356b3b6 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -289,8 +289,15 @@ pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram { "create_function_metadata: item bound to non-function") } } - ast_map::node_method(@ast::method { decl: ast::fn_decl { output: ref ty, _ }, - id: id, ident: ident, _}, _, _) => { + ast_map::node_method( + @ast::method { + decl: ast::fn_decl { output: ref ty, _ }, + id: id, + ident: ident, + _ + }, + _, + _) => { (ident, ty, id) } ast_map::node_expr(ref expr) => { @@ -309,10 +316,10 @@ pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram { decl: ast::fn_decl { output: ref ty, _ }, id: id, ident: ident, - _} - ), - _def_id, - _path) => { + _ + }), + _, + _) => { (ident, ty, id) } _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node") From 6aa43c77d4eaf72e673f060ed07bce7f8fc5757d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 17 Jul 2013 18:46:53 +0200 Subject: [PATCH 24/26] debuginfo: Fixed some merge fallout. --- src/librustc/middle/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 6c1d8b966e5a3..662a64ea788c7 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3914,7 +3914,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] { }; match variant.node.disr_expr { - Some(e) => match const_eval::eval_const_expr_partial(cx, e) { + Some(e) => match const_eval::eval_const_expr_partial(&cx, e) { Ok(const_eval::const_int(val)) => discriminant = val as int, Ok(_) => { cx.sess.span_err(e.span, "expected signed integer constant"); From b52eb4a0ffbb5be156a0d71dc37f74c3f92e315e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 19 Jul 2013 09:38:36 +0200 Subject: [PATCH 25/26] debuginfo: Fixed some merge fallout --- src/librustc/middle/trans/debuginfo.rs | 4 ++-- src/librustc/middle/ty.rs | 2 +- src/rustllvm/rustllvm.def.in | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index b4e168356b3b6..0e75e4e85c2f2 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -1225,8 +1225,8 @@ fn type_metadata(cx: &mut CrateContext, debug!("type_metadata: %?", ty::get(t)); - let sty = copy ty::get(t).sty; - let type_metadata = match sty { + let sty = &ty::get(t).sty; + let type_metadata = match *sty { ty::ty_nil | ty::ty_bot | ty::ty_bool | diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 662a64ea788c7..9451900091f3f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3694,7 +3694,7 @@ fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option { // Enum information #[deriving(Clone)] -pub struct VariantInfo_ { +pub struct VariantInfo { args: ~[t], arg_names: Option<~[ast::ident]>, ctor_ty: t, diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index d5f03ac604b76..5b6c3ed2f52f9 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -608,3 +608,6 @@ LLVMDIBuilderCreateSubroutineType LLVMDIBuilderGetOrCreateArray LLVMDIBuilderInsertDeclareAtEnd LLVMDIBuilderInsertDeclareBefore +LLVMDIBuilderCreateEnumerator +LLVMDIBuilderCreateEnumerationType +LLVMDIBuilderCreateUnionType From a1303cc81565a019d59be28940a94caf0f9329bf Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Sat, 20 Jul 2013 10:47:24 +0200 Subject: [PATCH 26/26] debuginfo: Removed some test relying on data structure sizes hard to predict for all possible platforms and configurations. --- src/test/debug-info/packed-struct.rs | 14 ++-------- src/test/debug-info/struct-with-destructor.rs | 28 +++++++++++++------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/test/debug-info/packed-struct.rs b/src/test/debug-info/packed-struct.rs index 11c09cfceb57b..859166cb023a3 100644 --- a/src/test/debug-info/packed-struct.rs +++ b/src/test/debug-info/packed-struct.rs @@ -34,14 +34,6 @@ // debugger:print sizeof(packedInPacked) // check:$6 = 40 -// debugger:print sizeof(packedInUnpacked) -// check:$7 = 48 - -// debugger:print sizeof(unpackedInPacked) -// check:$8 = 58 - - - #[packed] struct Packed { x: i16, @@ -57,7 +49,7 @@ struct PackedInPacked { d: Packed } -// layout: aaaa bbbb bbbb bbbb bb.. .... cccc cccc dddd dddd dddd dd.. +// layout (64 bit): aaaa bbbb bbbb bbbb bb.. .... cccc cccc dddd dddd dddd dd.. struct PackedInUnpacked { a: i32, b: Packed, @@ -65,7 +57,7 @@ struct PackedInUnpacked { d: Packed } -// layout: xx.. yyyy zz.. .... wwww wwww +// layout (64 bit): xx.. yyyy zz.. .... wwww wwww struct Unpacked { x: i16, y: i32, @@ -73,7 +65,7 @@ struct Unpacked { w: i64 } -// layout: aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd +// layout (64 bit): aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd #[packed] struct UnpackedInPacked { a: i16, diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs index ba28153ebafd5..0719f64b2564f 100644 --- a/src/test/debug-info/struct-with-destructor.rs +++ b/src/test/debug-info/struct-with-destructor.rs @@ -26,10 +26,6 @@ // debugger:print nested // check:$4 = {a = {a = {x = 7890, y = 9870}}} -// debugger:print sizeof(nested) -// check:$5 = 32 - - struct NoDestructor { x: i32, y: i64 @@ -84,6 +80,8 @@ fn main() { // then the debugger will have an invalid offset for the field 'guard' and thus should not be // able to read its value correctly (dots are padding bytes, D is the boolean destructor flag): // + // 64 bit + // // NoDestructorGuarded = 0000....00000000FFFFFFFF // <--------------><------> // NoDestructor guard @@ -96,15 +94,29 @@ fn main() { // <----------------------><------> // How it actually is // WithDestructor guard // + // 32 bit + // + // NoDestructorGuarded = 000000000000FFFFFFFF + // <----------><------> + // NoDestructor guard + // + // + // withDestructorGuarded = 000000000000D...FFFFFFFF + // <----------><------> // How debug info says it is + // WithDestructor guard + // + // <--------------><------> // How it actually is + // WithDestructor guard + // let withDestructor = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }; - // expected layout = xxxx....yyyyyyyyD.......D... - // <--WithDestructor------> - // <-------NestedInner--------> - // <-------NestedOuter--------> + // expected layout (64 bit) = xxxx....yyyyyyyyD.......D... + // <--WithDestructor------> + // <-------NestedInner--------> + // <-------NestedOuter--------> let nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }; zzz();