diff options
Diffstat (limited to 'src/boot/me')
| -rw-r--r-- | src/boot/me/alias.ml | 5 | ||||
| -rw-r--r-- | src/boot/me/dead.ml | 3 | ||||
| -rw-r--r-- | src/boot/me/dwarf.ml | 5 | ||||
| -rw-r--r-- | src/boot/me/effect.ml | 3 | ||||
| -rw-r--r-- | src/boot/me/layout.ml | 6 | ||||
| -rw-r--r-- | src/boot/me/loop.ml | 4 | ||||
| -rw-r--r-- | src/boot/me/resolve.ml | 16 | ||||
| -rw-r--r-- | src/boot/me/semant.ml | 114 | ||||
| -rw-r--r-- | src/boot/me/trans.ml | 199 | ||||
| -rw-r--r-- | src/boot/me/type.ml | 65 | ||||
| -rw-r--r-- | src/boot/me/typestate.ml | 67 | ||||
| -rw-r--r-- | src/boot/me/walk.ml | 74 |
12 files changed, 357 insertions, 204 deletions
diff --git a/src/boot/me/alias.ml b/src/boot/me/alias.ml index d98316ef..148f1249 100644 --- a/src/boot/me/alias.ml +++ b/src/boot/me/alias.ml @@ -67,7 +67,7 @@ let alias_analysis_visitor | Ast.STMT_recv (dst, _) -> alias dst | Ast.STMT_init_port (dst) -> alias dst | Ast.STMT_init_chan (dst, _) -> alias dst - | Ast.STMT_init_vec (dst, _) -> alias dst + | Ast.STMT_init_vec (dst, _, _) -> alias dst | Ast.STMT_init_str (dst, _) -> alias dst | Ast.STMT_for_each sfe -> let (slot, _) = sfe.Ast.for_each_slot in @@ -118,7 +118,8 @@ let process_crate Walk.empty_visitor); |] in - run_passes cx "alias" path passes (log cx "%s") crate + run_passes cx "alias" path passes + cx.ctxt_sess.Session.sess_log_alias log crate ;; (* diff --git a/src/boot/me/dead.ml b/src/boot/me/dead.ml index 47e56166..61aa846a 100644 --- a/src/boot/me/dead.ml +++ b/src/boot/me/dead.ml @@ -106,7 +106,8 @@ let process_crate |] in - run_passes cx "dead" path passes (log cx "%s") crate; + run_passes cx "dead" path passes + cx.ctxt_sess.Session.sess_log_dead log crate; () ;; diff --git a/src/boot/me/dwarf.ml b/src/boot/me/dwarf.ml index cdc88da7..f1d51f16 100644 --- a/src/boot/me/dwarf.ml +++ b/src/boot/me/dwarf.ml @@ -1450,7 +1450,7 @@ let dwarf_visitor let iso_stack = Stack.create () in - let path_name _ = Fmt.fmt_to_str Ast.fmt_name (Walk.path_to_name path) in + let path_name _ = Fmt.fmt_to_str Ast.fmt_name (path_to_name path) in let (abbrev_table:(abbrev, int) Hashtbl.t) = Hashtbl.create 0 in @@ -2547,7 +2547,8 @@ let process_crate in log cx "emitting DWARF records"; - run_passes cx "dwarf" path passes (log cx "%s") crate; + run_passes cx "dwarf" path passes + cx.ctxt_sess.Session.sess_log_dwarf log crate; (* Terminate the tables. *) { diff --git a/src/boot/me/effect.ml b/src/boot/me/effect.ml index 3ec492c8..9ddef63d 100644 --- a/src/boot/me/effect.ml +++ b/src/boot/me/effect.ml @@ -328,7 +328,8 @@ let process_crate else err (Some id) "auth clause in crate refers to non-item" in Hashtbl.iter auth_effect crate.node.Ast.crate_auth; - run_passes cx "effect" path passes (log cx "%s") crate + run_passes cx "effect" path passes + cx.ctxt_sess.Session.sess_log_effect log crate ;; (* diff --git a/src/boot/me/layout.ml b/src/boot/me/layout.ml index 365acbf9..e1a7ff47 100644 --- a/src/boot/me/layout.ml +++ b/src/boot/me/layout.ml @@ -21,7 +21,8 @@ let layout_visitor * |... | * |... | * +----------------------------+ <-- fp + abi_frame_base_sz - * |task ptr (implicit arg) | + abi_implicit_args_sz + * |closure/obj ptr (impl. arg) | + abi_implicit_args_sz + * |task ptr (implicit arg) | * |output ptr (implicit arg) | * +----------------------------+ <-- fp + abi_frame_base_sz * |return pc | @@ -456,7 +457,8 @@ let process_crate Walk.empty_visitor) |]; in - run_passes cx "layout" path passes (log cx "%s") crate + run_passes cx "layout" path passes + cx.ctxt_sess.Session.sess_log_layout log crate ;; diff --git a/src/boot/me/loop.ml b/src/boot/me/loop.ml index c23c4afd..1fbb8223 100644 --- a/src/boot/me/loop.ml +++ b/src/boot/me/loop.ml @@ -148,8 +148,8 @@ let process_crate |] in - run_passes cx "loop" path passes (log cx "%s") crate; - () + run_passes cx "loop" path passes + cx.ctxt_sess.Session.sess_log_loop log crate ;; diff --git a/src/boot/me/resolve.ml b/src/boot/me/resolve.ml index 77fdbb3b..2c2b1b4b 100644 --- a/src/boot/me/resolve.ml +++ b/src/boot/me/resolve.ml @@ -167,7 +167,7 @@ let all_item_collecting_visitor Array.iter (fun p -> htab_put cx.ctxt_all_defns p.id (DEFN_ty_param p.node)) p; htab_put cx.ctxt_all_defns i.id (DEFN_item i.node); - htab_put cx.ctxt_all_item_names i.id (Walk.path_to_name path); + htab_put cx.ctxt_all_item_names i.id (path_to_name path); log cx "collected item #%d: %s" (int_of_node i.id) n; begin match i.node.Ast.decl_item with @@ -191,14 +191,14 @@ let all_item_collecting_visitor let visit_obj_fn_pre obj ident fn = htab_put cx.ctxt_all_defns fn.id (DEFN_obj_fn (obj.id, fn.node)); - htab_put cx.ctxt_all_item_names fn.id (Walk.path_to_name path); + htab_put cx.ctxt_all_item_names fn.id (path_to_name path); note_header fn.id fn.node.Ast.fn_input_slots; inner.Walk.visit_obj_fn_pre obj ident fn in let visit_obj_drop_pre obj b = htab_put cx.ctxt_all_defns b.id (DEFN_obj_drop obj.id); - htab_put cx.ctxt_all_item_names b.id (Walk.path_to_name path); + htab_put cx.ctxt_all_item_names b.id (path_to_name path); inner.Walk.visit_obj_drop_pre obj b in @@ -210,7 +210,7 @@ let all_item_collecting_visitor htab_put cx.ctxt_all_defns id (DEFN_loop_body (Stack.top items)); htab_put cx.ctxt_all_item_names id - (Walk.path_to_name path); + (path_to_name path); | _ -> () end; inner.Walk.visit_stmt_pre s; @@ -1035,14 +1035,14 @@ let process_crate export_referencing_visitor cx Walk.empty_visitor |] in - + let log_flag = cx.ctxt_sess.Session.sess_log_resolve in log cx "running primary resolve passes"; - run_passes cx "resolve collect" path passes_0 (log cx "%s") crate; + run_passes cx "resolve collect" path passes_0 log_flag log crate; resolve_recursion cx node_to_references recursive_tag_groups; log cx "running secondary resolve passes"; - run_passes cx "resolve bind" path passes_1 (log cx "%s") crate; + run_passes cx "resolve bind" path passes_1 log_flag log crate; log cx "running tertiary resolve passes"; - run_passes cx "resolve patterns" path passes_2 (log cx "%s") crate; + run_passes cx "resolve patterns" path passes_2 log_flag log crate; iflog cx begin diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml index 64f2c939..434fb025 100644 --- a/src/boot/me/semant.ml +++ b/src/boot/me/semant.ml @@ -583,13 +583,13 @@ let atoms_slots (cx:ctxt) (az:Ast.atom array) : node_id array = ;; let tup_inputs_slots (cx:ctxt) (az:Ast.tup_input array) : node_id array = - Array.concat (List.map (atom_slots cx) (Array.to_list az)) + Array.concat (List.map (atom_slots cx) (Array.to_list (Array.map snd az))) ;; let rec_inputs_slots (cx:ctxt) (inputs:Ast.rec_input array) : node_id array = Array.concat (List.map - (fun (_, atom) -> atom_slots cx atom) + (fun (_, _, atom) -> atom_slots cx atom) (Array.to_list inputs)) ;; @@ -1506,6 +1506,97 @@ let unreferenced_required_item_ignoring_visitor Walk.visit_obj_drop_post = visit_obj_drop_post; } ;; +let rec name_of ncs = + match ncs with + [] -> bug () "Walk.name_of_ncs: empty path" + | [(Ast.COMP_ident i)] -> Ast.NAME_base (Ast.BASE_ident i) + | [(Ast.COMP_app x)] -> Ast.NAME_base (Ast.BASE_app x) + | [(Ast.COMP_idx _)] -> + bug () "Walk.name_of_ncs: path-name contains COMP_idx" + | nc::ncs -> Ast.NAME_ext (name_of ncs, nc) +;; + +let path_to_name + (path:Ast.name_component Stack.t) + : Ast.name = + name_of (stk_elts_from_top path) +;; + +let mod_item_logging_visitor + (cx:ctxt) + (log_flag:bool) + (log:ctxt -> ('a, unit, string, unit) format4 -> 'a) + (pass:int) + (path:Ast.name_component Stack.t) + (inner:Walk.visitor) + : Walk. +visitor = + let entering _ = + if log_flag + then + log cx "pass %d: entering %a" + pass Ast.sprintf_name (path_to_name path) + in + let entered _ = + if log_flag + then + log cx "pass %d: entered %a" + pass Ast.sprintf_name (path_to_name path) + in + let leaving _ = + if log_flag + then + log cx "pass %d: leaving %a" + pass Ast.sprintf_name (path_to_name path) + in + let left _ = + if log_flag + then + log cx "pass %d: left %a" + pass Ast.sprintf_name (path_to_name path) + in + + let visit_mod_item_pre name params item = + entering(); + inner.Walk.visit_mod_item_pre name params item; + entered(); + in + let visit_mod_item_post name params item = + leaving(); + inner.Walk.visit_mod_item_post name params item; + left(); + in + let visit_obj_fn_pre obj ident fn = + entering(); + inner.Walk.visit_obj_fn_pre obj ident fn; + entered(); + in + let visit_obj_fn_post obj ident fn = + leaving(); + inner.Walk.visit_obj_fn_post obj ident fn; + left(); + in + let visit_obj_drop_pre obj b = + entering(); + inner.Walk.visit_obj_drop_pre obj b; + entered(); + in + let visit_obj_drop_post obj fn = + leaving(); + inner.Walk.visit_obj_drop_post obj fn; + left(); + in + { inner with + Walk.visit_mod_item_pre = visit_mod_item_pre; + Walk.visit_mod_item_post = visit_mod_item_post; + Walk.visit_obj_fn_pre = visit_obj_fn_pre; + Walk.visit_obj_fn_post = visit_obj_fn_post; + Walk.visit_obj_drop_pre = visit_obj_drop_pre; + Walk.visit_obj_drop_post = visit_obj_drop_post; + } +;; + + (* Generic lookup, used for slots, items, types, etc. *) @@ -1752,14 +1843,14 @@ let run_passes (name:string) (path:Ast.name_component Stack.t) (passes:Walk.visitor array) - (log:string->unit) + (log_flag:bool) + (log:ctxt -> ('a, unit, string, unit) format4 -> 'a) (crate:Ast.crate) : unit = let do_pass i pass = - let logger s = log (Printf.sprintf "pass %d: %s" i s) in Walk.walk_crate (Walk.path_managing_visitor path - (Walk.mod_item_logging_visitor logger path pass)) + (mod_item_logging_visitor cx log_flag log i path pass)) crate in let sess = cx.ctxt_sess in @@ -1936,10 +2027,10 @@ let call_args_referent_type_full [| out_ptr_rty; (* Abi.calltup_elt_out_ptr *) task_ptr_rty; (* Abi.calltup_elt_task_ptr *) + Il.StructTy indirect_arg_rtys; (* Abi.calltup_elt_indirect_args *) ty_param_rtys; (* Abi.calltup_elt_ty_params *) arg_rtys; (* Abi.calltup_elt_args *) - Il.StructTy iterator_arg_rtys; (* Abi.calltup_elt_iterator_args *) - Il.StructTy indirect_arg_rtys (* Abi.calltup_elt_indirect_args *) + Il.StructTy iterator_arg_rtys (* Abi.calltup_elt_iterator_args *) |] ;; @@ -1950,13 +2041,12 @@ let call_args_referent_type (closure:Il.referent_ty option) : Il.referent_ty = let indirect_arg_rtys = + (* Abi.indirect_args_elt_closure *) match closure with - None -> [| |] + None -> + [| word_rty cx.ctxt_abi |] | Some c -> - [| - (* Abi.indirect_args_elt_closure *) - Il.ScalarTy (Il.AddrTy c) - |] + [| Il.ScalarTy (Il.AddrTy c) |] in let iterator_arg_rtys _ = [| diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index f77386a9..46329a10 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -225,7 +225,7 @@ let trans_visitor let epilogue_jumps = Stack.create() in let path_name (_:unit) : string = - string_of_name (Walk.path_to_name path) + string_of_name (path_to_name path) in let based (reg:Il.reg) : Il.mem = @@ -1228,8 +1228,8 @@ let trans_visitor (sorted_htab_keys fns)) end - and trans_init_str (dst:Ast.lval) (s:string) : unit = - (* Include null byte. *) + and trans_init_str (dst:Ast.lval) (s:string) : unit = + (* Include null byte. *) let init_sz = Int64.of_int ((String.length s) + 1) in let static = trans_static_string s in let (dst, _) = trans_lval_init dst in @@ -1715,49 +1715,63 @@ let trans_visitor (code:Il.code) (dst:Il.cell option) (args:Il.cell array) + (clo:Il.cell option) : unit = - let inner dst = + let inner dst cloptr = let scratch = next_vreg_cell Il.voidptr_t in let pop _ = emit (Il.Pop scratch) in for i = ((Array.length args) - 1) downto 0 do emit (Il.Push (Il.Cell args.(i))) done; + emit (Il.Push cloptr); emit (Il.Push (Il.Cell abi.Abi.abi_tp_cell)); emit (Il.Push dst); call_code code; pop (); pop (); + pop (); Array.iter (fun _ -> pop()) args; in + let cloptr = + match clo with + None -> zero + | Some cloptr -> Il.Cell cloptr + in match dst with - None -> inner zero - | Some dst -> aliasing true dst (fun dst -> inner (Il.Cell dst)) + None -> inner zero cloptr + | Some dst -> + aliasing true dst (fun dst -> inner (Il.Cell dst) cloptr) and trans_call_static_glue (callee:Il.operand) (dst:Il.cell option) (args:Il.cell array) + (clo:Il.cell option) : unit = - trans_call_glue (code_of_operand callee) dst args + trans_call_glue (code_of_operand callee) dst args clo and trans_call_dynamic_glue (tydesc:Il.cell) (idx:int) (dst:Il.cell option) (args:Il.cell array) + (clo:Il.cell option) : unit = let fptr = get_vtbl_entry_idx tydesc idx in - trans_call_glue (code_of_operand (Il.Cell fptr)) dst args + trans_call_glue (code_of_operand (Il.Cell fptr)) dst args clo and trans_call_simple_static_glue (fix:fixup) (ty_params:Il.cell) - (arg:Il.cell) + (args:Il.cell array) + (clo:Il.cell option) : unit = trans_call_static_glue (code_fixup_to_ptr_operand fix) - None [| alias ty_params; arg |] + None + (Array.append [| alias ty_params |] args) + clo and get_tydesc_params (outer_ty_params:Il.cell) @@ -1779,7 +1793,8 @@ let trans_visitor (ty_param:int) (vtbl_idx:int) (ty_params:Il.cell) - (arg:Il.cell) + (args:Il.cell array) + (clo:Il.cell option) : unit = iflog (fun _ -> annotate (Printf.sprintf "calling tydesc[%d].glue[%d]" @@ -1787,8 +1802,11 @@ let trans_visitor let td = get_ty_param ty_params ty_param in let ty_params_ptr = get_tydesc_params ty_params td in trans_call_dynamic_glue - td vtbl_idx - None [| ty_params_ptr; arg; |] + td + vtbl_idx + None + (Array.append [| ty_params_ptr |] args) + clo (* trans_compare returns a quad number of the cjmp, which the caller patches to the cjmp destination. *) @@ -2453,36 +2471,41 @@ let trans_visitor note_drop_step ty "drop_ty: obj path"; let binding = get_element_ptr cell Abi.binding_field_binding in let null_jmp = null_check binding in + let rc_jmp = drop_refcount_and_cmp binding in let obj = deref binding in - let rc = get_element_ptr obj 0 in - let rc_jmp = drop_refcount_and_cmp rc in let tydesc = get_element_ptr obj 1 in let body = get_element_ptr obj 2 in - let ty_params = - get_element_ptr (deref tydesc) Abi.tydesc_field_first_param - in + let ty_params = get_tydesc_params ty_params tydesc in let dtor = get_element_ptr (deref tydesc) Abi.tydesc_field_obj_drop_glue in let null_dtor_jmp = null_check dtor in (* Call any dtor, if present. *) - note_drop_step ty "drop_ty: calling obj dtor"; - trans_call_dynamic_glue tydesc - Abi.tydesc_field_obj_drop_glue None [| binding |]; - patch null_dtor_jmp; - (* Drop the body. *) - note_drop_step ty "drop_ty: dropping obj body"; - trans_call_dynamic_glue tydesc - Abi.tydesc_field_drop_glue None [| ty_params; alias body |]; - (* FIXME: this will fail if the user has lied about the - * state-ness of their obj. We need to store state-ness in the - * captured tydesc, and use that. *) - note_drop_step ty "drop_ty: freeing obj body"; - trans_free binding (type_has_state ty); - mov binding zero; - patch rc_jmp; - patch null_jmp; - note_drop_step ty "drop_ty: done obj path"; + note_drop_step ty "drop_ty: calling obj dtor"; + trans_call_dynamic_glue + tydesc + Abi.tydesc_field_obj_drop_glue + None + [| binding |] + (Some binding); + patch null_dtor_jmp; + (* Drop the body. *) + note_drop_step ty "drop_ty: dropping obj body"; + trans_call_dynamic_glue + tydesc + Abi.tydesc_field_drop_glue + None + [| ty_params; alias body |] + None; + (* FIXME: this will fail if the user has lied about the + * state-ness of their obj. We need to store state-ness in the + * captured tydesc, and use that. *) + note_drop_step ty "drop_ty: freeing obj body"; + trans_free binding (type_has_state ty); + mov binding zero; + patch rc_jmp; + patch null_jmp; + note_drop_step ty "drop_ty: done obj path"; | Ast.TY_param (i, _) -> @@ -2491,7 +2514,11 @@ let trans_visitor begin fun cell -> trans_call_simple_dynamic_glue - i Abi.tydesc_field_drop_glue ty_params cell + i + Abi.tydesc_field_drop_glue + ty_params + [| cell |] + None end; note_drop_step ty "drop_ty: done parametric-ty path"; @@ -2505,8 +2532,7 @@ let trans_visitor let _ = check_box_rty cell in let null_jmp = null_check cell in - let rc = box_rc_cell cell in - let j = drop_refcount_and_cmp rc in + let j = drop_refcount_and_cmp cell in (* FIXME (issue #25): check to see that the box has * further box members; if it doesn't we can elide the @@ -2514,7 +2540,9 @@ let trans_visitor trans_call_simple_static_glue (get_free_glue ty (mctrl = MEM_gc) curr_iso) - ty_params cell; + ty_params + [| cell |] + None; (* Null the slot out to prevent double-free if the frame * unwinds. @@ -2525,7 +2553,7 @@ let trans_visitor note_drop_step ty "drop_ty: done box-drop path"; | MEM_interior when type_is_structured ty -> - note_drop_step ty "drop:ty structured-interior path"; + note_drop_step ty "drop_ty structured-interior path"; iter_ty_parts ty_params cell ty (drop_ty ty_params) curr_iso; note_drop_step ty "drop_ty: done structured-interior path"; @@ -2603,7 +2631,7 @@ let trans_visitor trans_call_static_glue (code_fixup_to_ptr_operand glue_fix) (Some dst) - [| alias ty_params; src; clone_task |] + [| alias ty_params; src; clone_task |] None | _ -> iter_ty_parts_full ty_params dst src ty (clone_ty ty_params clone_task) curr_iso @@ -2640,7 +2668,10 @@ let trans_visitor lea vr body_mem; trace_word cx.ctxt_sess.Session.sess_trace_drop vr; trans_call_simple_static_glue - (get_drop_glue body_ty curr_iso) ty_params vr; + (get_drop_glue body_ty curr_iso) + ty_params + [| vr |] + None; note_drop_step ty "in free-ty, calling free"; trans_free cell is_gc; end; @@ -2700,7 +2731,9 @@ let trans_visitor lea tmp body_mem; trans_call_simple_static_glue (get_mark_glue ty curr_iso) - ty_params tmp; + ty_params + [| tmp |] + None; List.iter patch marked_jump; | MEM_interior when type_is_structured ty -> @@ -2714,7 +2747,9 @@ let trans_visitor lea tmp mem; trans_call_simple_static_glue (get_mark_glue ty curr_iso) - ty_params tmp + ty_params + [| tmp |] + None | _ -> () @@ -2740,14 +2775,35 @@ let trans_visitor emit (Il.jmp Il.JE Il.CodeNone); j - and drop_refcount_and_cmp (rc:Il.cell) : quad_idx = + and drop_refcount_and_cmp (boxed:Il.cell) : quad_idx = iflog (fun _ -> annotate "drop refcount and maybe free"); + let rc = box_rc_cell boxed in + if cx.ctxt_sess.Session.sess_trace_gc || + cx.ctxt_sess.Session.sess_trace_drop + then + begin + trace_str true "refcount--"; + trace_word true boxed; + trace_word true rc + end; emit (Il.binary Il.SUB rc (Il.Cell rc) one); emit (Il.cmp (Il.Cell rc) zero); let j = mark () in emit (Il.jmp Il.JNE Il.CodeNone); j + and incr_refcount (boxed:Il.cell) : unit = + let rc = box_rc_cell boxed in + if cx.ctxt_sess.Session.sess_trace_gc || + cx.ctxt_sess.Session.sess_trace_drop + then + begin + trace_str true "refcount++"; + trace_word true boxed; + trace_word true rc + end; + add_to rc one + and drop_slot (ty_params:Il.cell) (cell:Il.cell) @@ -2917,7 +2973,7 @@ let trans_visitor | (MEM_rc_struct, MEM_rc_struct) -> (* Lightweight copy: twiddle refcounts, move pointer. *) anno "refcounted light"; - add_to (box_rc_cell src) one; + incr_refcount src; if not initializing then drop_ty ty_params dst dst_ty None; @@ -3012,7 +3068,9 @@ let trans_visitor let ty_params_ptr = get_tydesc_params ty_params td in trans_call_dynamic_glue td Abi.tydesc_field_copy_glue - (Some dst) [| ty_params_ptr; src; |] + (Some dst) + [| ty_params_ptr; src; |] + None end | Ast.TY_fn _ @@ -3186,13 +3244,13 @@ let trans_visitor (dst:Il.cell) (dst_tys:Ast.ty array) (trec:Ast.ty_rec) - (atab:(Ast.ident * Ast.atom) array) + (atab:(Ast.ident * Ast.mutability * Ast.atom) array) (base:Ast.lval) : unit = Array.iteri begin fun i (fml_ident, _) -> - let fml_entry _ (act_ident, atom) = + let fml_entry _ (act_ident, _, atom) = if act_ident = fml_ident then Some atom else None in let dst_ty = dst_tys.(i) in @@ -3537,6 +3595,9 @@ let trans_visitor let callee_task_cell = get_element_ptr all_callee_args_cell Abi.calltup_elt_task_ptr in + let callee_indirect_args = + get_element_ptr all_callee_args_cell Abi.calltup_elt_indirect_args + in let callee_ty_params = get_element_ptr all_callee_args_cell Abi.calltup_elt_ty_params in @@ -3548,10 +3609,6 @@ let trans_visitor get_element_ptr_dyn_in_current_frame all_callee_args_cell Abi.calltup_elt_iterator_args in - let callee_indirect_args = - get_element_ptr_dyn_in_current_frame - all_callee_args_cell Abi.calltup_elt_indirect_args - in let n_args = Array.length call.call_args in let n_iterators = Array.length call.call_iterator_args in @@ -3611,9 +3668,9 @@ let trans_visitor end call.call_callee_ty_params; - trans_arg1 callee_task_cell; + trans_arg1 callee_task_cell; - trans_arg0 callee_output_cell initializing_arg0 call + trans_arg0 callee_output_cell initializing_arg0 call @@ -4002,10 +4059,9 @@ let trans_visitor let dst_slot_id = (fst (fo.Ast.for_slot)).id in let dst_slot = get_slot cx dst_slot_id in let dst_cell = cell_of_block_slot dst_slot_id in - let (head_stmts, seq) = fo.Ast.for_seq in + let seq = fo.Ast.for_seq in let (seq_cell, seq_ty) = trans_lval seq in let unit_ty = seq_unit_ty seq_ty in - Array.iter trans_stmt head_stmts; iter_seq_parts ty_params seq_cell seq_cell unit_ty begin fun _ src_cell unit_ty _ -> @@ -4070,7 +4126,11 @@ let trans_visitor let fp = get_iter_outer_frame_ptr_for_current_frame () in let vr = next_vreg_cell Il.voidptr_t in mov vr zero; - trans_call_glue (code_of_operand block_fptr) None [| vr; fp |] + trans_call_glue + (code_of_operand block_fptr) + None + [| vr; fp |] + None and trans_vec_append dst_cell dst_ty src_oper src_ty = let elt_ty = seq_unit_ty dst_ty in @@ -4255,7 +4315,7 @@ let trans_visitor begin match base with None -> - let atoms = Array.map snd atab in + let atoms = Array.map (fun (_, _, atom) -> atom) atab in trans_init_structural_from_atoms dst_cell dst_tys atoms | Some base_lval -> @@ -4263,7 +4323,7 @@ let trans_visitor dst_cell dst_tys trec atab base_lval end - | Ast.STMT_init_tup (dst, atoms) -> + | Ast.STMT_init_tup (dst, elems) -> let (slot_cell, ty) = trans_lval_init dst in let dst_tys = match ty with @@ -4272,6 +4332,7 @@ let trans_visitor bugi cx stmt.id "non-tup destination type in stmt_init_tup" in + let atoms = Array.map snd elems in let (dst_cell, _) = deref_ty DEREF_none true slot_cell ty in trans_init_structural_from_atoms dst_cell dst_tys atoms @@ -4279,7 +4340,7 @@ let trans_visitor | Ast.STMT_init_str (dst, s) -> trans_init_str dst s - | Ast.STMT_init_vec (dst, atoms) -> + | Ast.STMT_init_vec (dst, _, atoms) -> trans_init_vec dst atoms | Ast.STMT_init_port dst -> @@ -4297,7 +4358,7 @@ let trans_visitor trans_init_chan dst p end - | Ast.STMT_init_box (dst, src) -> + | Ast.STMT_init_box (dst, _, src) -> trans_init_box dst src | Ast.STMT_block block -> @@ -4614,7 +4675,7 @@ let trans_visitor trans_crate_rel_static_string_frag (string_of_name_component nc) in trans_crate_rel_data_operand - (DATA_name (Walk.name_of ncs)) + (DATA_name (name_of ncs)) (fun _ -> Asm.SEQ (Array.append (Array.map f (Array.of_list ncs)) [| Asm.WORD (word_ty_mach, Asm.IMM 0L) |])) @@ -5012,7 +5073,7 @@ let fixup_assigning_visitor : Walk.visitor = let path_name (_:unit) : string = - Fmt.fmt_to_str Ast.fmt_name (Walk.path_to_name path) + Fmt.fmt_to_str Ast.fmt_name (path_to_name path) in let enter_file_for id = @@ -5110,11 +5171,8 @@ let process_crate (fixup_assigning_visitor cx path Walk.empty_visitor)); (unreferenced_required_item_ignoring_visitor cx - (Walk.mod_item_logging_visitor - (log cx "translation pass: %s") - path - (trans_visitor cx path - Walk.empty_visitor))) + (trans_visitor cx path + Walk.empty_visitor)) |]; in log cx "translating crate"; @@ -5123,7 +5181,8 @@ let process_crate None -> () | Some m -> log cx "with main fn %s" m end; - run_passes cx "trans" path passes (log cx "%s") crate; + run_passes cx "trans" path passes + cx.ctxt_sess.Session.sess_log_trans log crate; ;; (* diff --git a/src/boot/me/type.ml b/src/boot/me/type.ml index b27e68dc..45570708 100644 --- a/src/boot/me/type.ml +++ b/src/boot/me/type.ml @@ -216,6 +216,20 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = in let retval_tvs = Stack.create () in + let fns = Stack.create () in + + let push_fn fn = + Stack.push fn fns + in + + let pop_fn _ = + ignore (Stack.pop fns) + in + + let fn_is_iter() = + (Stack.top fns).Ast.fn_aux.Ast.fn_is_iter + in + let push_retval_tv tv = Stack.push tv retval_tvs in @@ -1130,7 +1144,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = | Ast.STMT_init_rec (dst, fields, Some base) -> let dct = Hashtbl.create 10 in let tvrec = ref (TYSPEC_record dct) in - let add_field (ident, atom) = + let add_field (ident, _, atom) = let tv = any() in unify_atom arg_pass_ctx atom tv; Hashtbl.add dct ident tv @@ -1143,7 +1157,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = | Ast.STMT_init_rec (dst, fields, None) -> let dct = Hashtbl.create 10 in - let add_field (ident, atom) = + let add_field (ident, _, atom) = let tv = any() in unify_atom arg_pass_ctx atom tv; Hashtbl.add dct ident tv @@ -1152,7 +1166,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = unify_lval init_ctx dst (ref (TYSPEC_record dct)) | Ast.STMT_init_tup (dst, members) -> - let member_to_tv atom = + let member_to_tv (_, atom) = let tv = any() in unify_atom arg_pass_ctx atom tv; tv @@ -1160,7 +1174,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = let member_tvs = Array.map member_to_tv members in unify_lval init_ctx dst (ref (TYSPEC_tuple member_tvs)) - | Ast.STMT_init_vec (dst, atoms) -> + | Ast.STMT_init_vec (dst, _, atoms) -> let tv = any() in let unify_with_tv atom = unify_atom arg_pass_ctx atom tv in Array.iter unify_with_tv atoms; @@ -1215,13 +1229,27 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = | Ast.STMT_if { Ast.if_test = if_test } -> unify_expr rval_ctx if_test (ty Ast.TY_bool); - | Ast.STMT_ret atom_opt - | Ast.STMT_put atom_opt -> + | Ast.STMT_ret atom_opt -> begin + if fn_is_iter() + then + match atom_opt with + | None -> () + | Some _ -> err None "Iter returning value" + else + match atom_opt with + | None -> unify_ty arg_pass_ctx Ast.TY_nil (retval_tv()) + | Some atom -> unify_atom arg_pass_ctx atom (retval_tv()) + end + + | Ast.STMT_put atom_opt -> + if fn_is_iter() + then match atom_opt with - None -> unify_ty arg_pass_ctx Ast.TY_nil (retval_tv()) + | None -> unify_ty arg_pass_ctx Ast.TY_nil (retval_tv()) | Some atom -> unify_atom arg_pass_ctx atom (retval_tv()) - end + else + err None "Non-iter function with 'put'" | Ast.STMT_be (callee, args) -> check_callable (retval_tv()) callee args @@ -1263,7 +1291,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = let mem_tv = ref TYSPEC_all in let seq_tv = ref (TYSPEC_collection mem_tv) in let (si, _) = fo.Ast.for_slot in - let (_, seq) = fo.Ast.for_seq in + let seq = fo.Ast.for_seq in unify_lval rval_ctx seq seq_tv; unify_slot lval_ctx si.node (Some si.id) mem_tv @@ -1276,7 +1304,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = | Ast.STMT_join lval -> unify_lval rval_ctx lval (ty Ast.TY_task); - | Ast.STMT_init_box (dst, v) -> + | Ast.STMT_init_box (dst, _, v) -> let in_tv = any() in let tv = ref (TYSPEC_mutable (ref (TYSPEC_box in_tv))) in unify_lval strict_ctx dst tv; @@ -1344,11 +1372,17 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = in let enter_fn fn retspec = + push_fn fn; let out = fn.Ast.fn_output_slot in push_retval_tv (ref retspec); unify_slot arg_pass_ctx out.node (Some out.id) (retval_tv()) in + let leave_fn _ = + pop_retval_tv (); + pop_fn (); + in + let visit_obj_fn_pre obj ident fn = enter_fn fn.node TYSPEC_all; inner.Walk.visit_obj_fn_pre obj ident fn @@ -1356,7 +1390,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = let visit_obj_fn_post obj ident fn = inner.Walk.visit_obj_fn_post obj ident fn; - pop_retval_tv (); + leave_fn (); in let visit_mod_item_pre n p mod_item = @@ -1374,7 +1408,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = in let path_name (_:unit) : string = - string_of_name (Walk.path_to_name path) + string_of_name (path_to_name path) in let visit_mod_item_post n p mod_item = @@ -1382,7 +1416,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = match mod_item.node.Ast.decl_item with | Ast.MOD_ITEM_fn _ -> - pop_retval_tv (); + leave_fn (); if (Some (path_name())) = cx.ctxt_main_name then begin @@ -1528,9 +1562,8 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit = Hashtbl.iter init_mod_dict cx.ctxt_all_defns; Walk.walk_crate (Walk.path_managing_visitor path - (Walk.mod_item_logging_visitor - (log cx "typechecking pass: %s") - path + (mod_item_logging_visitor cx + cx.ctxt_sess.Session.sess_log_type log 0 path (visitor cx Walk.empty_visitor))) crate; diff --git a/src/boot/me/typestate.ml b/src/boot/me/typestate.ml index 3a13561a..cca548b8 100644 --- a/src/boot/me/typestate.ml +++ b/src/boot/me/typestate.ml @@ -434,7 +434,7 @@ let condition_assigning_visitor raise_pre_post_cond s.id precond; raise_postcondition s.id postcond - | Ast.STMT_init_vec (dst, atoms) -> + | Ast.STMT_init_vec (dst, _, atoms) -> let precond = slot_inits (atoms_slots cx atoms) in let postcond = slot_inits (lval_slots cx dst) in raise_pre_post_cond s.id precond; @@ -454,7 +454,7 @@ let condition_assigning_visitor raise_pre_post_cond s.id precond; raise_postcondition s.id postcond - | Ast.STMT_init_box (dst, src) -> + | Ast.STMT_init_box (dst, _, src) -> let precond = slot_inits (atom_slots cx src) in let postcond = slot_inits (lval_slots cx dst) in raise_pre_post_cond s.id precond; @@ -533,7 +533,7 @@ let condition_assigning_visitor | Ast.STMT_for fo -> let (si, _) = fo.Ast.for_slot in - let (_, lval) = fo.Ast.for_seq in + let lval = fo.Ast.for_seq in let precond = slot_inits (lval_slots cx lval) in let block_entry_state = [| Constr_init si.id |] in raise_pre_post_cond s.id precond; @@ -988,23 +988,30 @@ let lifecycle_visitor * used later on in translation. *) - let (live_block_slots:(node_id Stack.t) Stack.t) = Stack.create () in + let (live_block_slots:(node_id, unit) Hashtbl.t) = Hashtbl.create 0 in + let (block_slots:(node_id Stack.t) Stack.t) = Stack.create () in let (implicit_init_block_slots:(node_id,node_id) Hashtbl.t) = Hashtbl.create 0 in + let push_slot sl = + Stack.push sl (Stack.top block_slots) + in + let mark_slot_init sl = - Stack.push sl (Stack.top live_block_slots) + Hashtbl.replace live_block_slots sl () in let visit_block_pre b = - Stack.push (Stack.create()) live_block_slots; + Stack.push (Stack.create()) block_slots; begin match htab_search implicit_init_block_slots b.id with None -> () - | Some slot -> mark_slot_init slot + | Some slot -> + push_slot slot; + mark_slot_init slot end; inner.Walk.visit_block_pre b in @@ -1026,7 +1033,7 @@ let lifecycle_visitor let visit_block_post b = inner.Walk.visit_block_post b; - let blk_live = Stack.pop live_block_slots in + let blk_slots = Stack.pop block_slots in let stmts = b.node in let len = Array.length stmts in if len > 0 @@ -1037,9 +1044,22 @@ let lifecycle_visitor Ast.STMT_ret _ | Ast.STMT_be _ -> () (* Taken care of in visit_stmt_post below. *) - | _ -> - let slots = stk_elts_from_top blk_live in - note_drops s slots + | _ -> + (* The blk_slots stack we have has accumulated slots in + * declaration order as we walked the block; the top of the + * stack is the last-declared slot. We want to generate + * slot-drop obligations here for the slots in top-down order + * (starting with the last-declared) but only hitting those + * slots that actually got initialized (went live) at some + * point in the block. + *) + let slots = stk_elts_from_top blk_slots in + let live = + List.filter + (fun i -> Hashtbl.mem live_block_slots i) + slots + in + note_drops s live end; in @@ -1081,13 +1101,16 @@ let lifecycle_visitor init_lval lv_dst end; + | Ast.STMT_decl (Ast.DECL_slot (_, sloti)) -> + push_slot sloti.id + | Ast.STMT_init_rec (lv_dst, _, _) | Ast.STMT_init_tup (lv_dst, _) - | Ast.STMT_init_vec (lv_dst, _) + | Ast.STMT_init_vec (lv_dst, _, _) | Ast.STMT_init_str (lv_dst, _) | Ast.STMT_init_port lv_dst | Ast.STMT_init_chan (lv_dst, _) - | Ast.STMT_init_box (lv_dst, _) -> + | Ast.STMT_init_box (lv_dst, _, _) -> init_lval lv_dst | Ast.STMT_for f -> @@ -1107,7 +1130,7 @@ let lifecycle_visitor (fst f.Ast.for_each_slot).id - | _ -> () + | _ -> () end; inner.Walk.visit_stmt_pre s in @@ -1117,9 +1140,14 @@ let lifecycle_visitor match s.node with Ast.STMT_ret _ | Ast.STMT_be _ -> - let stks = stk_elts_from_top live_block_slots in + let stks = stk_elts_from_top block_slots in let slots = List.concat (List.map stk_elts_from_top stks) in - note_drops s slots + let live = + List.filter + (fun i -> Hashtbl.mem live_block_slots i) + slots + in + note_drops s live | _ -> () in @@ -1171,10 +1199,11 @@ let process_crate Walk.empty_visitor) |] in - run_passes cx "typestate setup" path setup_passes (log cx "%s") crate; + let log_flag = cx.ctxt_sess.Session.sess_log_typestate in + run_passes cx "typestate setup" path setup_passes log_flag log crate; run_dataflow cx constr_id graph; - run_passes cx "typestate verify" path verify_passes (log cx "%s") crate; - run_passes cx "typestate aux" path aux_passes (log cx "%s") crate + run_passes cx "typestate verify" path verify_passes log_flag log crate; + run_passes cx "typestate aux" path aux_passes log_flag log crate ;; diff --git a/src/boot/me/walk.ml b/src/boot/me/walk.ml index 0b60c832..fac44170 100644 --- a/src/boot/me/walk.ml +++ b/src/boot/me/walk.ml @@ -123,69 +123,6 @@ let path_managing_visitor } ;; -let rec name_of ncs = - match ncs with - [] -> bug () "Walk.name_of_ncs: empty path" - | [(Ast.COMP_ident i)] -> Ast.NAME_base (Ast.BASE_ident i) - | [(Ast.COMP_app x)] -> Ast.NAME_base (Ast.BASE_app x) - | [(Ast.COMP_idx _)] -> - bug () "Walk.name_of_ncs: path-name contains COMP_idx" - | nc::ncs -> Ast.NAME_ext (name_of ncs, nc) -;; - -let path_to_name - (path:Ast.name_component Stack.t) - : Ast.name = - name_of (stk_elts_from_top path) -;; - - -let mod_item_logging_visitor - (logfn:string->unit) - (path:Ast.name_component Stack.t) - (inner:visitor) - : visitor = - let path_name _ = Fmt.fmt_to_str Ast.fmt_name (path_to_name path) in - let visit_mod_item_pre name params item = - logfn (Printf.sprintf "entering %s" (path_name())); - inner.visit_mod_item_pre name params item; - logfn (Printf.sprintf "entered %s" (path_name())); - in - let visit_mod_item_post name params item = - logfn (Printf.sprintf "leaving %s" (path_name())); - inner.visit_mod_item_post name params item; - logfn (Printf.sprintf "left %s" (path_name())); - in - let visit_obj_fn_pre obj ident fn = - logfn (Printf.sprintf "entering %s" (path_name())); - inner.visit_obj_fn_pre obj ident fn; - logfn (Printf.sprintf "entered %s" (path_name())); - in - let visit_obj_fn_post obj ident fn = - logfn (Printf.sprintf "leaving %s" (path_name())); - inner.visit_obj_fn_post obj ident fn; - logfn (Printf.sprintf "left %s" (path_name())); - in - let visit_obj_drop_pre obj b = - logfn (Printf.sprintf "entering %s" (path_name())); - inner.visit_obj_drop_pre obj b; - logfn (Printf.sprintf "entered %s" (path_name())); - in - let visit_obj_drop_post obj fn = - logfn (Printf.sprintf "leaving %s" (path_name())); - inner.visit_obj_drop_post obj fn; - logfn (Printf.sprintf "left %s" (path_name())); - in - { inner with - visit_mod_item_pre = visit_mod_item_pre; - visit_mod_item_post = visit_mod_item_post; - visit_obj_fn_pre = visit_obj_fn_pre; - visit_obj_fn_post = visit_obj_fn_post; - visit_obj_drop_pre = visit_obj_drop_pre; - visit_obj_drop_post = visit_obj_drop_post; - } -;; - let walk_bracketed (pre:'a -> unit) @@ -419,9 +356,8 @@ and walk_stmt (s:Ast.stmt_for) : unit = let (si,_) = s.Ast.for_slot in - let (ss,lv) = s.Ast.for_seq in + let lv = s.Ast.for_seq in walk_slot_identified v si; - Array.iter (walk_stmt v) ss; walk_lval v lv; walk_block v s.Ast.for_body in @@ -450,16 +386,16 @@ and walk_stmt | Ast.STMT_init_rec (lv, atab, base) -> walk_lval v lv; - Array.iter (fun (_, a) -> walk_atom v a) atab; + Array.iter (fun (_, _, a) -> walk_atom v a) atab; walk_option (walk_lval v) base; - | Ast.STMT_init_vec (lv, atoms) -> + | Ast.STMT_init_vec (lv, _, atoms) -> walk_lval v lv; Array.iter (walk_atom v) atoms | Ast.STMT_init_tup (lv, mut_atoms) -> walk_lval v lv; - Array.iter (walk_atom v) mut_atoms + Array.iter (fun (_, atom) -> walk_atom v atom) mut_atoms | Ast.STMT_init_str (lv, _) -> walk_lval v lv @@ -471,7 +407,7 @@ and walk_stmt walk_option (walk_lval v) port; walk_lval v chan; - | Ast.STMT_init_box (dst, src) -> + | Ast.STMT_init_box (dst, _, src) -> walk_lval v dst; walk_atom v src |