aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-04-23 14:17:44 -0700
committerGraydon Hoare <[email protected]>2011-04-23 14:22:10 -0700
commit912c1fc81c844fcffecbae638a4adb629a68cbfb (patch)
treec3d80c2ed430fc104d8cb0bc030ba5ccc58f1969
parentrustc: Use a silly "magic numbers" hack; seems to speed things up a bit. (diff)
downloadrust-912c1fc81c844fcffecbae638a4adb629a68cbfb.tar.xz
rust-912c1fc81c844fcffecbae638a4adb629a68cbfb.zip
Fix busted iter/put code. Un-XFAIL foreach-box-drop.rs.
-rw-r--r--src/comp/middle/trans.rs189
-rw-r--r--src/test/run-pass/foreach-box-drop.rs2
2 files changed, 94 insertions, 97 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index cf16d317..f4901123 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -641,7 +641,7 @@ fn type_of_fn_full(@crate_ctxt cx,
atys +=
vec(T_fn_pair(cx.tn,
type_of_fn_full(cx, ast.proto_fn, none[TypeRef],
- vec(rec(mode=ast.val, ty=output)),
+ vec(rec(mode=ast.alias, ty=output)),
ty.mk_nil(cx.tystore), 0u)));
}
@@ -3553,17 +3553,15 @@ fn trans_for_each(@block_ctxt cx,
// pointer along with the foreach-body-fn pointer into a 'normal' fn pair
// and pass it in as a first class fn-arg to the iterator.
- auto iter_body_llty = type_of_fn_full(lcx.ccx, ast.proto_fn,
- none[TypeRef],
- vec(rec(mode=ast.val, ty=decl_ty)),
- ty.mk_nil(lcx.ccx.tystore), 0u);
+ auto iter_body_llty =
+ type_of_fn_full(lcx.ccx, ast.proto_fn,
+ none[TypeRef],
+ vec(rec(mode=ast.alias, ty=decl_ty)),
+ ty.mk_nil(lcx.ccx.tystore), 0u);
let ValueRef lliterbody = decl_internal_fastcall_fn(lcx.ccx.llmod,
s, iter_body_llty);
- // FIXME: handle ty params properly.
- let vec[ast.ty_param] ty_params = vec();
-
auto fcx = new_fn_ctxt(lcx, lliterbody);
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
@@ -3601,12 +3599,8 @@ fn trans_for_each(@block_ctxt cx,
i += 1u;
}
- // Treat the loop variable as an upvar as well. We copy it to an alloca
- // as usual.
- auto lllvar = llvm.LLVMGetParam(fcx.llfn, 3u);
- auto lllvarptr = alloca(bcx, val_ty(lllvar));
- bcx.build.Store(lllvar, lllvarptr);
- fcx.llupvars.insert(decl_id, lllvarptr);
+ // Add an upvar for the loop variable alias.
+ fcx.llupvars.insert(decl_id, llvm.LLVMGetParam(fcx.llfn, 3u));
auto r = trans_block(bcx, body);
@@ -4570,6 +4564,68 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
}
}
+fn trans_arg_expr(@block_ctxt cx,
+ ty.arg arg,
+ TypeRef lldestty0,
+ @ast.expr e) -> result {
+
+ auto val;
+ auto bcx = cx;
+ auto e_ty = ty.expr_ty(cx.fcx.lcx.ccx.tystore, e);
+
+ if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore, e_ty)) {
+ auto re = trans_expr(bcx, e);
+ val = re.val;
+ bcx = re.bcx;
+ } else if (arg.mode == ast.alias) {
+ let lval_result lv;
+ if (ty.is_lval(e)) {
+ lv = trans_lval(bcx, e);
+ } else {
+ auto r = trans_expr(bcx, e);
+ if (type_is_immediate(cx.fcx.lcx.ccx, e_ty)) {
+ lv = lval_val(r.bcx, r.val);
+ } else {
+ lv = lval_mem(r.bcx, r.val);
+ }
+ }
+ bcx = lv.res.bcx;
+
+ if (lv.is_mem) {
+ val = lv.res.val;
+ } else {
+ // Non-mem but we're trying to alias; synthesize an
+ // alloca, spill to it and pass its address.
+ val = do_spill(lv.res.bcx, lv.res.val);
+ }
+ } else {
+ auto re = trans_expr(bcx, e);
+ val = re.val;
+ bcx = re.bcx;
+ }
+
+ if (ty.count_ty_params(cx.fcx.lcx.ccx.tystore, arg.ty) > 0u) {
+ auto lldestty = lldestty0;
+ if (arg.mode == ast.val) {
+ // FIXME: we'd prefer to use &&, but rustboot doesn't like it
+ if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore, e_ty)) {
+ lldestty = T_ptr(lldestty);
+ }
+ }
+ val = bcx.build.PointerCast(val, lldestty);
+ }
+
+ if (arg.mode == ast.val) {
+ // FIXME: we'd prefer to use &&, but rustboot doesn't like it
+ if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore, e_ty)) {
+ // Until here we've been treating structures by pointer;
+ // we are now passing it as an arg, so need to load it.
+ val = bcx.build.Load(val);
+ }
+ }
+ ret res(bcx, val);
+}
+
// NB: must keep 4 fns in sync:
//
// - type_of_fn_full
@@ -4660,68 +4716,9 @@ fn trans_args(@block_ctxt cx,
auto i = 0u;
for (@ast.expr e in es) {
- auto mode = args.(i).mode;
-
- auto val;
- if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore,
- ty.expr_ty(cx.fcx.lcx.ccx.tystore, e))) {
- auto re = trans_expr(bcx, e);
- val = re.val;
- bcx = re.bcx;
- } else if (mode == ast.alias) {
- let lval_result lv;
- if (ty.is_lval(e)) {
- lv = trans_lval(bcx, e);
- } else {
- auto r = trans_expr(bcx, e);
- if (type_is_immediate(cx.fcx.lcx.ccx,
- ty.expr_ty(cx.fcx.lcx.ccx.tystore,
- e))) {
- lv = lval_val(r.bcx, r.val);
- } else {
- lv = lval_mem(r.bcx, r.val);
- }
- }
- bcx = lv.res.bcx;
-
- if (lv.is_mem) {
- val = lv.res.val;
- } else {
- // Non-mem but we're trying to alias; synthesize an
- // alloca, spill to it and pass its address.
- val = do_spill(lv.res.bcx, lv.res.val);
- }
-
- } else {
- auto re = trans_expr(bcx, e);
- val = re.val;
- bcx = re.bcx;
- }
-
- if (ty.count_ty_params(cx.fcx.lcx.ccx.tystore, args.(i).ty) > 0u) {
- auto lldestty = arg_tys.(i);
- if (mode == ast.val) {
- // FIXME: we'd prefer to use &&, but rustboot doesn't like it
- if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore,
- ty.expr_ty(cx.fcx.lcx.ccx.tystore, e))) {
- lldestty = T_ptr(lldestty);
- }
- }
-
- val = bcx.build.PointerCast(val, lldestty);
- }
-
- if (mode == ast.val) {
- // FIXME: we'd prefer to use &&, but rustboot doesn't like it
- if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore,
- ty.expr_ty(cx.fcx.lcx.ccx.tystore, e))) {
- // Until here we've been treating structures by pointer;
- // we are now passing it as an arg, so need to load it.
- val = bcx.build.Load(val);
- }
- }
-
- llargs += vec(val);
+ auto r = trans_arg_expr(bcx, args.(i), arg_tys.(i), e);
+ bcx = r.bcx;
+ llargs += vec(r.val);
i += 1u;
}
@@ -4797,15 +4794,23 @@ fn trans_call(@block_ctxt cx, @ast.expr f,
bcx.build.FastCall(faddr, llargs);
auto retval = C_nil();
- if (!ty.type_is_nil(cx.fcx.lcx.ccx.tystore, ret_ty)) {
- retval = load_if_immediate(bcx, llretslot, ret_ty);
- // Retval doesn't correspond to anything really tangible in the frame,
- // but it's a ref all the same, so we put a note here to drop it when
- // we're done in this scope.
- find_scope_cx(cx).cleanups +=
- vec(clean(bind drop_ty(_, retval, ret_ty)));
+ alt (lliterbody) {
+ case (none[ValueRef]) {
+ if (!ty.type_is_nil(cx.fcx.lcx.ccx.tystore, ret_ty)) {
+ retval = load_if_immediate(bcx, llretslot, ret_ty);
+ // Retval doesn't correspond to anything really tangible in
+ // the frame, but it's a ref all the same, so we put a note
+ // here to drop it when we're done in this scope.
+ find_scope_cx(cx).cleanups +=
+ vec(clean(bind drop_ty(_, retval, ret_ty)));
+ }
+ }
+ case (some[ValueRef](_)) {
+ // If there was an lliterbody, it means we were calling an
+ // iter, and we are *not* the party using its 'output' value,
+ // we should ignore llretslot.
+ }
}
-
ret res(bcx, retval);
}
@@ -5296,18 +5301,12 @@ fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
alt (e) {
case (none[@ast.expr]) { }
case (some[@ast.expr](?x)) {
- auto r = trans_expr(bcx, x);
-
- auto llarg = r.val;
+ auto e_ty = ty.expr_ty(cx.fcx.lcx.ccx.tystore, x);
+ auto arg = rec(mode=ast.alias, ty=e_ty);
+ auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, vec(arg));
+ auto r = trans_arg_expr(bcx, arg, arg_tys.(0), x);
bcx = r.bcx;
- if (ty.type_is_structural(cx.fcx.lcx.ccx.tystore,
- ty.expr_ty(cx.fcx.lcx.ccx.tystore, x))) {
- // Until here we've been treating structures by pointer; we
- // are now passing it as an arg, so need to load it.
- llarg = bcx.build.Load(llarg);
- }
-
- llargs += vec(llarg);
+ llargs += vec(r.val);
}
}
diff --git a/src/test/run-pass/foreach-box-drop.rs b/src/test/run-pass/foreach-box-drop.rs
index 26b2fb7f..50fc1816 100644
--- a/src/test/run-pass/foreach-box-drop.rs
+++ b/src/test/run-pass/foreach-box-drop.rs
@@ -1,5 +1,3 @@
-// xfail-stage0
-
obj ob[K](K k) {
iter foo() -> @tup(K) {
put @tup(k);