debuginfo: Began refactoring of composite type handling.

This commit is contained in:
Michael Woerister 2013-06-26 16:00:42 +02:00
parent 3514a5af06
commit 976d7a53cb
6 changed files with 292 additions and 46 deletions

View File

@ -1635,6 +1635,14 @@ pub mod llvm {
#[fast_ffi]
pub unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef,
Ty: TypeRef) -> c_uint;
/** Computes the byte offset of the indexed struct element for a target. */
#[fast_ffi]
pub unsafe fn LLVMOffsetOfElement(TD: TargetDataRef,
StructTy: TypeRef,
Element: c_uint)
-> c_ulonglong;
/**
* Returns the minimum alignment of a type when part of a call frame.
*/

View File

@ -49,6 +49,7 @@ use lib::llvm::debuginfo::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::trans::type_::Type;
use middle::trans;
use middle::ty;
use util::ppaux::ty_to_str;
@ -65,6 +66,8 @@ use syntax::codemap::span;
use syntax::{ast, codemap, ast_util, ast_map};
use syntax::parse::token;
static DW_LANG_RUST: int = 0x9000;
static AutoVariableTag: int = 256;
@ -594,17 +597,102 @@ fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field]
-> DICompositeType {
debug!("create_struct: %?", ty::get(struct_type));
let loc = span_start(cx, span);
let file_md = create_file(cx, loc.file.name);
let struct_name = ty_to_str(cx.tcx, struct_type);
let struct_llvm_type = type_of::type_of(cx, struct_type);
let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, struct_type), file_md, loc.line);
for fields.iter().advance |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);
scx.add_member(cx.sess.str_of(field.ident), loc.line, size, align, ty_md);
}
return scx.finalize();
let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty));
let field_names = fields.map(|field| cx.sess.str_of(field.ident).to_owned());
let field_types_metadata = fields.map(|field| create_ty(cx, field.mt.ty, span));
return create_composite_type(
cx,
struct_llvm_type,
struct_name,
field_llvm_types,
field_names,
field_types_metadata,
span);
}
fn create_tuple(cx: &mut CrateContext,
tuple_type: ty::t,
component_types: &[ty::t],
span: span)
-> DICompositeType {
let tuple_name = (cx.sess.str_of((dbg_cx(cx).names)("tuple"))).to_owned();
let tuple_llvm_type = type_of::type_of(cx, tuple_type);
// Create a vec of empty strings. A vec::build_n() function would be nice for this.
let mut component_names : ~[~str] = vec::with_capacity(component_types.len());
component_names.grow_fn(component_types.len(), |_| ~"");
let component_llvm_types = component_types.map(|it| type_of::type_of(cx, *it));
let component_types_metadata = component_types.map(|it| create_ty(cx, *it, span));
return create_composite_type(
cx,
tuple_llvm_type,
tuple_name,
component_llvm_types,
component_names,
component_types_metadata,
span);
}
fn create_composite_type(cx: &mut CrateContext,
composite_llvm_type: Type,
composite_type_name: &str,
member_llvm_types: &[Type],
member_names: &[~str],
member_type_metadata: &[DIType],
span: span)
-> DICompositeType {
let loc = span_start(cx, span);
let file_metadata = create_file(cx, loc.file.name);
let composite_size = machine::llsize_of_alloc(cx, composite_llvm_type);
let composite_align = machine::llalign_of_min(cx, composite_llvm_type);
let member_metadata = create_DIArray(
DIB(cx),
// transform the ty::t array of components into an array of DIEs
do vec::mapi(member_llvm_types) |i, member_llvm_type| {
let member_size = machine::llsize_of_alloc(cx, *member_llvm_type);
let member_align = machine::llalign_of_min(cx, *member_llvm_type);
let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
let member_name : &str = member_names[i];
do member_name.as_c_str |member_name| { unsafe {
llvm::LLVMDIBuilderCreateMemberType(
DIB(cx),
file_metadata,
member_name,
file_metadata,
loc.line as c_uint,
bytes_to_bits(member_size),
bytes_to_bits(member_align),
bytes_to_bits(member_offset),
0,
member_type_metadata[i])
}}
});
return do composite_type_name.as_c_str |name| { unsafe {
llvm::LLVMDIBuilderCreateStructType(
DIB(cx),
file_metadata,
name,
file_metadata,
loc.line as c_uint,
bytes_to_bits(composite_size),
bytes_to_bits(composite_align),
0,
ptr::null(),
member_metadata,
0,
ptr::null())
}};
}
// 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
return scx.finalize();
}
fn create_boxed_type(cx: &mut CrateContext, contents: ty::t,
span: span, boxed: DIType) -> DICompositeType {
debug!("create_boxed_type: %?", ty::get(contents));
fn create_boxed_type(cx: &mut CrateContext,
content_type: ty::t,
span: span)
-> DICompositeType {
let loc = span_start(cx, span);
let file_md = create_file(cx, loc.file.name);
let int_t = ty::mk_int();
let refcount_type = create_basic_type(cx, int_t, span);
let name = ty_to_str(cx.tcx, contents);
debug!("create_boxed_type: %?", ty::get(content_type));
let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0);
scx.add_member("refcnt", 0, sys::size_of::<uint>(),
sys::min_align_of::<uint>(), refcount_type);
// the tydesc and other pointers should be irrelevant to the
// debugger, so treat them as void* types
let (vp, vpsize, vpalign) = voidptr(cx);
scx.add_member("tydesc", 0, vpsize, vpalign, vp);
scx.add_member("prev", 0, vpsize, vpalign, vp);
scx.add_member("next", 0, vpsize, vpalign, vp);
let (size, align) = size_and_align_of(cx, contents);
scx.add_member("boxed", 0, size, align, boxed);
return scx.finalize();
let content_llvm_type = type_of::type_of(cx, content_type);
let content_type_metadata = create_ty(cx, content_type, span);
let box_llvm_type = Type::box(cx, &content_llvm_type);
let member_llvm_types = box_llvm_type.field_types();
let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"];
assert!(box_layout_is_as_expected(cx, member_llvm_types, content_llvm_type));
let int_type = ty::mk_int();
let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
let member_types_metadata = [
create_ty(cx, int_type, span),
create_ty(cx, nil_pointer_type, span),
create_ty(cx, nil_pointer_type, span),
create_ty(cx, nil_pointer_type, span),
content_type_metadata
];
return create_composite_type(
cx,
box_llvm_type,
"box name",
member_llvm_types,
member_names,
member_types_metadata,
span);
fn box_layout_is_as_expected(cx: &CrateContext,
member_types: &[Type],
content_type: Type)
-> bool {
return member_types[0] == cx.int_type
&& member_types[1] == cx.tydesc_type.ptr_to()
&& member_types[2] == Type::i8().ptr_to()
&& member_types[3] == Type::i8().ptr_to()
&& member_types[4] == content_type;
}
}
// fn create_boxed_type(cx: &mut CrateContext,
// contents: ty::t,
// span: span,
// boxed: DIType)
// -> DICompositeType {
// debug!("create_boxed_type: %?", ty::get(contents));
// let loc = span_start(cx, span);
// let file_md = create_file(cx, loc.file.name);
// let int_t = ty::mk_int();
// let refcount_type = create_basic_type(cx, int_t, span);
// let name = ty_to_str(cx.tcx, contents);
// let mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0);
// scx.add_member("refcnt", 0, sys::size_of::<uint>(),
// sys::min_align_of::<uint>(), refcount_type);
// // the tydesc and other pointers should be irrelevant to the
// // debugger, so treat them as void* types
// let (vp, vpsize, vpalign) = voidptr(cx);
// scx.add_member("tydesc", 0, vpsize, vpalign, vp);
// scx.add_member("prev", 0, vpsize, vpalign, vp);
// scx.add_member("next", 0, vpsize, vpalign, vp);
// let (size, align) = size_and_align_of(cx, contents);
// scx.add_member("val", 0, size, align, boxed);
// return scx.finalize();
// }
fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t,
len: uint, span: span) -> DIType {
debug!("create_fixed_vec: %?", ty::get(_vec_t));
@ -840,9 +981,8 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
create_unimpl_ty(cx, t)
}
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)
let box_metadata = create_boxed_type(cx, mt.ty, span);
create_pointer_type(cx, t, span, box_metadata)
},
ty::ty_evec(ref mt, ref vstore) => {
match *vstore {
@ -858,10 +998,7 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
}
}
},
ty::ty_ptr(ref mt) => {
let pointee = create_ty(cx, mt.ty, span);
create_pointer_type(cx, t, span, pointee)
},
ty::ty_ptr(ref mt) |
ty::ty_rptr(_, ref mt) => {
let pointee = create_ty(cx, mt.ty, span);
create_pointer_type(cx, t, span, pointee)

View File

@ -113,3 +113,48 @@ pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
}
}
pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> uint {
unsafe {
return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as uint;
}
}
// Computes the size of the data part of an enum.
pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint {
if cx.enum_sizes.contains_key(&t) {
return cx.enum_sizes.get_copy(&t);
}
debug!("static_size_of_enum %s", ty_to_str(cx.tcx, t));
match ty::get(t).sty {
ty::ty_enum(tid, ref substs) => {
// Compute max(variant sizes).
let mut max_size = 0;
let variants = ty::enum_variants(cx.tcx, tid);
for variants.iter().advance |variant| {
if variant.args.len() == 0 {
loop;
}
let lltypes = variant.args.map(|&variant_arg| {
let substituted = ty::subst(cx.tcx, substs, variant_arg);
type_of::sizing_type_of(cx, substituted)
});
debug!("static_size_of_enum: variant %s type %s",
cx.tcx.sess.str_of(variant.name),
cx.tn.type_to_str(Type::struct_(lltypes, false)));
let this_size = llsize_of_real(cx, Type::struct_(lltypes, false));
if max_size < this_size {
max_size = this_size;
}
}
cx.enum_sizes.insert(t, max_size);
return max_size;
}
_ => cx.sess.bug("static_size_of_enum called on non-enum")
}
}

