Represent boxed ifaces in a way similar to functions

They are now a (dictptr, box) pair, where box is a regular boxed
representation of the inner type. This cuts down on some special
case code.

Also removes some code from trans::base that was moved to shape but
then somehow restored in trans::base through a bad merge.

Starts on issue #1567
This commit is contained in:
Marijn Haverbeke 2012-02-10 11:32:03 +01:00
parent b17348527e
commit d01e7cd340
7 changed files with 69 additions and 286 deletions

View File

@ -57,7 +57,6 @@ const shape_res: u8 = 20u8;
const shape_var: u8 = 21u8;
const shape_uniq: u8 = 22u8;
const shape_opaque_closure_ptr: u8 = 23u8; // the closure itself.
const shape_iface: u8 = 24u8;
const shape_uniq_fn: u8 = 25u8;
const shape_stack_fn: u8 = 26u8;
const shape_bare_fn: u8 = 27u8;
@ -65,9 +64,6 @@ const shape_tydesc: u8 = 28u8;
const shape_send_tydesc: u8 = 29u8;
const shape_class: u8 = 30u8;
// FIXME: This is a bad API in trans_common.
fn C_u8(n: u8) -> ValueRef { ret trans::common::C_u8(n as uint); }
fn hash_res_info(ri: res_info) -> uint {
let h = 5381u;
h *= 33u;
@ -404,7 +400,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
}
add_substr(s, sub);
}
ty::ty_iface(_, _) { s += [shape_iface]; }
ty::ty_iface(_, _) { s += [shape_box_fn]; }
ty::ty_class(_, _) { s += [shape_class]; }
ty::ty_res(did, raw_subt, tps) {
let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt);
@ -720,7 +716,7 @@ fn dynamic_metrics(cx: @block_ctxt, t: ty::t) -> metrics {
alt ty::get(t).struct {
ty::ty_param(p, _) {
let ti = none::<@tydesc_info>;
let ti = none;
let {bcx, val: tydesc} = base::get_tydesc(cx, t, false, ti).result;
let szptr = GEPi(bcx, tydesc, [0, abi::tydesc_field_size]);
let aptr = GEPi(bcx, tydesc, [0, abi::tydesc_field_align]);
@ -783,7 +779,7 @@ fn dynamic_metrics(cx: @block_ctxt, t: ty::t) -> metrics {
fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
alt ty::get(typ).struct {
ty::ty_box(_) | ty::ty_iface(_, _) {
ty::ty_box(_) | ty::ty_opaque_box {
ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx));
}
ty::ty_uniq(_) {

View File

@ -41,9 +41,9 @@ import link::{mangle_internal_name_by_type_only,
import metadata::{csearch, cstore};
import util::ppaux::{ty_to_str, ty_to_short_str};
import shape::static_size_of_enum;
import common::*;
import build::*;
import shape::*;
import ast_map::{path, path_mod, path_name};
fn type_of_explicit_args(cx: @crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
@ -136,7 +136,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_fn(_) {
T_fn_pair(cx, type_of_fn_from_ty(cx, t, []))
}
ty::ty_iface(_, _) { T_opaque_iface_ptr(cx) }
ty::ty_iface(_, _) { T_opaque_iface(cx) }
ty::ty_res(_, sub, tps) {
let sub1 = ty::substitute_type_params(cx.tcx, tps, sub);
// FIXME #1184: Resource flag is larger than necessary
@ -320,44 +320,6 @@ fn umin(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
ret Select(cx, cond, a, b);
}
// Returns the real size of the given type for the current target.
fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
ret llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
}
// Returns the real alignment of the given type for the current target.
fn llalign_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
ret llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
}
fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
ret llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t), cx.int_type,
False);
}
fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
ret llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMAlignOf(t), cx.int_type,
False);
}
fn size_of(cx: @block_ctxt, t: ty::t) -> result {
size_of_(cx, t)
}
fn size_of_(cx: @block_ctxt, t: ty::t) -> result {
let ccx = bcx_ccx(cx);
if check type_has_static_size(ccx, t) {
rslt(cx, llsize_of(bcx_ccx(cx), type_of(ccx, t)))
} else { dynamic_size_of(cx, t) }
}
fn align_of(cx: @block_ctxt, t: ty::t) -> result {
let ccx = bcx_ccx(cx);
if check type_has_static_size(ccx, t) {
rslt(cx, llalign_of(bcx_ccx(cx), type_of(ccx, t)))
} else { dynamic_align_of(cx, t) }
}
fn alloca(cx: @block_ctxt, t: TypeRef) -> ValueRef {
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
ret Alloca(new_raw_block_ctxt(cx.fcx, cx.fcx.llstaticallocas), t);
@ -394,158 +356,6 @@ fn mk_obstack_token(ccx: @crate_ctxt, fcx: @fn_ctxt) ->
ret Call(cx, ccx.upcalls.dynastack_mark, []);
}
// Creates a simpler, size-equivalent type. The resulting type is guaranteed
// to have (a) the same size as the type that was passed in; (b) to be non-
// recursive. This is done by replacing all boxes in a type with boxed unit
// types.
fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
alt ty::get(typ).struct {
ty::ty_box(_) | ty::ty_iface(_, _) | ty::ty_opaque_box {
ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx));
}
ty::ty_uniq(_) {
ret ty::mk_imm_uniq(ccx.tcx, ty::mk_nil(ccx.tcx));
}
ty::ty_fn(_) {
ret ty::mk_tup(ccx.tcx,
[ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx)),
ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx))]);
}
ty::ty_res(_, sub, tps) {
let sub1 = ty::substitute_type_params(ccx.tcx, tps, sub);
ret ty::mk_tup(ccx.tcx,
[ty::mk_int(ccx.tcx), simplify_type(ccx, sub1)]);
}
_ { ret typ; }
}
}
ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
}
fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
//
// C padding rules:
//
//
// - Pad after each element so that next element is aligned.
// - Pad after final structure member so that whole structure
// is aligned to max alignment of interior.
//
let off = C_int(bcx_ccx(cx), 0);
let max_align = C_int(bcx_ccx(cx), 1);
let bcx = cx;
for e: ty::t in elts {
let elt_align = align_of(bcx, e);
bcx = elt_align.bcx;
let elt_size = size_of(bcx, e);
bcx = elt_size.bcx;
let aligned_off = align_to(bcx, off, elt_align.val);
off = Add(bcx, aligned_off, elt_size.val);
max_align = umax(bcx, max_align, elt_align.val);
}
off = align_to(bcx, off, max_align);
//off = alt mode {
// align_total. {
// align_to(bcx, off, max_align)
// }
// align_next(t) {
// let {bcx, val: align} = align_of(bcx, t);
// align_to(bcx, off, align)
// }
//};
ret rslt(bcx, off);
}
alt ty::get(t).struct {
ty::ty_param(p, _) {
let szptr = field_of_tydesc(cx, t, false, abi::tydesc_field_size);
ret rslt(szptr.bcx, Load(szptr.bcx, szptr.val));
}
ty::ty_rec(flds) {
let tys: [ty::t] = [];
for f: ty::field in flds { tys += [f.mt.ty]; }
ret align_elements(cx, tys);
}
ty::ty_tup(elts) {
let tys = [];
for tp in elts { tys += [tp]; }
ret align_elements(cx, tys);
}
ty::ty_enum(tid, tps) {
let bcx = cx;
let ccx = bcx_ccx(bcx);
// Compute max(variant sizes).
let max_size: ValueRef = alloca(bcx, ccx.int_type);
Store(bcx, C_int(ccx, 0), max_size);
let variants = ty::enum_variants(bcx_tcx(bcx), tid);
for variant: ty::variant_info in *variants {
// Perform type substitution on the raw argument types.
let raw_tys: [ty::t] = variant.args;
let tys: [ty::t] = [];
for raw_ty: ty::t in raw_tys {
let t = ty::substitute_type_params(bcx_tcx(cx), tps, raw_ty);
tys += [t];
}
let rslt = align_elements(bcx, tys);
bcx = rslt.bcx;
let this_size = rslt.val;
let old_max_size = Load(bcx, max_size);
Store(bcx, umax(bcx, this_size, old_max_size), max_size);
}
let max_size_val = Load(bcx, max_size);
let total_size =
if vec::len(*variants) != 1u {
Add(bcx, max_size_val, llsize_of(ccx, ccx.int_type))
} else { max_size_val };
ret rslt(bcx, total_size);
}
// Precondition?
_ { bcx_tcx(cx).sess.fatal("trans::dynamic_size_of alled on something \
with static size"); }
}
}
fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result {
// FIXME: Typestate constraint that shows this alt is
// exhaustive
alt ty::get(t).struct {
ty::ty_param(p, _) {
let aptr = field_of_tydesc(cx, t, false, abi::tydesc_field_align);
ret rslt(aptr.bcx, Load(aptr.bcx, aptr.val));
}
ty::ty_rec(flds) {
let a = C_int(bcx_ccx(cx), 1);
let bcx = cx;
for f: ty::field in flds {
let align = align_of(bcx, f.mt.ty);
bcx = align.bcx;
a = umax(bcx, a, align.val);
}
ret rslt(bcx, a);
}
ty::ty_enum(_, _) {
ret rslt(cx, C_int(bcx_ccx(cx), 1)); // FIXME: stub
}
ty::ty_tup(elts) {
let a = C_int(bcx_ccx(cx), 1);
let bcx = cx;
for e in elts {
let align = align_of(bcx, e);
bcx = align.bcx;
a = umax(bcx, a, align.val);
}
ret rslt(bcx, a);
}
_ { bcx_tcx(cx).sess.bug("trans::dynamic_align_of called on \
something with static size"); }
}
}
// Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
// The type of the returned pointer is always i8*. If you care about the
// return type, use bump_ptr().
@ -712,8 +522,7 @@ fn opaque_box_body(bcx: @block_ctxt,
// header.
fn trans_malloc_boxed_raw(bcx: @block_ctxt, t: ty::t,
&static_ti: option<@tydesc_info>) -> result {
let bcx = bcx;
let ccx = bcx_ccx(bcx);
let bcx = bcx, ccx = bcx_ccx(bcx);
// Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc
// wants.
@ -723,6 +532,7 @@ fn trans_malloc_boxed_raw(bcx: @block_ctxt, t: ty::t,
// Get the tydesc for the body:
let {bcx, val: lltydesc} = get_tydesc(bcx, t, true, static_ti).result;
lazily_emit_all_tydesc_glue(ccx, static_ti);
// Allocate space:
let rval = Call(bcx, ccx.upcalls.malloc, [lltydesc]);
@ -816,7 +626,7 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
let bcx = new_raw_block_ctxt(cx.fcx, cx.fcx.llderivedtydescs);
let tys = linearize_ty_params(bcx, t);
let root_ti = get_static_tydesc(bcx_ccx(bcx), t, tys.params);
static_ti = some::<@tydesc_info>(root_ti);
static_ti = some(root_ti);
lazily_emit_all_tydesc_glue(bcx_ccx(cx), static_ti);
let root = root_ti.tydesc;
let sz = size_of(bcx, t);
@ -1069,7 +879,7 @@ fn emit_tydescs(ccx: @crate_ctxt) {
some(v) { ccx.stats.n_real_glues += 1u; v }
};
let shape = shape::shape_of(ccx, key, ti.ty_params);
let shape = shape_of(ccx, key, ti.ty_params);
let shape_tables =
llvm::LLVMConstPointerCast(ccx.shape_cx.llshapetables,
T_ptr(T_i8()));
@ -1100,11 +910,10 @@ fn emit_tydescs(ccx: @crate_ctxt) {
}
fn make_take_glue(cx: @block_ctxt, v: ValueRef, t: ty::t) {
let bcx = cx;
// NB: v is an *alias* of type t here, not a direct value.
// NB: v is a *pointer* to type t here, not a direct value.
bcx = alt ty::get(t).struct {
ty::ty_box(_) | ty::ty_iface(_, _) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box {
incr_refcnt_of_boxed(bcx, Load(bcx, v))
}
ty::ty_uniq(_) {
@ -1128,6 +937,10 @@ fn make_take_glue(cx: @block_ctxt, v: ValueRef, t: ty::t) {
ty::ty_fn(_) {
closure::make_fn_glue(bcx, v, t, take_ty)
}
ty::ty_iface(_, _) {
let box = Load(bcx, GEPi(bcx, v, [0, 1]));
incr_refcnt_of_boxed(bcx, box)
}
ty::ty_opaque_closure_ptr(ck) {
closure::make_opaque_cbox_take_glue(bcx, ck, v)
}
@ -1177,20 +990,6 @@ fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) {
ty::ty_vec(_) | ty::ty_str {
tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of(ccx, t)), t)
}
ty::ty_iface(_, _) {
// Call through the box's own fields-drop glue first.
// Then free the body.
let ccx = bcx_ccx(bcx);
let llbox_ty = T_opaque_iface_ptr(ccx);
let b = PointerCast(bcx, v, llbox_ty);
let body = GEPi(bcx, b, [0, abi::box_field_body]);
let tydescptr = GEPi(bcx, body, [0, 0]);
let tydesc = Load(bcx, tydescptr);
let ti = none;
call_tydesc_glue_full(bcx, body, tydesc,
abi::tydesc_field_drop_glue, ti);
trans_free(bcx, b)
}
ty::ty_send_type {
// sendable type descriptors are basically unique pointers,
// they must be freed.
@ -1214,7 +1013,7 @@ fn make_drop_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) {
// NB: v0 is an *alias* of type t here, not a direct value.
let ccx = bcx_ccx(bcx);
let bcx = alt ty::get(t).struct {
ty::ty_box(_) | ty::ty_iface(_, _) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box {
decr_refcnt_maybe_free(bcx, Load(bcx, v0), t)
}
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str | ty::ty_send_type {
@ -1226,6 +1025,10 @@ fn make_drop_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) {
ty::ty_fn(_) {
closure::make_fn_glue(bcx, v0, t, drop_ty)
}
ty::ty_iface(_, _) {
let box = Load(bcx, GEPi(bcx, v0, [0, 1]));
decr_refcnt_maybe_free(bcx, box, ty::mk_opaque_box(ccx.tcx))
}
ty::ty_opaque_closure_ptr(ck) {
closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
}
@ -1300,7 +1103,7 @@ fn decr_refcnt_maybe_free(cx: @block_ctxt, box_ptr: ValueRef, t: ty::t)
let rc_adj_cx = new_sub_block_ctxt(cx, "rc--");
let free_cx = new_sub_block_ctxt(cx, "free");
let next_cx = new_sub_block_ctxt(cx, "next");
let llbox_ty = T_opaque_iface_ptr(ccx);
let llbox_ty = T_opaque_box_ptr(ccx);
let box_ptr = PointerCast(cx, box_ptr, llbox_ty);
let null_test = IsNull(cx, box_ptr);
CondBr(cx, null_test, next_cx.llbb, rc_adj_cx.llbb);
@ -1699,7 +1502,7 @@ fn drop_ty(cx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
alt ty::get(t).struct {
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { free_ty(bcx, v, t) }
ty::ty_box(_) | ty::ty_iface(_, _) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box {
decr_refcnt_maybe_free(bcx, v, t)
}
// Precondition?
@ -1709,7 +1512,7 @@ fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
fn take_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> result {
alt ty::get(t).struct {
ty::ty_box(_) | ty::ty_iface(_, _) | ty::ty_opaque_box {
ty::ty_box(_) | ty::ty_opaque_box {
rslt(incr_refcnt_of_boxed(bcx, v), v)
}
ty::ty_uniq(_) {
@ -2429,13 +2232,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
-> option<{llfn: ValueRef, fty: ty::t}> {
let substs = vec::map(substs, {|t|
alt ty::get(t).struct {
ty::ty_box(mt) {
if !ty::type_has_params(mt.ty) {
let ti = some(get_static_tydesc(ccx, mt.ty, []));
lazily_emit_all_tydesc_glue(ccx, ti);
}
ty::mk_opaque_box(ccx.tcx)
}
ty::ty_box(mt) { ty::mk_opaque_box(ccx.tcx) }
_ { t }
}
});
@ -4254,21 +4051,16 @@ fn mk_standard_basic_blocks(llfn: ValueRef) ->
dt: BasicBlockRef,
da: BasicBlockRef,
rt: BasicBlockRef} {
ret {sa:
str::as_buf("static_allocas",
{|buf| llvm::LLVMAppendBasicBlock(llfn, buf) }),
ca:
str::as_buf("load_env",
{|buf| llvm::LLVMAppendBasicBlock(llfn, buf) }),
dt:
str::as_buf("derived_tydescs",
{|buf| llvm::LLVMAppendBasicBlock(llfn, buf) }),
da:
str::as_buf("dynamic_allocas",
{|buf| llvm::LLVMAppendBasicBlock(llfn, buf) }),
rt:
str::as_buf("return",
{|buf| llvm::LLVMAppendBasicBlock(llfn, buf) })};
ret {sa: str::as_buf("static_allocas", {|buf|
llvm::LLVMAppendBasicBlock(llfn, buf) }),
ca: str::as_buf("load_env", {|buf|
llvm::LLVMAppendBasicBlock(llfn, buf) }),
dt: str::as_buf("derived_tydescs", {|buf|
llvm::LLVMAppendBasicBlock(llfn, buf) }),
da: str::as_buf("dynamic_allocas", {|buf|
llvm::LLVMAppendBasicBlock(llfn, buf) }),
rt: str::as_buf("return", {|buf|
llvm::LLVMAppendBasicBlock(llfn, buf) })};
}
@ -5415,7 +5207,7 @@ fn write_metadata(cx: @crate_ctxt, crate: @ast::crate) {
// Writes the current ABI version into the crate.
fn write_abi_version(ccx: @crate_ctxt) {
shape::mk_global(ccx, "rust_abi_version", C_uint(ccx, abi::abi_version),
mk_global(ccx, "rust_abi_version", C_uint(ccx, abi::abi_version),
false);
}
@ -5520,7 +5312,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
task_type: task_type,
opaque_vec_type: T_opaque_vec(targ_cfg),
builder: BuilderRef_res(llvm::LLVMCreateBuilder()),
shape_cx: shape::mk_ctxt(llmod),
shape_cx: mk_ctxt(llmod),
crate_map: crate_map,
dbg_cx: dbg_cx,
mutable do_not_commit_warning_issued: false};
@ -5529,7 +5321,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
trans_mod(ccx, crate.node.module);
fill_crate_map(ccx, crate_map);
emit_tydescs(ccx);
shape::gen_shape_tables(ccx);
gen_shape_tables(ccx);
write_abi_version(ccx);
// Translate the metadata.

View File

@ -642,7 +642,7 @@ fn make_opaque_cbox_take_glue(
let sz = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_size]));
// Adjust sz to account for the rust_opaque_box header fields
let sz = Add(bcx, sz, base::llsize_of(ccx, T_box_header(ccx)));
let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx)));
// Allocate memory, update original ptr, and copy existing data
let malloc = ccx.upcalls.shared_malloc;

View File

@ -710,9 +710,8 @@ fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef {
ret T_struct(vec::init_elt::<TypeRef>(n, T_ptr(cx.tydesc_type)));
}
fn T_opaque_iface_ptr(cx: @crate_ctxt) -> TypeRef {
let tdptr = T_ptr(cx.tydesc_type);
T_ptr(T_box(cx, T_struct([tdptr, tdptr, T_i8()])))
fn T_opaque_iface(cx: @crate_ctxt) -> TypeRef {
T_struct([T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
}
fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }

View File

@ -38,7 +38,7 @@ import ast_map::{path, path_mod, path_name};
// up.
//
// The trans_constants pass in trans.rs outputs the vtables. Typeck
// annotates notes with information about the methods and dicts that
// annotates nodes with information about the methods and dicts that
// are referenced (ccx.method_map and ccx.dict_map).
fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
@ -189,17 +189,15 @@ fn trans_iface_callee(bcx: @block_ctxt, callee_id: ast::node_id,
base: @ast::expr, n_method: uint)
-> lval_maybe_callee {
let {bcx, val} = trans_temp_expr(bcx, base);
let box_body = GEPi(bcx, val, [0, abi::box_field_body]);
let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, box_body, [0, 1]),
let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, val, [0, 0]),
T_ptr(T_ptr(T_dict()))));
let box = Load(bcx, GEPi(bcx, val, [0, 1]));
// FIXME[impl] I doubt this is alignment-safe
let self = PointerCast(bcx, GEPi(bcx, box_body, [0, 2]),
let self = PointerCast(bcx, GEPi(bcx, box, [0, abi::box_field_body]),
T_opaque_cbox_ptr(bcx_ccx(bcx)));
let iface_id = alt ty::get(expr_ty(bcx, base)).struct {
ty::ty_iface(did, _) { did }
// precondition
_ { bcx_tcx(bcx).sess.span_bug(base.span, "base has non-iface type \
in trans_iface_callee"); }
_ { fail "base has non-iface type in trans_iface_callee"; }
};
trans_vtable_callee(bcx, self, dict, callee_id, iface_id, n_method)
}
@ -360,20 +358,17 @@ fn trans_iface_wrapper(ccx: @crate_ctxt, pt: path, m: ty::method,
let {llty: llfty, _} = wrapper_fn_ty(ccx, T_ptr(T_i8()),
ty::mk_fn(ccx.tcx, m.fty), m.tps);
trans_wrapper(ccx, pt, llfty, {|llfn, bcx|
let self = Load(bcx, PointerCast(bcx,
LLVMGetParam(llfn, 2u as c_uint),
T_ptr(T_opaque_iface_ptr(ccx))));
let boxed = GEPi(bcx, self, [0, abi::box_field_body]);
let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, boxed, [0, 1]),
T_ptr(T_ptr(T_dict()))));
let param = PointerCast(bcx, LLVMGetParam(llfn, 2u as c_uint),
T_ptr(T_opaque_iface(ccx)));
let dict = Load(bcx, GEPi(bcx, param, [0, 0]));
let box = Load(bcx, GEPi(bcx, param, [0, 1]));
let self = GEPi(bcx, box, [0, abi::box_field_body]);
let vtable = PointerCast(bcx, Load(bcx, GEPi(bcx, dict, [0, 0])),
T_ptr(T_array(T_ptr(llfty), n + 1u)));
let mptr = Load(bcx, GEPi(bcx, vtable, [0, n as int]));
// FIXME[impl] This doesn't account for more-than-ptr-sized alignment
let inner_self = GEPi(bcx, boxed, [0, 2]);
let args = [PointerCast(bcx, dict, T_ptr(T_i8())),
LLVMGetParam(llfn, 1u as c_uint),
PointerCast(bcx, inner_self, T_opaque_cbox_ptr(ccx))];
PointerCast(bcx, self, T_opaque_cbox_ptr(ccx))];
let i = 3u as c_uint, total = llvm::LLVMCountParamTypes(llfty);
while i < total {
args += [LLVMGetParam(llfn, i)];
@ -531,18 +526,18 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
fn trans_cast(bcx: @block_ctxt, val: @ast::expr, id: ast::node_id, dest: dest)
-> @block_ctxt {
let ccx = bcx_ccx(bcx), tcx = ccx.tcx;
let val_ty = expr_ty(bcx, val);
if dest == ignore { ret trans_expr(bcx, val, ignore); }
let ccx = bcx_ccx(bcx);
let v_ty = expr_ty(bcx, val);
let {bcx, box, body} = trans_malloc_boxed(bcx, v_ty);
add_clean_free(bcx, box, false);
bcx = trans_expr_save_in(bcx, val, body);
revoke_clean(bcx, box);
let result = get_dest_addr(dest);
Store(bcx, box, PointerCast(bcx, GEPi(bcx, result, [0, 1]),
T_ptr(val_ty(box))));
let {bcx, val: dict} = get_dict(bcx, ccx.dict_map.get(id)[0]);
let body_ty = ty::mk_tup(tcx, [ty::mk_type(tcx), ty::mk_type(tcx),
val_ty]);
let ti = none;
let {bcx, val: tydesc} = get_tydesc(bcx, body_ty, true, ti).result;
lazily_emit_all_tydesc_glue(ccx, ti);
let {bcx, box, body: box_body} = trans_malloc_boxed(bcx, body_ty);
Store(bcx, tydesc, GEPi(bcx, box_body, [0, 0]));
Store(bcx, PointerCast(bcx, dict, T_ptr(ccx.tydesc_type)),
GEPi(bcx, box_body, [0, 1]));
bcx = trans_expr_save_in(bcx, val, GEPi(bcx, box_body, [0, 2]));
store_in_dest(bcx, PointerCast(bcx, box, T_opaque_iface_ptr(ccx)), dest)
Store(bcx, dict, PointerCast(bcx, GEPi(bcx, result, [0, 0]),
T_ptr(val_ty(dict))));
bcx
}

View File

@ -615,7 +615,7 @@ fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool }
fn type_is_structural(ty: t) -> bool {
alt get(ty).struct {
ty_rec(_) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) |
ty_res(_, _, _) { true }
ty_iface(_, _) | ty_res(_, _, _) { true }
_ { false }
}
}
@ -666,7 +666,7 @@ pure fn type_is_box(ty: t) -> bool {
pure fn type_is_boxed(ty: t) -> bool {
alt get(ty).struct {
ty_box(_) | ty_iface(_, _) | ty_opaque_box { true }
ty_box(_) | ty_opaque_box { true }
_ { false }
}
}

View File

@ -51,12 +51,13 @@ const uint8_t SHAPE_OBJ = 19u;
const uint8_t SHAPE_RES = 20u;
const uint8_t SHAPE_VAR = 21u;
const uint8_t SHAPE_UNIQ = 22u;
const uint8_t SHAPE_IFACE = 24u;
const uint8_t SHAPE_IFACE_OLD = 24u;
const uint8_t SHAPE_UNIQ_FN = 25u;
const uint8_t SHAPE_STACK_FN = 26u;
const uint8_t SHAPE_BARE_FN = 27u;
const uint8_t SHAPE_TYDESC = 28u;
const uint8_t SHAPE_SEND_TYDESC = 29u;
const uint8_t SHAPE_IFACE = 31u;
#ifdef _LP64
const uint8_t SHAPE_PTR = SHAPE_U64;
@ -381,7 +382,7 @@ ctxt<T>::walk() {
case SHAPE_RES: walk_res0(); break;
case SHAPE_VAR: walk_var0(); break;
case SHAPE_UNIQ: walk_uniq0(); break;
case SHAPE_IFACE: WALK_SIMPLE(walk_iface1); break;
case SHAPE_IFACE_OLD: WALK_SIMPLE(walk_iface1); break;
case SHAPE_BOX_FN:
case SHAPE_UNIQ_FN:
case SHAPE_STACK_FN: