Skip to content

Commit 976d7a5

Browse files
debuginfo: Began refactoring of composite type handling.
1 parent 3514a5a commit 976d7a5

File tree

6 files changed

+293
-47
lines changed

6 files changed

+293
-47
lines changed

src/librustc/lib/llvm.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,14 @@ pub mod llvm {
16351635
#[fast_ffi]
16361636
pub unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef,
16371637
Ty: TypeRef) -> c_uint;
1638+
1639+
/** Computes the byte offset of the indexed struct element for a target. */
1640+
#[fast_ffi]
1641+
pub unsafe fn LLVMOffsetOfElement(TD: TargetDataRef,
1642+
StructTy: TypeRef,
1643+
Element: c_uint)
1644+
-> c_ulonglong;
1645+
16381646
/**
16391647
* Returns the minimum alignment of a type when part of a call frame.
16401648
*/

src/librustc/middle/trans/debuginfo.rs

Lines changed: 175 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use lib::llvm::debuginfo::*;
4949
use middle::trans::common::*;
5050
use middle::trans::machine;
5151
use middle::trans::type_of;
52+
use middle::trans::type_::Type;
5253
use middle::trans;
5354
use middle::ty;
5455
use util::ppaux::ty_to_str;
@@ -65,6 +66,8 @@ use syntax::codemap::span;
6566
use syntax::{ast, codemap, ast_util, ast_map};
6667
use syntax::parse::token;
6768

69+
70+
6871
static DW_LANG_RUST: int = 0x9000;
6972

7073
static AutoVariableTag: int = 256;
@@ -594,17 +597,102 @@ fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field]
594597
-> DICompositeType {
595598
debug!("create_struct: %?", ty::get(struct_type));
596599

600+
let struct_name = ty_to_str(cx.tcx, struct_type);
601+
let struct_llvm_type = type_of::type_of(cx, struct_type);
602+
603+
let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty));
604+
let field_names = fields.map(|field| cx.sess.str_of(field.ident).to_owned());
605+
let field_types_metadata = fields.map(|field| create_ty(cx, field.mt.ty, span));
606+
607+
return create_composite_type(
608+
cx,
609+
struct_llvm_type,
610+
struct_name,
611+
field_llvm_types,
612+
field_names,
613+
field_types_metadata,
614+
span);
615+
}
616+
617+
fn create_tuple(cx: &mut CrateContext,
618+
tuple_type: ty::t,
619+
component_types: &[ty::t],
620+
span: span)
621+
-> DICompositeType {
622+
623+
let tuple_name = (cx.sess.str_of((dbg_cx(cx).names)("tuple"))).to_owned();
624+
let tuple_llvm_type = type_of::type_of(cx, tuple_type);
625+
// Create a vec of empty strings. A vec::build_n() function would be nice for this.
626+
let mut component_names : ~[~str] = vec::with_capacity(component_types.len());
627+
component_names.grow_fn(component_types.len(), |_| ~"");
628+
629+
let component_llvm_types = component_types.map(|it| type_of::type_of(cx, *it));
630+
let component_types_metadata = component_types.map(|it| create_ty(cx, *it, span));
631+
632+
return create_composite_type(
633+
cx,
634+
tuple_llvm_type,
635+
tuple_name,
636+
component_llvm_types,
637+
component_names,
638+
component_types_metadata,
639+
span);
640+
}
641+
642+
fn create_composite_type(cx: &mut CrateContext,
643+
composite_llvm_type: Type,
644+
composite_type_name: &str,
645+
member_llvm_types: &[Type],
646+
member_names: &[~str],
647+
member_type_metadata: &[DIType],
648+
span: span)
649+
-> DICompositeType {
650+
597651
let loc = span_start(cx, span);
598-
let file_md = create_file(cx, loc.file.name);
652+
let file_metadata = create_file(cx, loc.file.name);
653+
654+
let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type);
655+
let composite_align = machine::llalign_of_min(cx, composite_llvm_type);
656+
657+
let member_metadata = create_DIArray(
658+
DIB(cx),
659+
// transform the ty::t array of components into an array of DIEs
660+
do vec::mapi(member_llvm_types) |i, member_llvm_type| {
661+
let member_size = machine::llsize_of_alloc(cx, *member_llvm_type);
662+
let member_align = machine::llalign_of_min(cx, *member_llvm_type);
663+
let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
664+
let member_name : &str = member_names[i];
665+
666+
do member_name.as_c_str |member_name| { unsafe {
667+
llvm::LLVMDIBuilderCreateMemberType(
668+
DIB(cx),
669+
file_metadata,
670+
member_name,
671+
file_metadata,
672+
loc.line as c_uint,
673+
bytes_to_bits(member_size),
674+
bytes_to_bits(member_align),
675+
bytes_to_bits(member_offset),
676+
0,
677+
member_type_metadata[i])
678+
}}
679+
});
599680

