Skip to content

Commit 7d250d3

Browse files
committed
auto merge of #5824 : bleibig/rust/debuginfo, r=brson
This adds debugging symbol generation for boxes, bare functions, vectors, and strings, along with a tests for boxes and vectors. Note that gdb will see them as their actual compiled representation with the refcount, tydesc, etc. fields, so if `b` refers to box, `b->boxed` will refer to its value. Also, since you seem to use the [C struct hack](http://c-faq.com/struct/structhack.html) for dynamic vectors, you won't be able to print out the whole vector at once, only one element at a time by indexing specific elements.
2 parents 10e6869 + d2718e6 commit 7d250d3

File tree

4 files changed

+232
-35
lines changed

4 files changed

+232
-35
lines changed

src/librustc/middle/trans/base.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ impl get_insn_ctxt for fn_ctxt {
129129
}
130130
}
131131

132+
fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool {
133+
match fcx.span {
134+
None => true,
135+
Some(span) => *span.lo != 0 || *span.hi != 0
136+
}
137+
}
138+
132139
pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec,
133140
end: time::Timespec) {
134141
let elapsed = 1000 * ((end.sec - start.sec) as int) +
@@ -1150,7 +1157,8 @@ pub fn trans_stmt(cx: block, s: ast::stmt) -> block {
11501157
ast::decl_local(ref locals) => {
11511158
for locals.each |local| {
11521159
bcx = init_local(bcx, *local);
1153-
if cx.sess().opts.extra_debuginfo {
1160+
if cx.sess().opts.extra_debuginfo
1161+
&& fcx_has_nonzero_span(bcx.fcx) {
11541162
debuginfo::create_local_var(bcx, *local);
11551163
}
11561164
}
@@ -1730,7 +1738,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
17301738
17311739
fcx.llargs.insert(arg_id, local_mem(llarg));
17321740
1733-
if fcx.ccx.sess.opts.extra_debuginfo {
1741+
if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
17341742
debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
17351743
}
17361744
}
@@ -1853,7 +1861,8 @@ pub fn trans_fn(ccx: @CrateContext,
18531861
trans_closure(ccx, path, decl, body, llfndecl, ty_self,
18541862
param_substs, id, impl_id,
18551863
|fcx| {
1856-
if ccx.sess.opts.extra_debuginfo {
1864+
if ccx.sess.opts.extra_debuginfo
1865+
&& fcx_has_nonzero_span(fcx) {
18571866
debuginfo::create_function(fcx);
18581867
}
18591868
},

src/librustc/middle/trans/debuginfo.rs

+156-32
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,8 @@ fn create_pointer_type(cx: @CrateContext, t: ty::t, span: span,
414414
let fname = filename_from_span(cx, span);
415415
let file_node = create_file(cx, fname);
416416
//let cu_node = create_compile_unit(cx, fname);
417-
let llnode = create_derived_type(tg, file_node.node, ~"", 0, size * 8,
417+
let name = ty_to_str(cx.tcx, t);
418+
let llnode = create_derived_type(tg, file_node.node, name, 0, size * 8,
418419
align * 8, 0, pointee.node);
419420
let mdval = @Metadata {
420421
node: llnode,
@@ -536,33 +537,48 @@ fn create_tuple(cx: @CrateContext, t: ty::t, elements: &[ty::t], span: span)
536537
return mdval;
537538
}
538539

539-
fn create_boxed_type(cx: @CrateContext, outer: ty::t, _inner: ty::t,
540+
// returns (void* type as a ValueRef, size in bytes, align in bytes)
541+
fn voidptr() -> (ValueRef, int, int) {
542+
let null = ptr::null();
543+
let size = sys::size_of::<ValueRef>() as int;
544+
let align = sys::min_align_of::<ValueRef>() as int;
545+
let vp = create_derived_type(PointerTypeTag, null, ~"", 0,
546+
size, align, 0, null);
547+
return (vp, size, align);
548+
}
549+
550+
fn create_boxed_type(cx: @CrateContext, contents: ty::t,
540551
span: span, boxed: @Metadata<TyDescMetadata>)
541552
-> @Metadata<TyDescMetadata> {
542553
//let tg = StructureTypeTag;
543554
/*let cache = cx.llmetadata;
544555
match cached_metadata::<@Metadata<TyDescMetadata>>(
545-
cache, tg, {|md| ty::hash_ty(outer) == ty::hash_ty(md.data.hash)}) {
556+
cache, tg, {|md| ty::hash_ty(contents) == ty::hash_ty(md.data.hash)}) {
546557
option::Some(md) { return md; }
547558
option::None {}
548559
}*/
549560
let fname = filename_from_span(cx, span);
550561
let file_node = create_file(cx, fname);
551562
//let cu_node = create_compile_unit_metadata(cx, fname);
552-
let uint_t = ty::mk_uint(cx.tcx);
553-
let refcount_type = create_basic_type(cx, uint_t, span);
554-
let scx = create_structure(file_node,
555-
@/*bad*/ copy ty_to_str(cx.tcx, outer), 0);
563+
let int_t = ty::mk_int(cx.tcx);
564+
let refcount_type = create_basic_type(cx, int_t, span);
565+
let name = ty_to_str(cx.tcx, contents);
566+
let scx = create_structure(file_node, @fmt!("box<%s>", name), 0);
556567
add_member(scx, ~"refcnt", 0, sys::size_of::<uint>() as int,
557568
sys::min_align_of::<uint>() as int, refcount_type.node);
558-
add_member(scx, ~"boxed", 0, 8, //XXX member_size_and_align(??)
559-
8, //XXX just a guess
560-
boxed.node);
569+
// the tydesc and other pointers should be irrelevant to the
570+
// debugger, so treat them as void* types
571+
let (vp, vpsize, vpalign) = voidptr();
572+
add_member(scx, ~"tydesc", 0, vpsize, vpalign, vp);
573+
add_member(scx, ~"prev", 0, vpsize, vpalign, vp);
574+
add_member(scx, ~"next", 0, vpsize, vpalign, vp);
575+
let (size, align) = size_and_align_of(cx, contents);
576+
add_member(scx, ~"boxed", 0, size, align, boxed.node);
561577
let llnode = finish_structure(scx);
562578
let mdval = @Metadata {
563579
node: llnode,
564580
data: TyDescMetadata {
565-
hash: ty::type_id(outer)
581+
hash: ty::type_id(contents)
566582
}
567583
};
568584
//update_cache(cache, tg, tydesc_metadata(mdval));
@@ -600,33 +616,117 @@ fn create_composite_type(type_tag: int, name: &str, file: ValueRef,
600616
return llmdnode(lldata);
601617
}
602618

603-
fn create_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
604-
vec_ty_span: codemap::span) -> @Metadata<TyDescMetadata> {
619+
fn create_fixed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
620+
len: int, span: span) -> @Metadata<TyDescMetadata> {
621+
let t_md = create_ty(cx, elem_t, span);
622+
let fname = filename_from_span(cx, span);
623+
let file_node = create_file(cx, fname);
624+
let (size, align) = size_and_align_of(cx, elem_t);
625+
let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(len - 1)]);
626+
let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
627+
let array = create_composite_type(ArrayTypeTag, name, file_node.node, 0,
628+
size * len, align, 0, Some(t_md.node),
629+
Some(~[subrange]));
630+
@Metadata {
631+
node: array,
632+
data: TyDescMetadata {
633+
hash: ty::type_id(vec_t)
634+
}
635+
}
636+
}
637+
638+
fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
639+
vec_ty_span: codemap::span)
640+
-> @Metadata<TyDescMetadata> {
605641
let fname = filename_from_span(cx, vec_ty_span);
606642
let file_node = create_file(cx, fname);
607643
let elem_ty_md = create_ty(cx, elem_t, vec_ty_span);
608-
let scx = create_structure(file_node,
644+
let vec_scx = create_structure(file_node,
609645
@/*bad*/ copy ty_to_str(cx.tcx, vec_t), 0);
610646
let size_t_type = create_basic_type(cx, ty::mk_uint(cx.tcx), vec_ty_span);
611-
add_member(scx, ~"fill", 0, sys::size_of::<libc::size_t>() as int,
647+
add_member(vec_scx, ~"fill", 0, sys::size_of::<libc::size_t>() as int,
612648
sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
613-
add_member(scx, ~"alloc", 0, sys::size_of::<libc::size_t>() as int,
649+
add_member(vec_scx, ~"alloc", 0, sys::size_of::<libc::size_t>() as int,
614650
sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
615651
let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(0)]);
616652
let (arr_size, arr_align) = size_and_align_of(cx, elem_t);
617-
let data_ptr = create_composite_type(ArrayTypeTag, ~"", file_node.node, 0,
653+
let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
654+
let data_ptr = create_composite_type(ArrayTypeTag, name, file_node.node, 0,
618655
arr_size, arr_align, 0,
619656
Some(elem_ty_md.node),
620657
Some(~[subrange]));
621-
add_member(scx, ~"data", 0, 0, // clang says the size should be 0
658+
add_member(vec_scx, ~"data", 0, 0, // clang says the size should be 0
622659
sys::min_align_of::<u8>() as int, data_ptr);
660+
let llnode = finish_structure(vec_scx);
661+
let vec_md = @Metadata {
662+
node: llnode,
663+
data: TyDescMetadata {
664+
hash: ty::type_id(vec_t)
665+
}
666+
};
667+
668+
let box_scx = create_structure(file_node, @fmt!("box<%s>", name), 0);
669+
let int_t = ty::mk_int(cx.tcx);
670+
let refcount_type = create_basic_type(cx, int_t, vec_ty_span);
671+
add_member(box_scx, ~"refcnt", 0, sys::size_of::<uint>() as int,
672+
sys::min_align_of::<uint>() as int, refcount_type.node);
673+
let (vp, vpsize, vpalign) = voidptr();
674+
add_member(box_scx, ~"tydesc", 0, vpsize, vpalign, vp);
675+
add_member(box_scx, ~"prev", 0, vpsize, vpalign, vp);
676+
add_member(box_scx, ~"next", 0, vpsize, vpalign, vp);
677+
let size = 2 * sys::size_of::<int>() as int;
678+
let align = sys::min_align_of::<int>() as int;
679+
add_member(box_scx, ~"boxed", 0, size, align, vec_md.node);
680+
let llnode = finish_structure(box_scx);
681+
let mdval = @Metadata {
682+
node: llnode,
683+
data: TyDescMetadata {
684+
hash: ty::type_id(elem_t)
685+
}
686+
};
687+
return mdval;
688+
}
689+
690+
fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span)
691+
-> @Metadata<TyDescMetadata> {
692+
let fname = filename_from_span(cx, span);
693+
let file_node = create_file(cx, fname);
694+
let elem_ty_md = create_ty(cx, elem_t, span);
695+
let uint_type = create_basic_type(cx, ty::mk_uint(cx.tcx), span);
696+
let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md);
697+
let scx = create_structure(file_node, @ty_to_str(cx.tcx, vec_t), 0);
698+
let (_, ptr_size, ptr_align) = voidptr();
699+
add_member(scx, ~"vec", 0, ptr_size, ptr_align, elem_ptr.node);
700+
add_member(scx, ~"length", 0, sys::size_of::<uint>() as int,
701+
sys::min_align_of::<uint>() as int, uint_type.node);
623702
let llnode = finish_structure(scx);
624-
@Metadata {
703+
let mdval = @Metadata {
625704
node: llnode,
626705
data: TyDescMetadata {
627706
hash: ty::type_id(vec_t)
628707
}
629-
}
708+
};
709+
return mdval;
710+
}
711+
712+
fn create_fn_ty(cx: @CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
713+
span: span) -> @Metadata<TyDescMetadata> {
714+
let fname = filename_from_span(cx, span);
715+
let file_node = create_file(cx, fname);
716+
let (vp, _, _) = voidptr();
717+
let output_md = create_ty(cx, output, span);
718+
let output_ptr_md = create_pointer_type(cx, output, span, output_md);
719+
let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span).node };
720+
let members = ~[output_ptr_md.node, vp] + inputs_vals;
721+
let llnode = create_composite_type(SubroutineTag, ~"", file_node.node,
722+
0, 0, 0, 0, None, Some(members));
723+
let mdval = @Metadata {
724+
node: llnode,
725+
data: TyDescMetadata {
726+
hash: ty::type_id(fn_ty)
727+
}
728+
};
729+
return mdval;
630730
}
631731

632732
fn create_ty(cx: @CrateContext, t: ty::t, span: span)
@@ -643,20 +743,42 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span)
643743
match sty {
644744
ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_)
645745
| ty::ty_float(_) => create_basic_type(cx, t, span),
646-
ty::ty_estr(_vstore) => {
647-
cx.sess.span_bug(span, ~"debuginfo for estr NYI")
746+
ty::ty_estr(ref vstore) => {
747+
let i8_t = ty::mk_i8(cx.tcx);
748+
match *vstore {
749+
ty::vstore_fixed(len) => {
750+
create_fixed_vec(cx, t, i8_t, len as int + 1, span)
751+
},
752+
ty::vstore_uniq | ty::vstore_box => {
753+
let box_md = create_boxed_vec(cx, t, i8_t, span);
754+
create_pointer_type(cx, t, span, box_md)
755+
}
756+
ty::vstore_slice(_region) => {
757+
create_vec_slice(cx, t, i8_t, span)
758+
}
759+
}
648760
},
649761
ty::ty_enum(_did, ref _substs) => {
650762
cx.sess.span_bug(span, ~"debuginfo for enum NYI")
651763
}
652-
ty::ty_box(ref _mt) => {
653-
cx.sess.span_bug(span, ~"debuginfo for box NYI")
764+
ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => {
765+
let boxed = create_ty(cx, mt.ty, span);
766+
let box_md = create_boxed_type(cx, mt.ty, span, boxed);
767+
create_pointer_type(cx, t, span, box_md)
654768
},
655-
ty::ty_uniq(ref _mt) => {
656-
cx.sess.span_bug(span, ~"debuginfo for uniq NYI")
657-
},
658-
ty::ty_evec(ref _mt, ref _vstore) => {
659-
cx.sess.span_bug(span, ~"debuginfo for evec NYI")
769+
ty::ty_evec(ref mt, ref vstore) => {
770+
match *vstore {
771+
ty::vstore_fixed(len) => {
772+
create_fixed_vec(cx, t, mt.ty, len as int, span)
773+
},
774+
ty::vstore_uniq | ty::vstore_box => {
775+
let box_md = create_boxed_vec(cx, t, mt.ty, span);
776+
create_pointer_type(cx, t, span, box_md)
777+
},
778+
ty::vstore_slice(_region) => {
779+
create_vec_slice(cx, t, mt.ty, span)
780+
}
781+
}
660782
},
661783
ty::ty_ptr(ref mt) => {
662784
let pointee = create_ty(cx, mt.ty, span);
@@ -665,8 +787,10 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span)
665787
ty::ty_rptr(ref _region, ref _mt) => {
666788
cx.sess.span_bug(span, ~"debuginfo for rptr NYI")
667789
},
668-
ty::ty_bare_fn(ref _barefnty) => {
669-
cx.sess.span_bug(span, ~"debuginfo for bare_fn NYI")
790+
ty::ty_bare_fn(ref barefnty) => {
791+
let inputs = do barefnty.sig.inputs.map |a| { a.ty };
792+
let output = barefnty.sig.output;
793+
create_fn_ty(cx, t, inputs, output, span)
670794
},
671795
ty::ty_closure(ref _closurety) => {
672796
cx.sess.span_bug(span, ~"debuginfo for closure NYI")
@@ -812,7 +936,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
812936
}
813937
814938
pub fn update_source_pos(cx: block, s: span) {
815-
if !cx.sess().opts.debuginfo {
939+
if !cx.sess().opts.debuginfo || (*s.lo == 0 && *s.hi == 0) {
816940
return;
817941
}
818942
let cm = cx.sess().codemap;

src/test/debug-info/box.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-test
12+
13+
// compile-flags:-Z extra-debug-info
14+
// debugger:set print pretty off
15+
// debugger:break 29
16+
// debugger:run
17+
// debugger:print a->boxed
18+
// check:$1 = 1
19+
// debugger:print b->boxed
20+
// check:$2 = {2, 3.5}
21+
// debugger:print c->boxed
22+
// check:$3 = 4
23+
// debugger:print d->boxed
24+
// check:$4 = false
25+
26+
fn main() {
27+
let a = ~1;
28+
let b = ~(2, 3.5);
29+
let c = @4;
30+
let d = @false;
31+
let _z = 0;
32+
}

src/test/debug-info/vec.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-test
12+
13+
// compile-flags:-Z extra-debug-info
14+
// debugger:set print pretty off
15+
// debugger:break 29
16+
// debugger:run
17+
// debugger:print a
18+
// check:$1 = {1, 2, 3}
19+
// debugger:print b.vec[0]
20+
// check:$2 = 4
21+
// debugger:print c->boxed.data[1]
22+
// check:$3 = 8
23+
// debugger:print d->boxed.data[2]
24+
// check:$4 = 12
25+
26+
fn main() {
27+
let a = [1, 2, 3];
28+
let b = &[4, 5, 6];
29+
let c = @[7, 8, 9];
30+
let d = ~[10, 11, 12];
31+
let _z = 0;
32+
}

0 commit comments

Comments
 (0)