diff --git a/mk/tests.mk b/mk/tests.mk index 549741ddd65fe..33a828d6e6785 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 diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index e0db543250d66..a52075cba1238 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -225,6 +225,15 @@ actual:\n\ } 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 { @@ -267,8 +276,8 @@ fn run_debuginfo_test(config: config, props: TestProps, testfile: &Path) { } } 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); } } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 02b68afff4a82..8f18605490376 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 0000000000000..2441b35bc320b --- /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 b313291447794..30f4b657c4e35 100644 --- a/src/test/debug-info/struct.rs +++ b/src/test/debug-info/struct.rs @@ -8,15 +8,12 @@ // 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:set print pretty off +// debugger:break 29 // debugger:run // debugger:print pair -// check:$1 = { -// check:x = 1, -// check:y = 2, -// check:} +// check:$1 = {x = 1, y = 2} // debugger:print pair.x // check:$2 = 1 // debugger:print pair.y @@ -29,5 +26,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 75% rename from src/test/debug-info/simple.rs rename to src/test/debug-info/tuple.rs index 51bb177601ae1..a2cdc689fad47 100644 --- a/src/test/debug-info/simple.rs +++ b/src/test/debug-info/tuple.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test -// compile-flags:-g +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off // debugger:break 20 // debugger:run -// debugger:print x -// check:$1 = 42 +// debugger:print t +// check:$1 = {4, 5.5, true} fn main() { - let x = 42; - debug!("The answer is %d", x); + let t = (4, 5.5, true); + let _z = (); }