600-
let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, struct_type), file_md, loc.line);
601-
for fields.iter().advance |field| {
602-
let field_t = field.mt.ty;
603-
let ty_md = create_ty(cx, field_t, span);
604-
let (size, align) = size_and_align_of(cx, field_t);
605-
scx.add_member(cx.sess.str_of(field.ident), loc.line, size, align, ty_md);
606-
}
607-
return scx.finalize();
681+
return do composite_type_name.as_c_str |name| { unsafe {
682+
llvm::LLVMDIBuilderCreateStructType(
683+
DIB(cx),
684+
file_metadata,
685+
name,
686+
file_metadata,
687+
loc.line as c_uint,
688+
bytes_to_bits(composite_size),
689+
bytes_to_bits(composite_align),
690+
0,
691+
ptr::null(),
692+
member_metadata,
693+
0,
694+
ptr::null())
695+
}};
608696
}
609697

610698
// 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
639727
return scx.finalize();
640728
}
641729

642-
fn create_boxed_type(cx: &mut CrateContext, contents: ty::t,
643-
span: span, boxed: DIType) -> DICompositeType {
644-
debug!("create_boxed_type: %?", ty::get(contents));
645-
646-
let loc = span_start(cx, span);
647-
let file_md = create_file(cx, loc.file.name);
648-
let int_t = ty::mk_int();
649-
let refcount_type = create_basic_type(cx, int_t, span);
650-
let name = ty_to_str(cx.tcx, contents);
651-
652-
let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0);
653-
scx.add_member("refcnt", 0, sys::size_of::<uint>(),
654-
sys::min_align_of::<uint>(), refcount_type);
655-
// the tydesc and other pointers should be irrelevant to the
656-
// debugger, so treat them as void* types
657-
let (vp, vpsize, vpalign) = voidptr(cx);
658-
scx.add_member("tydesc", 0, vpsize, vpalign, vp);
659-
scx.add_member("prev", 0, vpsize, vpalign, vp);
660-
scx.add_member("next", 0, vpsize, vpalign, vp);
661-
let (size, align) = size_and_align_of(cx, contents);
662-
scx.add_member("boxed", 0, size, align, boxed);
663-
return scx.finalize();
730+
fn create_boxed_type(cx: &mut CrateContext,
731+
content_type: ty::t,
732+
span: span)
733+
-> DICompositeType {
734+
735+
debug!("create_boxed_type: %?", ty::get(content_type));
736+
737+
let content_llvm_type = type_of::type_of(cx, content_type);
738+
let content_type_metadata = create_ty(cx, content_type, span);
739+
740+
let box_llvm_type = Type::box(cx, &content_llvm_type);
741+
let member_llvm_types = box_llvm_type.field_types();
742+
let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"];
743+
744+
assert!(box_layout_is_as_expected(cx, member_llvm_types, content_llvm_type));
745+
746+
let int_type = ty::mk_int();
747+
let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
748+
749+
let member_types_metadata = [
750+
create_ty(cx, int_type, span),
751+
create_ty(cx, nil_pointer_type, span),
752+
create_ty(cx, nil_pointer_type, span),
753+
create_ty(cx, nil_pointer_type, span),
754+
content_type_metadata
755+
];
756+
757+
return create_composite_type(
758+
cx,
759+
box_llvm_type,
760+
"box name",
761+
member_llvm_types,
762+
member_names,
763+
member_types_metadata,
764+
span);
765+
766+
fn box_layout_is_as_expected(cx: &CrateContext,
767+
member_types: &[Type],
768+
content_type: Type)
769+
-> bool {
770+
return member_types[0] == cx.int_type
771+
&& member_types[1] == cx.tydesc_type.ptr_to()
772+
&& member_types[2] == Type::i8().ptr_to()
773+
&& member_types[3] == Type::i8().ptr_to()
774+
&& member_types[4] == content_type;
775+
}
664776
}
665777

778+
// fn create_boxed_type(cx: &mut CrateContext,
779+
// contents: ty::t,
780+
// span: span,
781+
// boxed: DIType)
782+
// -> DICompositeType {
783+
784+
// debug!("create_boxed_type: %?", ty::get(contents));
785+
786+
// let loc = span_start(cx, span);
787+
// let file_md = create_file(cx, loc.file.name);
788+
// let int_t = ty::mk_int();
789+
// let refcount_type = create_basic_type(cx, int_t, span);
790+
// let name = ty_to_str(cx.tcx, contents);
791+
792+
// let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0);
793+
// scx.add_member("refcnt", 0, sys::size_of::<uint>(),
794+
// sys::min_align_of::<uint>(), refcount_type);
795+
// // the tydesc and other pointers should be irrelevant to the
796+
// // debugger, so treat them as void* types
797+
// let (vp, vpsize, vpalign) = voidptr(cx);
798+
// scx.add_member("tydesc", 0, vpsize, vpalign, vp);
799+
// scx.add_member("prev", 0, vpsize, vpalign, vp);
800+
// scx.add_member("next", 0, vpsize, vpalign, vp);
801+
// let (size, align) = size_and_align_of(cx, contents);
802+
// scx.add_member("val", 0, size, align, boxed);
803+
// return scx.finalize();
804+
// }
805+
806+
666807
fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t,
667808
len: uint, span: span) -> DIType {
668809
debug!("create_fixed_vec: %?", ty::get(_vec_t));
@@ -840,9 +981,8 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
840981
create_unimpl_ty(cx, t)
841982
}
842983
ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => {
843-
let boxed = create_ty(cx, mt.ty, span);
844-
let box_md = create_boxed_type(cx, mt.ty, span, boxed);
845-
create_pointer_type(cx, t, span, box_md)
984+
let box_metadata = create_boxed_type(cx, mt.ty, span);
985+
create_pointer_type(cx, t, span, box_metadata)
846986
},
847987
ty::ty_evec(ref mt, ref vstore) => {
848988
match *vstore {
@@ -858,10 +998,7 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
858998
}
859999
}
8601000
},
861-
ty::ty_ptr(ref mt) => {
862-
let pointee = create_ty(cx, mt.ty, span);
863-
create_pointer_type(cx, t, span, pointee)
864-
},
1001+
ty::ty_ptr(ref mt) |
8651002
ty::ty_rptr(_, ref mt) => {
8661003
let pointee = create_ty(cx, mt.ty, span);
8671004
create_pointer_type(cx, t, span, pointee)

src/librustc/middle/trans/machine.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,48 @@ pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
113113
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
114114
}
115115
}
116+
117+
pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> uint {
118+
unsafe {
119+
return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as uint;
120+
}
121+
}
122+
123+
// Computes the size of the data part of an enum.
124+
pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint {
125+
if cx.enum_sizes.contains_key(&t) {
126+
return cx.enum_sizes.get_copy(&t);
127+
}
128+
129+
debug!("static_size_of_enum %s", ty_to_str(cx.tcx, t));
130+
131+
match ty::get(t).sty {
132+
ty::ty_enum(tid, ref substs) => {
133+
// Compute max(variant sizes).
134+
let mut max_size = 0;
135+
let variants = ty::enum_variants(cx.tcx, tid);
136+
for variants.iter().advance |variant| {
137+
if variant.args.len() == 0 {
138+
loop;
139+
}
140+
141+
let lltypes = variant.args.map(|&variant_arg| {
142+
let substituted = ty::subst(cx.tcx, substs, variant_arg);
143+
type_of::sizing_type_of(cx, substituted)
144+
});
145+
146+
debug!("static_size_of_enum: variant %s type %s",
147+
cx.tcx.sess.str_of(variant.name),
148+
cx.tn.type_to_str(Type::struct_(lltypes, false)));
149+
150+
let this_size = llsize_of_real(cx, Type::struct_(lltypes, false));
151+
if max_size < this_size {
152+
max_size = this_size;
153+
}
154+
}
155+
cx.enum_sizes.insert(t, max_size);
156+
return max_size;
157+
}
158+
_ => cx.sess.bug("static_size_of_enum called on non-enum")
159+
}
160+
}

src/test/debug-info/box.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,18 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// xfail-test
12-
1311
// compile-flags:-Z extra-debug-info
1412
// debugger:set print pretty off
1513
// debugger:break _zzz
1614
// debugger:run
1715
// debugger:finish
18-
// debugger:print a->boxed
16+
// debugger:print a->val
1917
// check:$1 = 1
20-
// debugger:print b->boxed
18+
// debugger:print b->val
2119
// check:$2 = {2, 3.5}
22-
// debugger:print c->boxed
20+
// debugger:print c->val
2321
// check:$3 = 4
24-
// debugger:print d->boxed
22+
// debugger:print d->val
2523
// check:$4 = false
2624

2725
fn main() {

0 commit comments

Comments
 (0)