diff options
| author | Graydon Hoare <[email protected]> | 2011-01-17 15:22:36 -0800 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-01-17 15:22:45 -0800 |
| commit | 5f591c37671ad1e3932d8a5c27124eb52903026c (patch) | |
| tree | 6fe6e280e2289713fa11db94b03f36a0f875a7c2 /src | |
| parent | Enable more tests. (diff) | |
| download | rust-5f591c37671ad1e3932d8a5c27124eb52903026c.tar.xz rust-5f591c37671ad1e3932d8a5c27124eb52903026c.zip | |
Allocate and reload retslots. Copy into them on polymorphic returns.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/trans.rs | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3a453db5..62c8a4fb 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1996,12 +1996,14 @@ impure fn trans_args(@block_ctxt cx, option.t[generic_info] gen, &vec[@ast.expr] es, @ty.t fn_ty) - -> tup(@block_ctxt, vec[ValueRef]) { + -> tup(@block_ctxt, vec[ValueRef], option.t[ValueRef]) { let vec[ValueRef] vs = vec(cx.fcx.lltaskptr); let @block_ctxt bcx = cx; let vec[ty.arg] args = ty.ty_fn_args(fn_ty); + let option.t[ValueRef] llretslot_opt = none[ValueRef]; + alt (gen) { case (some[generic_info](?g)) { for (ValueRef t in g.tydescs) { @@ -2009,9 +2011,12 @@ impure fn trans_args(@block_ctxt cx, } args = ty.ty_fn_args(g.item_type); if (ty.type_has_dynamic_size(ty.ty_fn_ret(g.item_type))) { - // FIXME: allocate real outptr in caller, - // pass in to here. - vs += C_null(T_typaram_ptr()); + auto retty = ty.ty_fn_ret(fn_ty); + auto llretty = type_of(cx.fcx.ccx, retty); + auto llretslot = cx.build.Alloca(llretty); + llretslot = cx.build.PointerCast(llretslot, T_ptr(T_i8())); + vs += llretslot; + llretslot_opt = some[ValueRef](llretslot); } } case (_) { } @@ -2076,7 +2081,7 @@ impure fn trans_args(@block_ctxt cx, i += 1u; } - ret tup(bcx, vs); + ret tup(bcx, vs, llretslot_opt); } impure fn trans_bind_thunk(@crate_ctxt cx, @@ -2311,29 +2316,40 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f, f_res.generic, args, fn_ty); - auto real_retval = args_res._0.build.FastCall(faddr, args_res._1); + auto bcx = args_res._0; + auto real_retval = bcx.build.FastCall(faddr, args_res._1); auto retval; - if (ty.type_is_nil(ret_ty)) { - retval = C_nil(); - } else { - retval = real_retval; - } - // Structured returns come back as first-class values. This is nice for - // LLVM but wrong for us; we treat structured values by pointer in - // most of our code here. So spill it to an alloca. - if (ty.type_is_structural(ret_ty)) { - auto local = args_res._0.build.Alloca(type_of(cx.fcx.ccx, ret_ty)); - args_res._0.build.Store(retval, local); - retval = local; + // Check for a generic retslot. + alt (args_res._2) { + case (some[ValueRef](?llretslot)) { + retval = bcx.build.Load(llretslot); + } + case (none[ValueRef]) { + retval = real_retval; + + if (ty.type_is_nil(ret_ty)) { + retval = C_nil(); + } else if (ty.type_is_structural(ret_ty)) { + // Structured returns come back as first-class values. This is + // nice for LLVM but wrong for us; we treat structured values + // by pointer in most of our code here. So spill it to an + // alloca. + auto local = bcx.build.Alloca(type_of(cx.fcx.ccx, ret_ty)); + bcx.build.Store(retval, local); + retval = local; + } + } } + + // 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 += clean(bind drop_ty(_, retval, ret_ty)); - ret res(args_res._0, retval); + ret res(bcx, retval); } impure fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, |