correct use of GEP_tup_like in closure constr
also, streamline type_is_tup_like() to the cases which actually work
This commit is contained in:
parent
2286d8c17e
commit
da828747e6
@ -691,6 +691,9 @@ fn GEP_tup_like(bcx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
|
||||
: type_is_tup_like(bcx, t) -> result {
|
||||
// It might be a static-known type. Handle this.
|
||||
if !ty::type_has_dynamic_size(bcx_tcx(bcx), t) {
|
||||
#debug["GEP_tup_like t=%? ixs=%? -> static",
|
||||
ty_to_str(bcx_tcx(bcx), t), ixs];
|
||||
|
||||
ret rslt(bcx, GEPi(bcx, base, ixs));
|
||||
}
|
||||
// It is a dynamic-containing type that, if we convert directly to an LLVM
|
||||
@ -758,6 +761,10 @@ fn GEP_tup_like(bcx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
|
||||
for typ: ty::t in s.prefix { args += [typ]; }
|
||||
let prefix_ty = ty::mk_tup(bcx_tcx(bcx), args);
|
||||
|
||||
#debug["GEP_tup_like t=%? ixs=%? prefix_ty=%?",
|
||||
ty_to_str(bcx_tcx(bcx), t), ixs,
|
||||
ty_to_str(bcx_tcx(bcx), prefix_ty)];
|
||||
|
||||
let sz = size_of_(bcx, prefix_ty, align_next(s.target));
|
||||
ret rslt(sz.bcx, bump_ptr(sz.bcx, s.target, base, sz.val));
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ fn allocate_cbox(bcx: @block_ctxt,
|
||||
|
||||
type closure_result = {
|
||||
llbox: ValueRef, // llvalue of ptr to closure
|
||||
cboxptr_ty: ty::t, // type of ptr to closure
|
||||
cbox_ty: ty::t, // type of the closure data
|
||||
bcx: @block_ctxt // final bcx
|
||||
};
|
||||
|
||||
@ -332,12 +332,12 @@ fn store_environment(
|
||||
// whatever.
|
||||
let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mut:ast::imm});
|
||||
let llbox = cast_if_we_can(bcx, llbox, cboxptr_ty);
|
||||
check type_is_tup_like(bcx, cboxptr_ty);
|
||||
check type_is_tup_like(bcx, cbox_ty);
|
||||
|
||||
// If necessary, copy tydescs describing type parameters into the
|
||||
// appropriate slot in the closure.
|
||||
let {bcx:bcx, val:ty_params_slot} =
|
||||
GEP_tup_like_1(bcx, cboxptr_ty, llbox, [0, abi::cbox_elt_ty_params]);
|
||||
GEP_tup_like(bcx, cbox_ty, llbox, [0, abi::cbox_elt_ty_params]);
|
||||
let off = 0;
|
||||
for tp in lltyparams {
|
||||
let cloned_td = maybe_clone_tydesc(bcx, ck, tp.desc);
|
||||
@ -354,15 +354,16 @@ fn store_environment(
|
||||
|
||||
// Copy expr values into boxed bindings.
|
||||
// Silly check
|
||||
let {bcx: bcx, val:bindings_slot} =
|
||||
GEP_tup_like_1(bcx, cboxptr_ty, llbox, [0, abi::cbox_elt_bindings]);
|
||||
vec::iteri(bound_values) { |i, bv|
|
||||
if (!ccx.sess.opts.no_asm_comments) {
|
||||
add_comment(bcx, #fmt("Copy %s into closure",
|
||||
ev_to_str(ccx, bv)));
|
||||
}
|
||||
|
||||
let bound_data = GEPi(bcx, bindings_slot, [0, i as int]);
|
||||
let bound_data = GEP_tup_like_1(bcx, cbox_ty, llbox,
|
||||
[0, abi::cbox_elt_bindings, i as int]);
|
||||
bcx = bound_data.bcx;
|
||||
let bound_data = bound_data.val;
|
||||
alt bv {
|
||||
env_expr(e) {
|
||||
bcx = trans::trans_expr_save_in(bcx, e, bound_data);
|
||||
@ -397,7 +398,7 @@ fn store_environment(
|
||||
}
|
||||
for cleanup in temp_cleanups { revoke_clean(bcx, cleanup); }
|
||||
|
||||
ret {llbox: llbox, cboxptr_ty: cboxptr_ty, bcx: bcx};
|
||||
ret {llbox: llbox, cbox_ty: cbox_ty, bcx: bcx};
|
||||
}
|
||||
|
||||
// Given a context and a list of upvars, build a closure. This just
|
||||
@ -441,13 +442,15 @@ fn build_closure(bcx0: @block_ctxt,
|
||||
// with the upvars and type descriptors.
|
||||
fn load_environment(enclosing_cx: @block_ctxt,
|
||||
fcx: @fn_ctxt,
|
||||
cboxptr_ty: ty::t,
|
||||
cbox_ty: ty::t,
|
||||
cap_vars: [capture::capture_var],
|
||||
ck: ty::closure_kind) {
|
||||
let bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
|
||||
let ccx = bcx_ccx(bcx);
|
||||
let tcx = bcx_tcx(bcx);
|
||||
|
||||
let sp = bcx.sp;
|
||||
let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mut:ast::imm});
|
||||
check (type_has_static_size(ccx, cboxptr_ty));
|
||||
let llty = type_of(ccx, sp, cboxptr_ty);
|
||||
let llclosure = PointerCast(bcx, fcx.llenv, llty);
|
||||
@ -479,9 +482,9 @@ fn load_environment(enclosing_cx: @block_ctxt,
|
||||
alt cap_var.mode {
|
||||
capture::cap_drop. { /* ignore */ }
|
||||
_ {
|
||||
check type_is_tup_like(bcx, cboxptr_ty);
|
||||
check type_is_tup_like(bcx, cbox_ty);
|
||||
let upvarptr = GEP_tup_like(
|
||||
bcx, cboxptr_ty, llclosure, path + [i as int]);
|
||||
bcx, cbox_ty, llclosure, path + [i as int]);
|
||||
bcx = upvarptr.bcx;
|
||||
let llupvarptr = upvarptr.val;
|
||||
alt ck {
|
||||
@ -516,9 +519,9 @@ fn trans_expr_fn(bcx: @block_ctxt,
|
||||
let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef {
|
||||
let cap_vars = capture::compute_capture_vars(
|
||||
ccx.tcx, id, proto, cap_clause);
|
||||
let {llbox, cboxptr_ty, bcx} = build_closure(bcx, cap_vars, ck);
|
||||
let {llbox, cbox_ty, bcx} = build_closure(bcx, cap_vars, ck);
|
||||
trans_closure(sub_cx, sp, decl, body, llfn, no_self, [], id, {|fcx|
|
||||
load_environment(bcx, fcx, cboxptr_ty, cap_vars, ck);
|
||||
load_environment(bcx, fcx, cbox_ty, cap_vars, ck);
|
||||
});
|
||||
llbox
|
||||
};
|
||||
@ -616,7 +619,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
|
||||
};
|
||||
|
||||
// Actually construct the closure
|
||||
let {llbox, cboxptr_ty, bcx} = store_environment(
|
||||
let {llbox, cbox_ty, bcx} = store_environment(
|
||||
bcx, vec::map(lltydescs, {|d| {desc: d, dicts: none}}),
|
||||
env_vals + vec::map(bound, {|x| env_expr(x)}),
|
||||
ty::ck_box);
|
||||
@ -624,7 +627,7 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
|
||||
// Make thunk
|
||||
let llthunk =
|
||||
trans_bind_thunk(cx.fcx.lcx, cx.sp, pair_ty, outgoing_fty_real, args,
|
||||
cboxptr_ty, *param_bounds, target_res);
|
||||
cbox_ty, *param_bounds, target_res);
|
||||
|
||||
// Fill the function pair
|
||||
fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
|
||||
@ -782,7 +785,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
|
||||
incoming_fty: ty::t,
|
||||
outgoing_fty: ty::t,
|
||||
args: [option::t<@ast::expr>],
|
||||
cboxptr_ty: ty::t,
|
||||
cbox_ty: ty::t,
|
||||
param_bounds: [ty::param_bounds],
|
||||
target_fn: option::t<ValueRef>)
|
||||
-> {val: ValueRef, ty: TypeRef} {
|
||||
@ -794,6 +797,7 @@ fn trans_bind_thunk(cx: @local_ctxt,
|
||||
*/
|
||||
// but since we don't, we have to do the checks at the beginning.
|
||||
let ccx = cx.ccx;
|
||||
let tcx = ccx_tcx(ccx);
|
||||
check type_has_static_size(ccx, incoming_fty);
|
||||
|
||||
// Here we're not necessarily constructing a thunk in the sense of
|
||||
@ -838,7 +842,8 @@ fn trans_bind_thunk(cx: @local_ctxt,
|
||||
// to the original function. So, let's create one of those:
|
||||
|
||||
// The llenv pointer needs to be the correct size. That size is
|
||||
// 'cboxptr_ty', which was determined by trans_bind.
|
||||
// 'cbox_ty', which was determined by trans_bind.
|
||||
let cboxptr_ty = ty::mk_ptr(tcx, {ty:cbox_ty, mut:ast::imm});
|
||||
check type_has_static_size(ccx, cboxptr_ty);
|
||||
let llclosure_ptr_ty = type_of(ccx, sp, cboxptr_ty);
|
||||
let llclosure = PointerCast(l_bcx, fcx.llenv, llclosure_ptr_ty);
|
||||
@ -854,9 +859,9 @@ fn trans_bind_thunk(cx: @local_ctxt,
|
||||
}
|
||||
none. {
|
||||
// Silly check
|
||||
check type_is_tup_like(bcx, cboxptr_ty);
|
||||
check type_is_tup_like(bcx, cbox_ty);
|
||||
let {bcx: cx, val: pair} =
|
||||
GEP_tup_like(bcx, cboxptr_ty, llclosure,
|
||||
GEP_tup_like(bcx, cbox_ty, llclosure,
|
||||
[0, abi::cbox_elt_bindings, 0]);
|
||||
let lltargetenv =
|
||||
Load(cx, GEPi(cx, pair, [0, abi::fn_field_box]));
|
||||
@ -891,9 +896,9 @@ fn trans_bind_thunk(cx: @local_ctxt,
|
||||
let llargs: [ValueRef] = [llretptr, lltargetenv];
|
||||
|
||||
// Copy in the type parameters.
|
||||
check type_is_tup_like(l_bcx, cboxptr_ty);
|
||||
check type_is_tup_like(l_bcx, cbox_ty);
|
||||
let {bcx: l_bcx, val: param_record} =
|
||||
GEP_tup_like(l_bcx, cboxptr_ty, llclosure,
|
||||
GEP_tup_like(l_bcx, cbox_ty, llclosure,
|
||||
[0, abi::cbox_elt_ty_params]);
|
||||
let off = 0;
|
||||
for param in param_bounds {
|
||||
@ -932,9 +937,9 @@ fn trans_bind_thunk(cx: @local_ctxt,
|
||||
// closure.
|
||||
some(e) {
|
||||
// Silly check
|
||||
check type_is_tup_like(bcx, cboxptr_ty);
|
||||
check type_is_tup_like(bcx, cbox_ty);
|
||||
let bound_arg =
|
||||
GEP_tup_like(bcx, cboxptr_ty, llclosure,
|
||||
GEP_tup_like(bcx, cbox_ty, llclosure,
|
||||
[0, abi::cbox_elt_bindings, b]);
|
||||
bcx = bound_arg.bcx;
|
||||
let val = bound_arg.val;
|
||||
|
@ -859,8 +859,7 @@ fn sequence_element_type(cx: ctxt, ty: t) -> t {
|
||||
pure fn type_is_tup_like(cx: ctxt, ty: t) -> bool {
|
||||
let sty = struct(cx, ty);
|
||||
alt sty {
|
||||
ty_ptr(_) | ty_uniq(_) |
|
||||
ty_box(_) | ty_rec(_) | ty_tup(_) | ty_tag(_,_) { true }
|
||||
ty_rec(_) | ty_tup(_) { true }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
@ -871,12 +870,9 @@ fn get_element_type(cx: ctxt, ty: t, i: uint) -> t {
|
||||
ty_tup(ts) { ret ts[i]; }
|
||||
_ {
|
||||
cx.sess.bug("get_element_type called on type " + ty_to_str(cx, ty) +
|
||||
" - expected a \
|
||||
tuple or record");
|
||||
" - expected a tuple or record");
|
||||
}
|
||||
}
|
||||
// NB: This is not exhaustive -- struct(cx, ty) could be a box or a
|
||||
// tag.
|
||||
}
|
||||
|
||||
pure fn type_is_box(cx: ctxt, ty: t) -> bool {
|
||||
|
14
src/test/run-pass/alignment-gep-tup-like-1.rs
Normal file
14
src/test/run-pass/alignment-gep-tup-like-1.rs
Normal file
@ -0,0 +1,14 @@
|
||||
type pair<A,B> = {
|
||||
a: A, b: B
|
||||
};
|
||||
|
||||
fn f<A:copy>(a: A, b: u16) -> fn@() -> (A, u16) {
|
||||
fn@() -> (A, u16) { (a, b) }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (a, b) = f(22_u64, 44u16)();
|
||||
#debug["a=%? b=%?", a, b];
|
||||
assert a == 22u64;
|
||||
assert b == 44u16;
|
||||
}
|
16
src/test/run-pass/alignment-gep-tup-like-2.rs
Normal file
16
src/test/run-pass/alignment-gep-tup-like-2.rs
Normal file
@ -0,0 +1,16 @@
|
||||
type pair<A,B> = {
|
||||
a: A, b: B
|
||||
};
|
||||
|
||||
fn f<A:send,B:send>(a: A, b: B) -> fn~() -> (A, B) {
|
||||
fn~() -> (A, B) { (a, b) }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 22_u8;
|
||||
let y = 44_u64;
|
||||
let (a, b) = f(~x, ~y)();
|
||||
#debug["a=%? b=%?", *a, *b];
|
||||
assert *a == x;
|
||||
assert *b == y;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user