View File

@ -8,20 +8,18 @@
// 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 _zzz
// debugger:run
// debugger:finish
// debugger:print a->boxed
// debugger:print a->val
// check:$1 = 1
// debugger:print b->boxed
// debugger:print b->val
// check:$2 = {2, 3.5}
// debugger:print c->boxed
// debugger:print c->val
// check:$3 = 4
// debugger:print d->boxed
// debugger:print d->val
// check:$4 = false
fn main() {

View File

@ -0,0 +1,60 @@
// 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.
// 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 zzz
// debugger:run
// debugger:finish
// debugger:print unique->val
// check:$1 = {x = 99, y = 999, z = 9999, w = 99999}
// debugger:print managed->val
// check:$2 = {x = 88, y = 888, z = 8888, w = 88888}
// debugger:print unique_dtor->val
// check:$3 = {x = 77, y = 777, z = 7777, w = 77777}
// debugger:print managed_dtor->val
// check:$4 = {x = 33, y = 333, z = 3333, w = 33333}
struct StructWithSomePadding {
x: i16,
y: i32,
z: i32,
w: i64
}
struct StructWithDestructor {
x: i16,
y: i32,
z: i32,
w: i64
}
impl Drop for StructWithDestructor {
fn drop(&self) {}
}
fn main() {
let unique = ~StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
let managed = @StructWithSomePadding { x: 88, y: 888, z: 8888, w: 88888 };
let unique_dtor = ~StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
let managed_dtor = @StructWithDestructor { x: 33, y: 333, z: 3333, w: 33333 };
zzz();
}
fn zzz() {()}

View File

@ -8,8 +8,6 @@
// 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 zzz
// debugger:run
@ -34,7 +32,7 @@ struct WithDestructor {
}
impl Drop for WithDestructor {
fn finalize(&self) {}
fn drop(&self) {}
}
struct NoDestructorGuarded {