From c978025d0dc416524313fd0c5f0797d9940574d9 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Wed, 27 Feb 2013 13:35:56 -0500 Subject: [PATCH 1/5] Debuginfo revamp --- src/compiletest/runtest.rs | 9 + src/librustc/middle/trans/debuginfo.rs | 212 ++++++++++++-------- src/test/debug-info/basic-types.rs | 68 +++++++ src/test/debug-info/struct.rs | 9 +- src/test/debug-info/{simple.rs => tuple.rs} | 17 +- 5 files changed, 217 insertions(+), 98 deletions(-) create mode 100644 src/test/debug-info/basic-types.rs rename src/test/debug-info/{simple.rs => tuple.rs} (72%) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index e0db543250d..0f72f956fa0 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -225,6 +225,15 @@ fn make_typecheck_args(config: config, testfile: &Path) -> ProcArgs { } fn run_debuginfo_test(config: config, props: TestProps, testfile: &Path) { + // do not optimize debuginfo tests + let config = match config.rustcflags { + Some(flags) => config { + rustcflags: Some(str::replace(flags, ~"-O", ~"")), + .. config + }, + None => config + }; + // compile test file (it shoud have 'compile-flags:-g' in the header) let mut ProcRes = compile_test(config, props, testfile); if ProcRes.status != 0 { diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 02b68afff4a..8f186054903 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -356,7 +356,31 @@ fn create_basic_type(cx: @CrateContext, t: ty::t, span: span) option::None => () } - let (name, encoding) = (~"uint", DW_ATE_unsigned); + let (name, encoding) = match ty::get(t).sty { + ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned), + ty::ty_bool => (~"bool", DW_ATE_boolean), + ty::ty_int(int_ty) => match int_ty { + ast::ty_i => (~"int", DW_ATE_signed), + ast::ty_char => (~"char", DW_ATE_signed_char), + ast::ty_i8 => (~"i8", DW_ATE_signed), + ast::ty_i16 => (~"i16", DW_ATE_signed), + ast::ty_i32 => (~"i32", DW_ATE_signed), + ast::ty_i64 => (~"i64", DW_ATE_signed) + }, + ty::ty_uint(uint_ty) => match uint_ty { + ast::ty_u => (~"uint", DW_ATE_unsigned), + ast::ty_u8 => (~"u8", DW_ATE_unsigned), + ast::ty_u16 => (~"i16", DW_ATE_unsigned), + ast::ty_u32 => (~"u32", DW_ATE_unsigned), + ast::ty_u64 => (~"u64", DW_ATE_unsigned) + }, + ty::ty_float(float_ty) => match float_ty { + ast::ty_f => (~"float", DW_ATE_float), + 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") + }; let fname = filename_from_span(cx, span); let file_node = create_file(cx, fname); @@ -473,6 +497,53 @@ fn add_member(cx: @mut StructCtxt, cx.total_size += size * 8; } +fn create_struct(cx: @CrateContext, t: ty::t, fields: ~[ty::field], + span: span) -> @Metadata { + let fname = filename_from_span(cx, span); + let file_node = create_file(cx, fname); + let scx = create_structure(file_node, @ty_to_str(cx.tcx, t), + line_from_span(cx.sess.codemap, span) as int); + for fields.each |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); + add_member(scx, *cx.sess.str_of(field.ident), + line_from_span(cx.sess.codemap, span) as int, + size as int, align as int, ty_md.node); + } + let mdval = @Metadata { + node: finish_structure(scx), + data: TyDescMetadata { + hash: ty::type_id(t) + } + }; + return mdval; +} + +fn create_tuple(cx: @CrateContext, t: ty::t, elements: ~[ty::t], span: span) + -> @Metadata { + let fname = filename_from_span(cx, span); + let file_node = create_file(cx, fname); + let scx = create_structure(file_node, + cx.sess.str_of( + ((/*bad*/copy cx.dbg_cx).get().names) + (~"tuple")), + line_from_span(cx.sess.codemap, span) as int); + for elements.each |element| { + let ty_md = create_ty(cx, *element, span); + let (size, align) = size_and_align_of(cx, *element); + add_member(scx, ~"", line_from_span(cx.sess.codemap, span) as int, + size as int, align as int, ty_md.node); + } + let mdval = @Metadata { + node: finish_structure(scx), + data: TyDescMetadata { + hash: ty::type_id(t) + } + }; + return mdval; +} + fn create_boxed_type(cx: @CrateContext, outer: ty::t, _inner: ty::t, span: span, boxed: @Metadata) -> @Metadata { @@ -538,11 +609,10 @@ fn create_composite_type(type_tag: int, name: &str, file: ValueRef, } fn create_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, - vec_ty_span: codemap::span, elem_ty: @ast::Ty) - -> @Metadata { + vec_ty_span: codemap::span) -> @Metadata { let fname = filename_from_span(cx, vec_ty_span); let file_node = create_file(cx, fname); - let elem_ty_md = create_ty(cx, elem_t, elem_ty); + let elem_ty_md = create_ty(cx, elem_t, vec_ty_span); let scx = create_structure(file_node, @/*bad*/ copy ty_to_str(cx.tcx, vec_t), 0); let size_t_type = create_basic_type(cx, ty::mk_uint(cx.tcx), vec_ty_span); @@ -567,8 +637,9 @@ fn create_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, } } -fn create_ty(_cx: @CrateContext, _t: ty::t, _ty: @ast::Ty) +fn create_ty(cx: @CrateContext, t: ty::t, span: span) -> @Metadata { + debug!("create_ty: %?", ty::get(t)); /*let cache = get_cache(cx); match cached_metadata::<@Metadata>( cache, tg, {|md| t == md.data.hash}) { @@ -576,85 +647,50 @@ fn create_ty(_cx: @CrateContext, _t: ty::t, _ty: @ast::Ty) option::None {} }*/ - /* FIXME (#2012): disabled this code as part of the patch that moves - * recognition of named builtin types into resolve. I tried to fix - * it, but it seems to already be broken -- it's only called when - * --xg is given, and compiling with --xg fails on trivial programs. - * - * Generating an ast::ty from a ty::t seems like it should not be - * needed. It is only done to track spans, but you will not get the - * right spans anyway -- types tend to refer to stuff defined - * elsewhere, not be self-contained. - */ - - fail!(); - /* - fn t_to_ty(cx: CrateContext, t: ty::t, span: span) -> @ast::ty { - let ty = match ty::get(t).struct { - ty::ty_nil { ast::ty_nil } - ty::ty_bot { ast::ty_bot } - ty::ty_bool { ast::ty_bool } - ty::ty_int(t) { ast::ty_int(t) } - ty::ty_float(t) { ast::ty_float(t) } - ty::ty_uint(t) { ast::ty_uint(t) } - ty::ty_box(mt) { ast::ty_box({ty: t_to_ty(cx, mt.ty, span), - mutbl: mt.mutbl}) } - ty::ty_uniq(mt) { ast::ty_uniq({ty: t_to_ty(cx, mt.ty, span), - mutbl: mt.mutbl}) } - ty::ty_vec(mt) { ast::ty_vec({ty: t_to_ty(cx, mt.ty, span), - mutbl: mt.mutbl}) } - _ { - cx.sess.span_bug(span, "t_to_ty: Can't handle this type"); - } - }; - return @{node: ty, span: span}; - } - - match ty.node { - ast::ty_box(mt) { - let inner_t = match ty::get(t).struct { - ty::ty_box(boxed) { boxed.ty } - _ { cx.sess.span_bug(ty.span, "t_to_ty was incoherent"); } - }; - let md = create_ty(cx, inner_t, mt.ty); - let box = create_boxed_type(cx, t, inner_t, ty.span, md); - return create_pointer_type(cx, t, ty.span, box); - } - - ast::ty_uniq(mt) { - let inner_t = match ty::get(t).struct { - ty::ty_uniq(boxed) { boxed.ty } - // Hoping we'll have a way to eliminate this check soon. - _ { cx.sess.span_bug(ty.span, "t_to_ty was incoherent"); } - }; - let md = create_ty(cx, inner_t, mt.ty); - return create_pointer_type(cx, t, ty.span, md); - } - - ast::ty_infer { - let inferred = t_to_ty(cx, t, ty.span); - return create_ty(cx, t, inferred); - } - - ast::ty_vec(mt) { - let inner_t = ty::sequence_element_type(cx.tcx, t); - let inner_ast_t = t_to_ty(cx, inner_t, mt.ty.span); - let v = create_vec(cx, t, inner_t, ty.span, inner_ast_t); - return create_pointer_type(cx, t, ty.span, v); - } - - ast::ty_path(_, id) { - match cx.tcx.def_map.get(id) { - ast::def_prim_ty(pty) { - return create_basic_type(cx, t, pty, ty.span); - } - _ {} + let sty = copy ty::get(t).sty; + match copy 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(_vstore) => { + cx.sess.span_bug(span, ~"debuginfo for estr NYI") + }, + ty::ty_enum(_did, _substs) => { + cx.sess.span_bug(span, ~"debuginfo for enum NYI") } - } - - _ {} - }; - */ + ty::ty_box(_mt) => { + cx.sess.span_bug(span, ~"debuginfo for box NYI") + }, + ty::ty_uniq(_mt) => { + cx.sess.span_bug(span, ~"debuginfo for uniq NYI") + }, + ty::ty_evec(_mt, _vstore) => { + cx.sess.span_bug(span, ~"debuginfo for evec NYI") + }, + ty::ty_ptr(mt) => { + let pointee = create_ty(cx, mt.ty, span); + create_pointer_type(cx, t, span, pointee) + }, + ty::ty_rptr(_region, _mt) => { + cx.sess.span_bug(span, ~"debuginfo for rptr NYI") + }, + ty::ty_bare_fn(_barefnty) => { + cx.sess.span_bug(span, ~"debuginfo for bare_fn NYI") + }, + ty::ty_closure(_closurety) => { + cx.sess.span_bug(span, ~"debuginfo for closure NYI") + }, + ty::ty_trait(_did, _substs, _vstore) => { + cx.sess.span_bug(span, ~"debuginfo for trait NYI") + }, + ty::ty_struct(did, substs) => { + let fields = ty::struct_fields(cx.tcx, did, &substs); + create_struct(cx, t, fields, span) + }, + ty::ty_tup(elements) => { + create_tuple(cx, t, elements, span) + }, + _ => cx.sess.bug(~"debuginfo: unexpected type in create_ty") + } } fn filename_from_span(cx: @CrateContext, sp: codemap::span) -> ~str { @@ -693,7 +729,7 @@ pub fn create_local_var(bcx: block, local: @ast::local) }; let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); let ty = node_id_type(bcx, local.node.id); - let tymd = create_ty(cx, ty, local.node.ty); + let tymd = create_ty(cx, ty, local.node.ty.span); let filemd = create_file(cx, /*bad*/copy loc.file.name); let context = match bcx.parent { None => create_function(bcx.fcx).node, @@ -743,8 +779,11 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span) } let loc = cx.sess.codemap.lookup_char_pos(sp.lo); + if loc.file.name == ~"" { + return None; + } let ty = node_id_type(bcx, arg.id); - let tymd = create_ty(cx, ty, arg.ty); + let tymd = create_ty(cx, ty, arg.ty.span); let filemd = create_file(cx, /*bad*/copy loc.file.name); let context = create_function(bcx.fcx); @@ -856,7 +895,8 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { let ty_node = if cx.sess.opts.extra_debuginfo { match ret_ty.node { ast::ty_nil => llnull(), - _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty).node + _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), + ret_ty.span).node } } else { llnull() diff --git a/src/test/debug-info/basic-types.rs b/src/test/debug-info/basic-types.rs new file mode 100644 index 00000000000..2441b35bc32 --- /dev/null +++ b/src/test/debug-info/basic-types.rs @@ -0,0 +1,68 @@ +// 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. + +// 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 +// its numerical value. + +// compile-flags:-Z extra-debug-info +// debugger:break 67 +// debugger:run +// debugger:print b +// check:$1 = false +// debugger:print i +// check:$2 = -1 +// debugger:print c +// check:$3 = 97 +// debugger:print i8 +// check:$4 = 68 'D' +// debugger:print i16 +// check:$5 = -16 +// debugger:print i32 +// check:$6 = -32 +// debugger:print i64 +// check:$7 = -64 +// debugger:print u +// check:$8 = 1 +// debugger:print u8 +// check:$9 = 100 'd' +// debugger:print u16 +// check:$10 = 16 +// debugger:print u32 +// check:$11 = 32 +// debugger:print u64 +// check:$12 = 64 +// debugger:print f +// check:$13 = 1.5 +// debugger:print f32 +// check:$14 = 2.5 +// debugger:print f64 +// check:$15 = 3.5 + +fn main() { + let b: bool = false; + let i: int = -1; + let c: char = 'a'; + let i8: i8 = 68; + let i16: i16 = -16; + let i32: i32 = -32; + let i64: i64 = -64; + let u: uint = 1; + let u8: u8 = 100; + let u16: u16 = 16; + let u32: u32 = 32; + let u64: u64 = 64; + let f: float = 1.5; + let f32: f32 = 2.5; + let f64: f64 = 3.5; + let _z = (); +} diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/struct.rs index b3132914477..d376bed76b7 100644 --- a/src/test/debug-info/struct.rs +++ b/src/test/debug-info/struct.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test -// compile-flags:-g -// debugger:break 32 +// compile-flags:-Z extra-debug-info +// debugger:break 31 // debugger:run // debugger:print pair // check:$1 = { // check:x = 1, -// check:y = 2, +// check:y = 2 // check:} // debugger:print pair.x // check:$2 = 1 @@ -29,5 +28,5 @@ struct Pair { fn main() { let pair = Pair { x: 1, y: 2 }; - debug!("x = %d, y = %d", pair.x, pair.y); + let _z = (); } diff --git a/src/test/debug-info/simple.rs b/src/test/debug-info/tuple.rs similarity index 72% rename from src/test/debug-info/simple.rs rename to src/test/debug-info/tuple.rs index 51bb177601a..5bceb9916ed 100644 --- a/src/test/debug-info/simple.rs +++ b/src/test/debug-info/tuple.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test -// compile-flags:-g -// debugger:break 20 +// compile-flags:-Z extra-debug-info +// debugger:break 23 // debugger:run -// debugger:print x -// check:$1 = 42 +// debugger:print t +// check:$1 = { +// check:4, +// check:5.5, +// check:true +// check:} fn main() { - let x = 42; - debug!("The answer is %d", x); + let t = (4, 5.5, true); + let _z = (); } From c913eff51def7f65474f27a032b5ba4c71f4ce90 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Thu, 28 Feb 2013 13:39:54 -0500 Subject: [PATCH 2/5] Disable struct value printing in debug info tests This is due to the way different versions of gdb print out structs: older versions have them always spread out with fields on different lines, while newer versions will compactly print them on one line. This makes it hard for the output checker to verify the expected output. --- src/test/debug-info/struct.rs | 11 +++-------- src/test/debug-info/tuple.rs | 1 + 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/struct.rs index d376bed76b7..4e12c0f940f 100644 --- a/src/test/debug-info/struct.rs +++ b/src/test/debug-info/struct.rs @@ -9,17 +9,12 @@ // except according to those terms. // compile-flags:-Z extra-debug-info -// debugger:break 31 +// debugger:break 26 // debugger:run -// debugger:print pair -// check:$1 = { -// check:x = 1, -// check:y = 2 -// check:} // debugger:print pair.x -// check:$2 = 1 +// check:$1 = 1 // debugger:print pair.y -// check:$3 = 2 +// check:$2 = 2 struct Pair { x: int, diff --git a/src/test/debug-info/tuple.rs b/src/test/debug-info/tuple.rs index 5bceb9916ed..e93e3ba3cec 100644 --- a/src/test/debug-info/tuple.rs +++ b/src/test/debug-info/tuple.rs @@ -8,6 +8,7 @@ // 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 23 // debugger:run From f1928d8e2c52cef8426a4c438fc050180a96edb6 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Thu, 28 Feb 2013 14:42:26 -0500 Subject: [PATCH 3/5] Re-enable struct value printing in debug info tests with gdb pretty printing off --- src/test/debug-info/struct.rs | 9 ++++++--- src/test/debug-info/tuple.rs | 10 +++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/struct.rs index 4e12c0f940f..30f4b657c4e 100644 --- a/src/test/debug-info/struct.rs +++ b/src/test/debug-info/struct.rs @@ -9,12 +9,15 @@ // except according to those terms. // compile-flags:-Z extra-debug-info -// debugger:break 26 +// debugger:set print pretty off +// debugger:break 29 // debugger:run +// debugger:print pair +// check:$1 = {x = 1, y = 2} // debugger:print pair.x -// check:$1 = 1 +// check:$2 = 1 // debugger:print pair.y -// check:$2 = 2 +// check:$3 = 2 struct Pair { x: int, diff --git a/src/test/debug-info/tuple.rs b/src/test/debug-info/tuple.rs index e93e3ba3cec..a2cdc689fad 100644 --- a/src/test/debug-info/tuple.rs +++ b/src/test/debug-info/tuple.rs @@ -8,16 +8,12 @@ // 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 23 +// debugger:set print pretty off +// debugger:break 20 // debugger:run // debugger:print t -// check:$1 = { -// check:4, -// check:5.5, -// check:true -// check:} +// check:$1 = {4, 5.5, true} fn main() { let t = (4, 5.5, true); From 61524251800ba5408166b45ef640f87da965dd73 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Fri, 1 Mar 2013 13:34:12 -0500 Subject: [PATCH 4/5] More descriptive error messages for debug info tests --- src/compiletest/runtest.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 0f72f956fa0..a52075cba12 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -276,8 +276,8 @@ fn debugger() -> ~str { ~"gdb" } } } if i != num_check_lines { - fatal(fmt!("line not found in debugger output: %s", - props.check_lines[i])); + fatal_ProcRes(fmt!("line not found in debugger output: %s" + props.check_lines[i]), ProcRes); } } } From 3976e56bfe58c38f4413ef25677edbc2a375b384 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 12 Mar 2013 11:58:50 -0700 Subject: [PATCH 5/5] Disable debuginfo tests on mac since gdb requires root --- mk/tests.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mk/tests.mk b/mk/tests.mk index 549741ddd65..33a828d6e67 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -386,6 +386,10 @@ ifeq ($(CFG_GDB),) CTEST_DISABLE_debuginfo = "no gdb found" endif +ifeq ($(CFG_OSTYPE),apple-darwin) +CTEST_DISABLE_debuginfo = "gdb on darwing needs root" +endif + define DEF_CTEST_VARS # All the per-stage build rules you might want to call from the