Skip to content

Add debug info for boxes, vectors, and strings #5824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ impl get_insn_ctxt for fn_ctxt {
}
}

fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool {
match fcx.span {
None => true,
Some(span) => *span.lo != 0 || *span.hi != 0
}
}

pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec,
end: time::Timespec) {
let elapsed = 1000 * ((end.sec - start.sec) as int) +
Expand Down Expand Up @@ -1158,7 +1165,8 @@ pub fn trans_stmt(cx: block, s: ast::stmt) -> block {
ast::decl_local(ref locals) => {
for locals.each |local| {
bcx = init_local(bcx, *local);
if cx.sess().opts.extra_debuginfo {
if cx.sess().opts.extra_debuginfo
&& fcx_has_nonzero_span(bcx.fcx) {
debuginfo::create_local_var(bcx, *local);
}
}
Expand Down Expand Up @@ -1738,7 +1746,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,

fcx.llargs.insert(arg_id, local_mem(llarg));

if fcx.ccx.sess.opts.extra_debuginfo {
if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
}
}
Expand Down Expand Up @@ -1861,7 +1869,8 @@ pub fn trans_fn(ccx: @CrateContext,
trans_closure(ccx, path, decl, body, llfndecl, ty_self,
param_substs, id, impl_id,
|fcx| {
if ccx.sess.opts.extra_debuginfo {
if ccx.sess.opts.extra_debuginfo
&& fcx_has_nonzero_span(fcx) {
debuginfo::create_function(fcx);
}
},
Expand Down
188 changes: 156 additions & 32 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,8 @@ fn create_pointer_type(cx: @CrateContext, t: ty::t, span: span,
let fname = filename_from_span(cx, span);
let file_node = create_file(cx, fname);
//let cu_node = create_compile_unit(cx, fname);
let llnode = create_derived_type(tg, file_node.node, ~"", 0, size * 8,
let name = ty_to_str(cx.tcx, t);
let llnode = create_derived_type(tg, file_node.node, name, 0, size * 8,
align * 8, 0, pointee.node);
let mdval = @Metadata {
node: llnode,
Expand Down Expand Up @@ -542,33 +543,48 @@ fn create_tuple(cx: @CrateContext, t: ty::t, elements: &[ty::t], span: span)
return mdval;
}

fn create_boxed_type(cx: @CrateContext, outer: ty::t, _inner: ty::t,
// returns (void* type as a ValueRef, size in bytes, align in bytes)
fn voidptr() -> (ValueRef, int, int) {
let null = ptr::null();
let size = sys::size_of::<ValueRef>() as int;
let align = sys::min_align_of::<ValueRef>() as int;
let vp = create_derived_type(PointerTypeTag, null, ~"", 0,
size, align, 0, null);
return (vp, size, align);
}

fn create_boxed_type(cx: @CrateContext, contents: ty::t,
span: span, boxed: @Metadata<TyDescMetadata>)
-> @Metadata<TyDescMetadata> {
//let tg = StructureTypeTag;
/*let cache = cx.llmetadata;
match cached_metadata::<@Metadata<TyDescMetadata>>(
cache, tg, {|md| ty::hash_ty(outer) == ty::hash_ty(md.data.hash)}) {
cache, tg, {|md| ty::hash_ty(contents) == ty::hash_ty(md.data.hash)}) {
option::Some(md) { return md; }
option::None {}
}*/
let fname = filename_from_span(cx, span);
let file_node = create_file(cx, fname);
//let cu_node = create_compile_unit_metadata(cx, fname);
let uint_t = ty::mk_uint(cx.tcx);
let refcount_type = create_basic_type(cx, uint_t, span);
let scx = create_structure(file_node,
@/*bad*/ copy ty_to_str(cx.tcx, outer), 0);
let int_t = ty::mk_int(cx.tcx);
let refcount_type = create_basic_type(cx, int_t, span);
let name = ty_to_str(cx.tcx, contents);
let scx = create_structure(file_node, @fmt!("box<%s>", name), 0);
add_member(scx, ~"refcnt", 0, sys::size_of::<uint>() as int,
sys::min_align_of::<uint>() as int, refcount_type.node);
add_member(scx, ~"boxed", 0, 8, //XXX member_size_and_align(??)
8, //XXX just a guess
boxed.node);
// the tydesc and other pointers should be irrelevant to the
// debugger, so treat them as void* types
let (vp, vpsize, vpalign) = voidptr();
add_member(scx, ~"tydesc", 0, vpsize, vpalign, vp);
add_member(scx, ~"prev", 0, vpsize, vpalign, vp);
add_member(scx, ~"next", 0, vpsize, vpalign, vp);
let (size, align) = size_and_align_of(cx, contents);
add_member(scx, ~"boxed", 0, size, align, boxed.node);
let llnode = finish_structure(scx);
let mdval = @Metadata {
node: llnode,
data: TyDescMetadata {
hash: ty::type_id(outer)
hash: ty::type_id(contents)
}
};
//update_cache(cache, tg, tydesc_metadata(mdval));
Expand Down Expand Up @@ -606,33 +622,117 @@ fn create_composite_type(type_tag: int, name: &str, file: ValueRef,
return llmdnode(lldata);
}

fn create_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
vec_ty_span: codemap::span) -> @Metadata<TyDescMetadata> {
fn create_fixed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
len: int, span: span) -> @Metadata<TyDescMetadata> {
let t_md = create_ty(cx, elem_t, span);
let fname = filename_from_span(cx, span);
let file_node = create_file(cx, fname);
let (size, align) = size_and_align_of(cx, elem_t);
let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(len - 1)]);
let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
let array = create_composite_type(ArrayTypeTag, name, file_node.node, 0,
size * len, align, 0, Some(t_md.node),
Some(~[subrange]));
@Metadata {
node: array,
data: TyDescMetadata {
hash: ty::type_id(vec_t)
}
}
}

fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
vec_ty_span: codemap::span)
-> @Metadata<TyDescMetadata> {
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, vec_ty_span);
let scx = create_structure(file_node,
let vec_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);
add_member(scx, ~"fill", 0, sys::size_of::<libc::size_t>() as int,
add_member(vec_scx, ~"fill", 0, sys::size_of::<libc::size_t>() as int,
sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
add_member(scx, ~"alloc", 0, sys::size_of::<libc::size_t>() as int,
add_member(vec_scx, ~"alloc", 0, sys::size_of::<libc::size_t>() as int,
sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(0)]);
let (arr_size, arr_align) = size_and_align_of(cx, elem_t);
let data_ptr = create_composite_type(ArrayTypeTag, ~"", file_node.node, 0,
let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
let data_ptr = create_composite_type(ArrayTypeTag, name, file_node.node, 0,
arr_size, arr_align, 0,
Some(elem_ty_md.node),
Some(~[subrange]));
add_member(scx, ~"data", 0, 0, // clang says the size should be 0
add_member(vec_scx, ~"data", 0, 0, // clang says the size should be 0
sys::min_align_of::<u8>() as int, data_ptr);
let llnode = finish_structure(vec_scx);
let vec_md = @Metadata {
node: llnode,
data: TyDescMetadata {
hash: ty::type_id(vec_t)
}
};

let box_scx = create_structure(file_node, @fmt!("box<%s>", name), 0);
let int_t = ty::mk_int(cx.tcx);
let refcount_type = create_basic_type(cx, int_t, vec_ty_span);
add_member(box_scx, ~"refcnt", 0, sys::size_of::<uint>() as int,
sys::min_align_of::<uint>() as int, refcount_type.node);
let (vp, vpsize, vpalign) = voidptr();
add_member(box_scx, ~"tydesc", 0, vpsize, vpalign, vp);
add_member(box_scx, ~"prev", 0, vpsize, vpalign, vp);
add_member(box_scx, ~"next", 0, vpsize, vpalign, vp);
let size = 2 * sys::size_of::<int>() as int;
let align = sys::min_align_of::<int>() as int;
add_member(box_scx, ~"boxed", 0, size, align, vec_md.node);
let llnode = finish_structure(box_scx);
let mdval = @Metadata {
node: llnode,
data: TyDescMetadata {
hash: ty::type_id(elem_t)
}
};
return mdval;
}

fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span)
-> @Metadata<TyDescMetadata> {
let fname = filename_from_span(cx, span);
let file_node = create_file(cx, fname);
let elem_ty_md = create_ty(cx, elem_t, span);
let uint_type = create_basic_type(cx, ty::mk_uint(cx.tcx), span);
let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md);
let scx = create_structure(file_node, @ty_to_str(cx.tcx, vec_t), 0);
let (_, ptr_size, ptr_align) = voidptr();
add_member(scx, ~"vec", 0, ptr_size, ptr_align, elem_ptr.node);
add_member(scx, ~"length", 0, sys::size_of::<uint>() as int,
sys::min_align_of::<uint>() as int, uint_type.node);
let llnode = finish_structure(scx);
@Metadata {
let mdval = @Metadata {
node: llnode,
data: TyDescMetadata {
hash: ty::type_id(vec_t)
}
}
};
return mdval;
}

fn create_fn_ty(cx: @CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
span: span) -> @Metadata<TyDescMetadata> {
let fname = filename_from_span(cx, span);
let file_node = create_file(cx, fname);
let (vp, _, _) = voidptr();
let output_md = 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).node };
let members = ~[output_ptr_md.node, vp] + inputs_vals;
let llnode = create_composite_type(SubroutineTag, ~"", file_node.node,
0, 0, 0, 0, None, Some(members));
let mdval = @Metadata {
node: llnode,
data: TyDescMetadata {
hash: ty::type_id(fn_ty)
}
};
return mdval;
}

fn create_ty(cx: @CrateContext, t: ty::t, span: span)
Expand All @@ -649,20 +749,42 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span)
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(_vstore) => {
cx.sess.span_bug(span, ~"debuginfo for estr NYI")
ty::ty_estr(ref vstore) => {
let i8_t = ty::mk_i8(cx.tcx);
match *vstore {
ty::vstore_fixed(len) => {
create_fixed_vec(cx, t, i8_t, len as int + 1, span)
},
ty::vstore_uniq | ty::vstore_box => {
let box_md = create_boxed_vec(cx, t, i8_t, span);
create_pointer_type(cx, t, span, box_md)
}
ty::vstore_slice(_region) => {
create_vec_slice(cx, t, i8_t, span)
}
}
},
ty::ty_enum(_did, ref _substs) => {
cx.sess.span_bug(span, ~"debuginfo for enum NYI")
}
ty::ty_box(ref _mt) => {
cx.sess.span_bug(span, ~"debuginfo for box NYI")
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)
},
ty::ty_uniq(ref _mt) => {
cx.sess.span_bug(span, ~"debuginfo for uniq NYI")
},
ty::ty_evec(ref _mt, ref _vstore) => {
cx.sess.span_bug(span, ~"debuginfo for evec NYI")
ty::ty_evec(ref mt, ref vstore) => {
match *vstore {
ty::vstore_fixed(len) => {
create_fixed_vec(cx, t, mt.ty, len as int, span)
},
ty::vstore_uniq | ty::vstore_box => {
let box_md = create_boxed_vec(cx, t, mt.ty, span);
create_pointer_type(cx, t, span, box_md)
},
ty::vstore_slice(_region) => {
create_vec_slice(cx, t, mt.ty, span)
}
}
},
ty::ty_ptr(ref mt) => {
let pointee = create_ty(cx, mt.ty, span);
Expand All @@ -671,8 +793,10 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span)
ty::ty_rptr(ref _region, ref _mt) => {
cx.sess.span_bug(span, ~"debuginfo for rptr NYI")
},
ty::ty_bare_fn(ref _barefnty) => {
cx.sess.span_bug(span, ~"debuginfo for bare_fn NYI")
ty::ty_bare_fn(ref barefnty) => {
let inputs = do barefnty.sig.inputs.map |a| { a.ty };
let output = barefnty.sig.output;
create_fn_ty(cx, t, inputs, output, span)
},
ty::ty_closure(ref _closurety) => {
cx.sess.span_bug(span, ~"debuginfo for closure NYI")
Expand Down Expand Up @@ -822,7 +946,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
}

pub fn update_source_pos(cx: block, s: span) {
if !cx.sess().opts.debuginfo {
if !cx.sess().opts.debuginfo || (*s.lo == 0 && *s.hi == 0) {
return;
}
let cm = cx.sess().codemap;
Expand Down
32 changes: 32 additions & 0 deletions src/test/debug-info/box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// xfail-test

// compile-flags:-Z extra-debug-info
// debugger:set print pretty off
// debugger:break 29
// debugger:run
// debugger:print a->boxed
// check:$1 = 1
// debugger:print b->boxed
// check:$2 = {2, 3.5}
// debugger:print c->boxed
// check:$3 = 4
// debugger:print d->boxed
// check:$4 = false

fn main() {
let a = ~1;
let b = ~(2, 3.5);
let c = @4;
let d = @false;
let _z = 0;
}
32 changes: 32 additions & 0 deletions src/test/debug-info/vec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// xfail-test

// compile-flags:-Z extra-debug-info
// debugger:set print pretty off
// debugger:break 29
// debugger:run
// 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];
let _z = 0;
}