]> git.lizzy.rs Git - rust.git/commitdiff
correct use of GEP_tup_like in closure constr
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 18 Jan 2012 23:42:00 +0000 (15:42 -0800)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 19 Jan 2012 01:20:46 +0000 (17:20 -0800)
also, streamline type_is_tup_like() to the cases which
actually work

src/comp/middle/trans.rs
src/comp/middle/trans_closure.rs
src/comp/middle/ty.rs
src/test/run-pass/alignment-gep-tup-like-1.rs [new file with mode: 0644]
src/test/run-pass/alignment-gep-tup-like-2.rs [new file with mode: 0644]

index 46e742a24effc0744c84f694983c86386c6e1adc..16148c360a5810c27c97fb58b518152c46e7b4b9 100644 (file)
@@ -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 split_type(ccx: @crate_ctxt, t: ty::t, ixs: [int], n: uint) ->
     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));
 }
index 4a2c6756428f9686ed17a06e69ce4a8dfe736afd..7c12f223a2f90f7f45bb7575e3f9003f7bacd405 100644 (file)
@@ -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 maybe_clone_tydesc(bcx: @block_ctxt,
     // 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 maybe_clone_tydesc(bcx: @block_ctxt,
 
     // 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 maybe_clone_tydesc(bcx: @block_ctxt,
     }
     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;
index 586e8b166a2f1fee929b46a85c4447b6c8c29b62..fee19a7b660a3481bcc57f0cf391a3eea5aba929 100644 (file)
@@ -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 (file)
index 0000000..0e25b86
--- /dev/null
@@ -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 (file)
index 0000000..3de5c2b
--- /dev/null
@@ -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