diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml index d33eb6d9020..ddf148380d0 100644 --- a/src/boot/me/semant.ml +++ b/src/boot/me/semant.ml @@ -1792,16 +1792,16 @@ let word_slot (abi:Abi.abi) : Ast.slot = interior_slot (Ast.TY_mach abi.Abi.abi_word_ty) ;; -let read_alias_slot (ty:Ast.ty) : Ast.slot = +let alias_slot (ty:Ast.ty) : Ast.slot = { Ast.slot_mode = Ast.MODE_alias; Ast.slot_mutable = false; Ast.slot_ty = Some ty } ;; -let word_write_alias_slot (abi:Abi.abi) : Ast.slot = +let mutable_alias_slot (ty:Ast.ty) : Ast.slot = { Ast.slot_mode = Ast.MODE_alias; Ast.slot_mutable = true; - Ast.slot_ty = Some (Ast.TY_mach abi.Abi.abi_word_ty) } + Ast.slot_ty = Some ty } ;; let mk_ty_fn_or_iter diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index cb492561226..99e53753ea2 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -27,6 +27,16 @@ type call = } ;; +let need_ty_fn ty = + match ty with + Ast.TY_fn tfn -> tfn + | _ -> bug () "need fn" +;; + +let call_output_slot call = + (fst (need_ty_fn call.call_callee_ty)).Ast.sig_output_slot +;; + let trans_visitor (cx:ctxt) (path:Ast.name_component Stack.t) @@ -240,10 +250,6 @@ let trans_visitor Il.Mem (mem, Il.ScalarTy (Il.ValTy word_bits)) in - let wordptr_at (mem:Il.mem) : Il.cell = - Il.Mem (mem, Il.ScalarTy (Il.AddrTy (Il.ScalarTy (Il.ValTy word_bits)))) - in - let mov (dst:Il.cell) (src:Il.operand) : unit = emit (Il.umov dst src) in @@ -1547,7 +1553,7 @@ let trans_visitor and ty_params_covering (t:Ast.ty) : Ast.slot = let n_ty_params = n_used_type_params t in let params = make_tydesc_slots n_ty_params in - read_alias_slot (Ast.TY_tup params) + alias_slot (Ast.TY_tup params) and get_drop_glue (ty:Ast.ty) @@ -1563,7 +1569,7 @@ let trans_visitor note_drop_step ty "drop-glue complete"; in let ty_params_ptr = ty_params_covering ty in - let fty = mk_simple_ty_fn [| ty_params_ptr; read_alias_slot ty |] in + let fty = mk_simple_ty_fn [| ty_params_ptr; alias_slot ty |] in get_typed_mem_glue g fty inner @@ -1632,7 +1638,7 @@ let trans_visitor mark_ty ty_params ty (deref cell) curr_iso in let ty_params_ptr = ty_params_covering ty in - let fty = mk_simple_ty_fn [| ty_params_ptr; read_alias_slot ty |] in + let fty = mk_simple_ty_fn [| ty_params_ptr; alias_slot ty |] in get_typed_mem_glue g fty inner @@ -1654,7 +1660,7 @@ let trans_visitor (interior_slot ty) (* dst *) [| ty_params_ptr; - read_alias_slot ty; (* src *) + alias_slot ty; (* src *) word_slot (* clone-task *) |] in @@ -1676,7 +1682,7 @@ let trans_visitor let fty = mk_ty_fn (interior_slot ty) - [| ty_params_ptr; read_alias_slot ty |] + [| ty_params_ptr; alias_slot ty |] in get_typed_mem_glue g fty inner @@ -1992,7 +1998,7 @@ let trans_visitor Ast.DOMAIN_thread -> begin trans_upcall "upcall_new_thread" new_task [| |]; - copy_fn_args false (CLONE_all new_task) call; + copy_fn_args false true (CLONE_all new_task) call; trans_upcall "upcall_start_thread" task_cell [| Il.Cell new_task; @@ -2004,7 +2010,7 @@ let trans_visitor | _ -> begin trans_upcall "upcall_new_task" new_task [| |]; - copy_fn_args false (CLONE_chan new_task) call; + copy_fn_args false true (CLONE_chan new_task) call; trans_upcall "upcall_start_task" task_cell [| Il.Cell new_task; @@ -3337,13 +3343,22 @@ let trans_visitor bound_arg_slots bound_args - and trans_arg0 (arg_cell:Il.cell) (output_cell:Il.cell) : unit = + and trans_arg0 (arg_cell:Il.cell) (initializing:bool) (call:call) : unit = (* Emit arg0 of any call: the output slot. *) iflog (fun _ -> annotate "fn-call arg 0: output slot"); - trans_init_slot_from_cell - CLONE_none - arg_cell (word_write_alias_slot abi) - output_cell word_slot + if not initializing + then + drop_slot + (get_ty_params_of_current_frame()) + call.call_output + (call_output_slot call) None; + (* We always get to the same state here: the output slot is uninitialized. + * We then do something that's illegal to do in the language, but legal + * here: alias the uninitialized memory. We are ok doing this because the + * call will fill it in before anyone else observes it. That's the + * point. + *) + mov arg_cell (Il.Cell (alias call.call_output)); and trans_arg1 (arg_cell:Il.cell) : unit = (* Emit arg1 of any call: the task pointer. *) @@ -3385,6 +3400,7 @@ let trans_visitor and copy_fn_args (tail_area:bool) + (initializing_arg0:bool) (clone:clone_ctrl) (call:call) : unit = @@ -3489,7 +3505,7 @@ let trans_visitor trans_arg1 callee_task_cell; - trans_arg0 callee_output_cell call.call_output + trans_arg0 callee_output_cell initializing_arg0 call @@ -3700,13 +3716,12 @@ let trans_visitor in iflog (fun _ -> annotate (Printf.sprintf "copy args for tail call to %s" (logname ()))); - copy_fn_args true CLONE_none call; + copy_fn_args true true CLONE_none call; drop_slots_at_curr_stmt(); abi.Abi.abi_emit_fn_tail_call (emitter()) (force_sz (current_fn_callsz())) caller_argsz callee_code callee_argsz; - and trans_prepare_call (initializing:bool) (logname:(unit -> string)) @@ -3716,17 +3731,8 @@ let trans_visitor let callee_fptr = callee_fn_ptr call.call_callee_ptr call.call_ctrl in iflog (fun _ -> annotate (Printf.sprintf "copy args for call to %s" (logname ()))); - copy_fn_args false CLONE_none call; + copy_fn_args false initializing CLONE_none call; iflog (fun _ -> annotate (Printf.sprintf "call %s" (logname ()))); - if not initializing - then - begin - match call.call_callee_ty with - Ast.TY_fn (tsig, _) -> - drop_slot (get_ty_params_of_current_frame()) call.call_output - tsig.Ast.sig_output_slot None; - | _ -> bug () "calling non-fn" - end; callee_fptr and callee_drop_slot @@ -3868,15 +3874,20 @@ let trans_visitor b - and trans_set_outptr (at:Ast.atom) : unit = - let (dst_mem, _) = - need_mem_cell - (deref (wordptr_at (fp_imm out_mem_disp))) + and get_current_output_cell_and_slot _ : (Il.cell * Ast.slot) = + let curr_fty = + need_ty_fn (Hashtbl.find cx.ctxt_all_item_types (current_fn())) in - let atom_ty = atom_type cx at in - let dst_slot = interior_slot atom_ty in - let dst_ty = referent_type abi atom_ty in - let dst_cell = Il.Mem (dst_mem, dst_ty) in + let curr_args = get_args_for_current_frame () in + let curr_outptr = + get_element_ptr curr_args Abi.calltup_elt_out_ptr + in + let dst_cell = deref curr_outptr in + let dst_slot = (fst curr_fty).Ast.sig_output_slot in + (dst_cell, dst_slot) + + and trans_set_outptr (at:Ast.atom) : unit = + let (dst_cell, dst_slot) = get_current_output_cell_and_slot () in trans_init_slot_from_atom CLONE_none dst_cell dst_slot at @@ -4239,26 +4250,13 @@ let trans_visitor emit (Il.jmp Il.JMP Il.CodeNone) | Ast.STMT_be (flv, args) -> - let ty = lval_ty cx flv in let ty_params = match htab_search cx.ctxt_call_lval_params (lval_base_id flv) with Some params -> params | None -> [| |] in - begin - match ty with - Ast.TY_fn (tsig, _) -> - let result_ty = slot_ty tsig.Ast.sig_output_slot in - let (dst_mem, _) = - need_mem_cell - (deref (wordptr_at (fp_imm out_mem_disp))) - in - let dst_rty = referent_type abi result_ty in - let dst_cell = Il.Mem (dst_mem, dst_rty) in - trans_be_fn cx dst_cell flv ty_params args - - | _ -> bug () "Calling unexpected lval." - end + let (dst_cell, _) = get_current_output_cell_and_slot () in + trans_be_fn cx dst_cell flv ty_params args | Ast.STMT_put atom_opt -> trans_put atom_opt @@ -4446,10 +4444,9 @@ let trans_visitor let ctor_ty = Hashtbl.find cx.ctxt_all_item_types obj_id in let obj_ty = - match ctor_ty with - Ast.TY_fn (tsig, _) -> slot_ty tsig.Ast.sig_output_slot - | _ -> bug () "object constructor doesn't have function type" + slot_ty (fst (need_ty_fn ctor_ty)).Ast.sig_output_slot in + let vtbl_ptr = get_obj_vtbl obj_id in let _ = iflog (fun _ -> annotate "calculate vtbl-ptr from displacement") @@ -4667,15 +4664,10 @@ let trans_visitor let (header_tup, _, _) = tag in let ctor_ty = Hashtbl.find cx.ctxt_all_item_types tagid in let ttag = - match ctor_ty with - Ast.TY_fn (tsig, _) -> - begin - match slot_ty tsig.Ast.sig_output_slot with - Ast.TY_tag ttag -> ttag - | Ast.TY_iso tiso -> get_iso_tag tiso - | _ -> bugi cx tagid "unexpected fn type for tag constructor" - end - | _ -> bugi cx tagid "unexpected type for tag constructor" + match slot_ty (fst (need_ty_fn ctor_ty)).Ast.sig_output_slot with + Ast.TY_tag ttag -> ttag + | Ast.TY_iso tiso -> get_iso_tag tiso + | _ -> bugi cx tagid "unexpected fn type for tag constructor" in let slots = Array.map (fun sloti -> referent_to_slot cx sloti.id) header_tup diff --git a/src/test/run-pass/output-slot-variants.rs b/src/test/run-pass/output-slot-variants.rs index 65d03fd8b63..3dd5ae2e3b5 100644 --- a/src/test/run-pass/output-slot-variants.rs +++ b/src/test/run-pass/output-slot-variants.rs @@ -35,24 +35,24 @@ fn main() { int_i = ret_int_i(); // non-initializing int_i = ret_int_i(); // non-initializing - //ext_i = ret_ext_i(); // initializing - //ext_i = ret_ext_i(); // non-initializing - //ext_i = ret_ext_i(); // non-initializing + ext_i = ret_ext_i(); // initializing + ext_i = ret_ext_i(); // non-initializing + ext_i = ret_ext_i(); // non-initializing int_tup = ret_int_tup(); // initializing int_tup = ret_int_tup(); // non-initializing int_tup = ret_int_tup(); // non-initializing - //ext_tup = ret_ext_tup(); // initializing - //ext_tup = ret_ext_tup(); // non-initializing - //ext_tup = ret_ext_tup(); // non-initializing + ext_tup = ret_ext_tup(); // initializing + ext_tup = ret_ext_tup(); // non-initializing + ext_tup = ret_ext_tup(); // non-initializing ext_mem = ret_ext_mem(); // initializing ext_mem = ret_ext_mem(); // non-initializing ext_mem = ret_ext_mem(); // non-initializing - //ext_ext_mem = ret_ext_ext_mem(); // initializing - //ext_ext_mem = ret_ext_ext_mem(); // non-initializing - //ext_ext_mem = ret_ext_ext_mem(); // non-initializing + ext_ext_mem = ret_ext_ext_mem(); // initializing + ext_ext_mem = ret_ext_ext_mem(); // non-initializing + ext_ext_mem = ret_ext_ext_mem(); // non-initializing }