diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-01-18 15:42:00 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-01-18 17:20:46 -0800 |
| commit | da828747e6d291f92046b6333ba2bca71ca58752 (patch) | |
| tree | 4e61884e546f97e6c5662646f1c2cd380d4e1fa0 /src | |
| parent | 2286d8c17e5bf3d4312357eba9a845262068f007 (diff) | |
| download | rust-da828747e6d291f92046b6333ba2bca71ca58752.tar.gz rust-da828747e6d291f92046b6333ba2bca71ca58752.zip | |
correct use of GEP_tup_like in closure constr
also, streamline type_is_tup_like() to the cases which actually work
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/trans.rs | 7 | ||||
| -rw-r--r-- | src/comp/middle/trans_closure.rs | 49 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 8 | ||||
| -rw-r--r-- | src/test/run-pass/alignment-gep-tup-like-1.rs | 14 | ||||
| -rw-r--r-- | src/test/run-pass/alignment-gep-tup-like-2.rs | 16 |
5 files changed, 66 insertions, 28 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 46e742a24ef..16148c360a5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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)); } diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index 4a2c6756428..7c12f223a2f 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -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; diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 586e8b166a2..fee19a7b660 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -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 { diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs new file mode 100644 index 00000000000..0e25b86c90d --- /dev/null +++ b/src/test/run-pass/alignment-gep-tup-like-1.rs @@ -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; +} \ No newline at end of file diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs new file mode 100644 index 00000000000..3de5c2bc1e9 --- /dev/null +++ b/src/test/run-pass/alignment-gep-tup-like-2.rs @@ -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; +} \ No newline at end of file |
