diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-11-16 12:32:38 +0100 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-11-18 12:49:00 +0100 |
| commit | 4e0311214160ea0dc7d1ff7347db6c6550c79de2 (patch) | |
| tree | c4024b2ab58c93b1441e887e0f3e93936d2dc530 /src/comp/middle | |
| parent | 6297fc979ee715c276b5303decf2220e70629917 (diff) | |
| download | rust-4e0311214160ea0dc7d1ff7347db6c6550c79de2.tar.gz rust-4e0311214160ea0dc7d1ff7347db6c6550c79de2.zip | |
Add a pass-by-copy parameter passing convention
This is intended to solve the problem of how to pass arguments to constructor functions -- you want to move in rvalues, but not have to explicitly copy stuff that is not an rvalue. The by-copy passing convention will ensure the callee gets its own copy of the value. For rvalues, it'll just pass off the value. For lvalues, it'll make a copy. Issue #1177
Diffstat (limited to 'src/comp/middle')
| -rw-r--r-- | src/comp/middle/alias.rs | 5 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 14 |
2 files changed, 15 insertions, 4 deletions
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 88d4f3b56a5..b4cd16d1ee9 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -255,7 +255,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { local_id: 0u, unsafe_tys: unsafe_set(root.mut), mutable copied: alt arg_t.mode { - ast::by_move. { copied } + ast::by_move. | ast::by_copy. { copied } ast::by_mut_ref. { not_allowed } _ { i + 1u == by_ref ? not_allowed : not_copied } }}]; @@ -337,6 +337,9 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id, if arg.mode == ast::by_move { bad = some("a move-mode parameter"); } + if arg.mode == ast::by_copy { + bad = some("a copy-mode parameter"); + } if cur_node != arg_node_id { bad = some("the wrong parameter"); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d5d2620fa6f..b57953d20a6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -67,8 +67,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, sp: span, inputs: [ty::arg]) -> // that would obviate the need for this check check non_ty_var(cx, arg_ty); let llty = type_of_inner(cx, sp, arg_ty); - if arg.mode == ast::by_val { atys += [llty]; } - else { atys += [T_ptr(llty)]; } + atys += [arg.mode == ast::by_val ? llty : T_ptr(llty)]; } ret atys; } @@ -3636,6 +3635,15 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef, if arg.mode == ast::by_val && (lv.kind == owned || !imm) { val = Load(bcx, val); } + } else if arg.mode == ast::by_copy { + let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty); + bcx = cx; + if lv.kind == temporary { revoke_clean(bcx, val); } + if lv.kind == owned || !ty::type_is_immediate(ccx.tcx, e_ty) { + bcx = memmove_ty(bcx, alloc, val, e_ty); + } else { Store(bcx, val, alloc); } + val = alloc; + if lv.kind != temporary { bcx = take_ty(bcx, val, e_ty); } } else if ty::type_is_immediate(ccx.tcx, e_ty) && lv.kind != owned { let r = do_spill(bcx, val, e_ty); val = r.val; @@ -4989,7 +4997,7 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], let argval = alt fcx.llargs.get(id) { local_mem(v) { v } }; alt arg.mode { ast::by_mut_ref. { } - ast::by_move. { add_clean(bcx, argval, arg.ty); } + ast::by_move. | ast::by_copy. { add_clean(bcx, argval, arg.ty); } ast::by_val. { if !ty::type_is_immediate(bcx_tcx(bcx), arg.ty) { let {bcx: cx, val: alloc} = alloc_ty(bcx, arg.ty); |
