Browse Source

remove analyzer changes

Simon Krajewski 1 year ago
parent
commit
3a49bf23e9

+ 1 - 19
src/optimization/analyzer.ml

@@ -739,16 +739,7 @@ module Debug = struct
 	let dot_debug_node g ch nil bb =
 		let s = Printf.sprintf "(%i)" bb.bb_id in
 		let s = List.fold_left (fun s ni -> s ^ match ni with
-			| NIExpr ->
-				let sl = DynArray.to_list (DynArray.map s_expr_pretty bb.bb_el) in
-				let sl = match terminator_to_texpr_maybe bb.bb_terminator with
-					| None -> sl
-					| Some e -> sl @ [s_expr_pretty e]
-				in
-				begin match sl with
-					| [] -> ""
-					| _ -> "\n" ^  String.concat "\n" sl
-				end
+			| NIExpr -> if DynArray.length bb.bb_el = 0 then "" else "\n" ^  String.concat "\n" (DynArray.to_list (DynArray.map s_expr_pretty bb.bb_el))
 			| NIPhi -> if DynArray.length bb.bb_phi = 0 then "" else "\n" ^ String.concat "\n" (DynArray.to_list (DynArray.map (fun e -> s_expr_pretty e) bb.bb_phi))
 			| NIVars -> if bb.bb_var_writes = [] then "" else "\n" ^ String.concat ", " (List.map (fun v -> s_var v) bb.bb_var_writes)
 			| NILoopGroups -> if bb.bb_loop_groups = [] then "" else "\nLoops: " ^ (String.concat ", " (List.map string_of_int bb.bb_loop_groups))
@@ -804,8 +795,6 @@ module Debug = struct
 			edge bb_next "next";
 		| SEMerge bb_next ->
 			edge bb_next "merge"
-		| SESuspend (call, bb_next) ->
-			edge bb_next ("suspend " ^ s_expr_pretty (mk (TCall (call.efun, call.args)) t_dynamic call.pos))
 		| SESwitch ss ->
 			List.iter (fun (el,bb) -> edge bb ("case " ^ (String.concat " | " (List.map s_expr_pretty el)))) ss.ss_cases;
 			(match ss.ss_default with None -> () | Some bb -> edge bb "default");
@@ -1119,13 +1108,6 @@ module Run = struct
 			let e = reduce_control_flow com e in
 			maybe_debug();
 			cf.cf_expr <- Some e;
-
-			(* lose Coroutine<T> type here *)
-			(match follow_with_coro cf.cf_type with
-			| Coro (args, ret) ->
-				let args = args @ [("",false,tfun [ret; t_dynamic] com.basic.tvoid)] in
-				cf.cf_type <- TFun (args, com.basic.tvoid);
-			| _ -> ())
 		| _ -> ()
 
 	let run_on_field com config c cf =

+ 0 - 3
src/optimization/analyzerConfig.ml

@@ -38,7 +38,6 @@ type t = {
 	detail_times : int;
 	user_var_fusion : bool;
 	fusion_debug : bool;
-	coro_debug : bool;
 }
 
 let flag_optimize = "optimize"
@@ -75,7 +74,6 @@ let get_base_config com =
 		detail_times = (try int_of_string (Common.defined_value_safe com ~default:"0" Define.AnalyzerTimes) with _ -> 0);
 		user_var_fusion = (match com.platform with Flash | Jvm -> false | _ -> true) && (Common.raw_defined com "analyzer_user_var_fusion" || (not com.debug && not (Common.raw_defined com "analyzer_no_user_var_fusion")));
 		fusion_debug = false;
-		coro_debug = false;
 	}
 
 let update_config_from_meta com config ml =
@@ -99,7 +97,6 @@ let update_config_from_meta com config ml =
 						| "dot_debug" -> { config with debug_kind = DebugDot }
 						| "full_debug" -> { config with debug_kind = DebugFull }
 						| "fusion_debug" -> { config with fusion_debug = true }
-						| "coro_debug" -> { config with coro_debug = true }
 						| "as_var" -> config
 						| _ ->
 							let options = Warning.from_meta ml in

+ 0 - 390
src/optimization/analyzerCoro.ml

@@ -1,390 +0,0 @@
-open Globals
-open Type
-open AnalyzerTypes
-open BasicBlock
-open Graph
-open Texpr
-
-let block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
-	assert(bb.bb_closed);
-
-	let open Texpr.Builder in
-	let com = ctx.com in
-
-	let eerror = make_local verror null_pos in
-
-	let mk_int i = make_int com.basic i null_pos in
-
-	let mk_assign estate eid =
-		mk (TBinop (OpAssign,estate,eid)) eid.etype null_pos
-	in
-
-	let vstate = alloc_var VGenerated "_hx_state" com.basic.tint p in
-	add_var_flag vstate VCaptured;
-	declare_var ctx.graph vstate bb;
-	let estate = make_local vstate p in
-	let set_state id = mk_assign estate (mk_int id) in
-
-	let vexcstate = alloc_var VGenerated "_hx_exceptionState" com.basic.tint p in
-	add_var_flag vexcstate VCaptured;
-	declare_var ctx.graph vexcstate bb;
-	let eexcstate = make_local vexcstate p in
-	let set_excstate id = mk_assign eexcstate (mk_int id) in
-
-	let tstatemachine = tfun [t_dynamic; t_dynamic] com.basic.tvoid in
-	let vstatemachine = alloc_var VGenerated "_hx_stateMachine" tstatemachine p in
-	add_var_flag vstatemachine VCaptured;
-	declare_var ctx.graph vstatemachine bb;
-	let estatemachine = make_local vstatemachine p in
-
-	let get_next_state_id =
-		let counter = ref 0 in
-		fun () -> (let id = !counter in incr counter; id)
-	in
-
-	let get_rethrow_state_id =
-		let rethrow_state_id = ref (-1) in
-		fun () -> begin
-			if !rethrow_state_id = (-1) then rethrow_state_id := get_next_state_id ();
-			!rethrow_state_id;
-		end
-	in
-
-	let mk_continuation_call eresult p =
-		let econtinuation = make_local vcontinuation p in
-		mk (TCall (econtinuation, [eresult; make_null t_dynamic p])) com.basic.tvoid p
-	in
-	let mk_continuation_call_error eerror p =
-		let econtinuation = make_local vcontinuation p in
-		mk (TCall (econtinuation, [make_null t_dynamic p; eerror])) com.basic.tvoid p
-	in
-
-	let mk_suspending_call call =
-		let p = call.pos in
-
-		(* lose Coroutine<T> type for the called function not to confuse further filters and generators *)
-		let tcoroutine = tfun [t_dynamic; t_dynamic] com.basic.tvoid in
-		let tfun = match follow_with_coro call.efun.etype with
-			| Coro (args, ret) ->
-				let tcontinuation = tfun [ret; t_dynamic] com.basic.tvoid in
-				let args = args @ [("",false,tcontinuation)] in
-				TFun (args, tcoroutine)
-			| NotCoro _ ->
-				die "Unexpected coroutine type" __LOC__
-		in
-		let efun = { call.efun with etype = tfun } in
-		let args = call.args @ [ estatemachine ] in
-		let ecreatecoroutine = mk (TCall (efun, args)) tcoroutine call.pos in
-		let enull = make_null t_dynamic p in
-		mk (TCall (ecreatecoroutine, [enull; enull])) com.basic.tvoid call.pos
-	in
-
-	(* TODO: stolen from exceptions.ml. we should really figure out the filter ordering here *)
-	let std_is e t =
-		let std_cls =
-			(* TODO: load it? *)
-			match (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> die "" __LOC__) with
-			| TClassDecl cls -> cls
-			| _ -> die "" __LOC__
-		in
-		let isOfType_field =
-			try PMap.find "isOfType" std_cls.cl_statics
-			with Not_found -> die "" __LOC__
-		in
-		let type_expr = mk (TTypeExpr (module_type_of_type t)) t_dynamic null_pos in
-		let isOfType_expr = Typecore.make_static_field_access std_cls isOfType_field isOfType_field.cf_type null_pos in
-		mk (TCall (isOfType_expr, [e; type_expr])) com.basic.tbool null_pos
-	in
-
-
-	let states = ref [] in
-
-	let exc_states = ref [] in
-
-	let debug_endline s =
-		if ctx.config.coro_debug then
-			print_endline s
-	in
-	(* TODO: maybe merge this into block_to_texpr somehow, and only introduce new states when there is a suspension point *)
-	debug_endline "---";
-	let rec loop bb state_id back_state_id current_el while_loop exc_state_id_getter =
-		let p = bb.bb_pos in
-		(* TODO: only do this in the end, avoid unnecessary List.rev *)
-		let el = DynArray.to_list bb.bb_el in
-
-		let ereturn = mk (TReturn None) com.basic.tvoid p in
-
-		let add_state el =
-			states := (state_id,mk (TBlock el) com.basic.tvoid null_pos) :: !states
-		in
-		let get_cond_branch () = match bb.bb_terminator with TermCondBranch e -> e | _ -> die "" __LOC__ in
-
-		match bb.bb_syntax_edge with
-		| SESuspend (call, bb_next) ->
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "suspend cur:%d,next:%d,back:%d" state_id next_state_id back_state_id);
-			loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter;
-			let ecallcoroutine = mk_suspending_call call in
-			let esetstate = set_state next_state_id in
-			add_state (current_el @ el @ [esetstate; ecallcoroutine; ereturn])
-
-		| SENone ->
-			debug_endline (Printf.sprintf "none cur:%d,back:%d" state_id back_state_id);
-			(match bb.bb_terminator with
-			| TermBreak _ -> (* todo use pos *)
-				let _,next_state_id = Option.get while_loop in
-				let esetstate = set_state next_state_id in
-				add_state (current_el @ el @ [esetstate])
-			| TermContinue _ -> (* todo use pos *)
-				let body_state_id,_ = Option.get while_loop in
-				let esetstate = set_state body_state_id in
-				add_state (current_el @ el @ [esetstate])
-			| TermReturn _ | TermReturnValue _ -> (* todo use pos *)
-				let esetstate = set_state (-1) in
-				let eresult = match bb.bb_terminator with
-					| TermReturnValue (e,_) -> e
-					| _ -> make_null t_dynamic p
-				in
-				let ecallcontinuation = mk_continuation_call eresult p in
-				add_state (current_el @ el @ [esetstate; ecallcontinuation; ereturn])
-			| TermNone when back_state_id = -1 ->
-				let esetstate = set_state (-1) in
-				let ecallcontinuation = mk_continuation_call (make_null t_dynamic p) p in
-				add_state (current_el @ el @ [esetstate; ecallcontinuation; ereturn])
-			| TermNone ->
-				add_state (current_el @ el @ [set_state back_state_id])
-			| TermThrow (e,p) ->
-				let ethrow = mk (TThrow e) t_dynamic p in
-				add_state (current_el @ el @ [ethrow])
-			| TermCondBranch _ ->
-				die "unexpected TermCondBranch" __LOC__)
-
-		| SEMerge bb_next ->
-			debug_endline (Printf.sprintf "merge cur:%d,back:%d" state_id back_state_id);
-			loop bb_next state_id back_state_id (current_el @ el) while_loop exc_state_id_getter
-
-		| SESubBlock (bb_sub,bb_next) ->
-			let sub_state_id = get_next_state_id () in
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "sub cur:%d,sub:%d,next:%d,back:%d" state_id sub_state_id next_state_id back_state_id);
-			loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter;
-			loop bb_sub sub_state_id next_state_id [] while_loop exc_state_id_getter;
-			add_state (current_el @ el @ [set_state sub_state_id])
-
-		| SEIfThen (bb_then,bb_next,p) ->
-			let econd = get_cond_branch () in
-			let then_state_id = get_next_state_id () in
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "if-then cur:%d,then:%d,next:%d,back:%d" state_id then_state_id next_state_id back_state_id);
-			loop bb_then then_state_id next_state_id [] while_loop exc_state_id_getter;
-			loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter;
-			let eif = mk (TIf (econd, set_state then_state_id, Some (set_state next_state_id))) com.basic.tint p in
-			add_state (current_el @ el @ [eif])
-
-		| SEIfThenElse (bb_then,bb_else,bb_next,t,p) ->
-			let econd = get_cond_branch () in
-			let then_state_id = get_next_state_id () in
-			let else_state_id = get_next_state_id () in
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "if-then-else cur:%d,then:%d,else:%d,next:%d,back:%d" state_id then_state_id else_state_id next_state_id back_state_id);
-			loop bb_then then_state_id next_state_id [] while_loop exc_state_id_getter;
-			loop bb_else else_state_id next_state_id [] while_loop exc_state_id_getter;
-			loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter;
-			let eif = mk (TIf (econd, set_state then_state_id, Some (set_state else_state_id))) com.basic.tint p in
-			add_state (current_el @ el @ [eif])
-
-		| SESwitch switch ->
-			let esubj = get_cond_branch () in
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "switch cur:%d,next:%d,back:%d" state_id next_state_id back_state_id);
-			let ecases = List.map (fun (patterns,bb) ->
-				(* TODO: variable capture and other fancy things O_o *)
-				let case_state_id = get_next_state_id () in
-				debug_endline (Printf.sprintf "  case %d" case_state_id);
-				loop bb case_state_id next_state_id [] while_loop exc_state_id_getter;
-				{case_patterns = patterns;case_expr = set_state case_state_id}
-			) switch.ss_cases in
-			let default_state_id = match switch.ss_default with
-				| Some bb ->
-					let default_state_id = get_next_state_id () in
-					loop bb default_state_id next_state_id [] while_loop exc_state_id_getter;
-					default_state_id
-				| None ->
-					next_state_id
-			in
-			debug_endline (Printf.sprintf "  default %d" default_state_id);
-			let eswitch = mk_switch esubj ecases (Some (set_state default_state_id)) true in
-			let eswitch = mk (TSwitch eswitch) com.basic.tvoid p in
-			loop switch.ss_next next_state_id back_state_id [] while_loop exc_state_id_getter;
-			add_state (current_el @ el @ [eswitch])
-
-		| SEWhile (bb_body, bb_next, p) ->
-			let body_state_id = get_next_state_id () in
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "while cur:%d,body:%d,next:%d,back:%d" state_id body_state_id next_state_id back_state_id);
-			let new_while_loop = Some (body_state_id,next_state_id) in
-			(* TODO: next is empty? *)
-			loop bb_body body_state_id body_state_id [] new_while_loop exc_state_id_getter;
-			loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter;
-			add_state (current_el @ el @ [set_state body_state_id]);
-
-		| SETry (bb_try,_,catches,bb_next,p) ->
-			let try_state_id = get_next_state_id () in
-			let new_exc_state_id = get_next_state_id () in
-			let next_state_id = get_next_state_id () in
-			debug_endline (Printf.sprintf "try cur:%d,try:%d,catch:%d,next:%d,back:%d" state_id try_state_id new_exc_state_id next_state_id back_state_id);
-			loop bb_try try_state_id next_state_id [set_excstate new_exc_state_id] while_loop (fun () -> new_exc_state_id); (* TODO: add test for nested try/catch *)
-			let esetexcstate = set_excstate (exc_state_id_getter ()) in
-			let catch_case =
-				let erethrow = mk (TThrow eerror) t_dynamic null_pos in
-				let eif =
-					List.fold_left (fun enext (vcatch,bb_catch) ->
-						let catch_state_id = get_next_state_id () in
-						let ecatchvar = mk (TVar (vcatch, Some eerror)) com.basic.tvoid null_pos in
-						loop bb_catch catch_state_id next_state_id [esetexcstate; ecatchvar] while_loop exc_state_id_getter;
-
-						(* TODO: exceptions filter... *)
-						match follow vcatch.v_type with
-						| TDynamic _ ->
-							set_state catch_state_id (* no next *)
-						| t ->
-							let etypecheck = std_is (make_local verror null_pos) vcatch.v_type in
-							mk (TIf (etypecheck, set_state catch_state_id, Some enext)) com.basic.tvoid null_pos
-					) erethrow catches
-				in
-				(new_exc_state_id, eif)
-			in
-			exc_states := catch_case :: !exc_states;
-			loop bb_next next_state_id back_state_id [esetexcstate (* TODO: test propagation after try/catch *)] while_loop exc_state_id_getter;
-			add_state (current_el @ el @ [set_state try_state_id])
-	in
-	loop bb (get_next_state_id ()) (-1) [] None get_rethrow_state_id;
-
-	let states = !states @ !exc_states in
-
-	(* TODO: this (and the coroutine transform in general) should probably be run before captured vars handling *)
-	(* very ugly, but seems to work: extract locals that are used across states *)
-	let var_usages = Hashtbl.create 5 in
-	begin
-		let use v state_id =
-			let m = try
-				Hashtbl.find var_usages v.v_id
-			with Not_found ->
-				let m = Hashtbl.create 1 in
-				Hashtbl.add var_usages v.v_id m;
-				m
-			in
-			Hashtbl.replace m state_id true
-		in
-		List.iter (fun (state_id, expr) ->
-			let rec loop e =
-				match e.eexpr with
-				| TVar (v, eo) ->
-					Option.may loop eo;
-					use v state_id;
-				| TLocal v ->
-					use v state_id;
-				| _ ->
-					Type.iter loop e
-			in
-			loop expr
-		) states;
-	end;
-	let states, decls = begin
-		let is_used_across_states v_id =
-			let m = Hashtbl.find var_usages v_id in
-			(Hashtbl.length m) > 1
-		in
-		let rec loop cases cases_acc decls =
-			match cases with
-			| (id,expr) :: rest ->
-				let decls = ref decls in
-				let expr = begin
-					let rec loop e =
-						match e.eexpr with
-						| TVar (v, eo) when is_used_across_states v.v_id ->
-							decls := v :: !decls;
-							let elocal = make_local v e.epos in
-							(match eo with
-							| None -> elocal
-							| Some einit -> mk (TBinop (OpAssign,elocal,einit)) v.v_type e.epos)
-						| _ ->
-							Type.map_expr loop e
-					in
-					loop expr
-				end in
-				loop rest ((id,expr) :: cases_acc) !decls
-			| [] ->
-				List.rev cases_acc, decls
-		in
-		loop states [] []
-	end in
-
-	(* TODO:
-		we can optimize while and switch in some cases:
-		- if there's only one state (no suspensions) - don't wrap into while/switch, don't introduce state var
-	*)
-
-	let rethrow_state_id = get_rethrow_state_id () in
-	let rethrow_state = (rethrow_state_id, mk (TThrow eerror) com.basic.tvoid null_pos) in
-	let states = states @ [rethrow_state] in
-
-	let ethrow = mk (TBlock [
-		set_state rethrow_state_id;
-		mk (TThrow (make_string com.basic "Invalid coroutine state" p)) com.basic.tvoid p
-	]) com.basic.tvoid null_pos
-	in
-
-	let switch =
-		let cases = List.map (fun (id,e) -> {case_patterns = [mk_int id];case_expr = e}) states in
-		mk_switch estate cases (Some ethrow) true
-	in
-	let eswitch = mk (TSwitch switch) com.basic.tvoid p in
-
-	let etry = mk (TTry (
-		eswitch,
-		[
-			let vcaught = alloc_var VGenerated "e" t_dynamic null_pos in
-			declare_var ctx.graph vcaught bb;
-			(vcaught, mk (TIf (
-				mk (TBinop (OpEq, estate, mk_int rethrow_state_id)) com.basic.tbool null_pos,
-				mk (TBlock [
-					mk_assign eexcstate (mk_int rethrow_state_id);
-					mk_continuation_call_error (make_local vcaught null_pos) null_pos;
-					mk (TReturn None) com.basic.tvoid null_pos;
-				]) com.basic.tvoid null_pos,
-				Some (mk (TBlock [
-					mk_assign estate eexcstate;
-					mk_assign eerror (make_local vcaught null_pos);
-				]) com.basic.tvoid null_pos)
-			)) com.basic.tvoid null_pos)
-		]
-	)) com.basic.tvoid null_pos in
-
-	let eloop = mk (TWhile (make_bool com.basic true p, etry, DoWhile)) com.basic.tvoid p in
-
-	let eif = mk (TIf (
-		mk (TBinop (
-			OpNotEq,
-			eerror,
-			make_null verror.v_type p
-		)) com.basic.tbool p,
-		mk_assign estate eexcstate,
-		None
-	)) com.basic.tvoid p in
-
-	let estatemachine_def = mk (TFunction {
-		tf_args = [(vresult,None); (verror,None)];
-		tf_type = com.basic.tvoid;
-		tf_expr = mk (TBlock [eif; eloop]) com.basic.tvoid null_pos
-	}) tstatemachine p in
-
-	let state_var = mk (TVar (vstate, Some (make_int com.basic 0 p))) com.basic.tvoid p in
-	let excstate_var = mk (TVar (vexcstate, Some (make_int com.basic rethrow_state_id p))) com.basic.tvoid p in
-	let shared_vars = List.map (fun v -> mk (TVar (v,None)) com.basic.tvoid null_pos) decls in
-	let shared_vars = List.rev (excstate_var :: state_var :: shared_vars) in
-
-	mk (TBlock (shared_vars @ [
-		mk (TVar (vstatemachine, Some estatemachine_def)) com.basic.tvoid p;
-		mk (TReturn (Some estatemachine)) com.basic.tvoid p;
-	])) com.basic.tvoid p

+ 0 - 10
src/optimization/analyzerTexpr.ml

@@ -96,16 +96,6 @@ let can_throw e =
 	with Exit ->
 		true
 
-
-let terminator_to_texpr_maybe = function
-| AnalyzerTypes.BasicBlock.TermReturn p -> Some (mk (TReturn None) t_dynamic p)
-| TermBreak p -> Some (mk TBreak t_dynamic p)
-| TermContinue p -> Some (mk TContinue t_dynamic p)
-| TermReturnValue(e1,p) -> Some (mk (TReturn (Some e1)) t_dynamic p)
-| TermThrow(e1,p) -> Some (mk (TThrow e1) t_dynamic p)
-| TermCondBranch e1 -> Some e1 (* TODO: this shouldn't be here *)
-| _ -> None
-
 let rec can_be_inlined e = match e.eexpr with
 	| TConst _ -> true
 	| TParenthesis e1 | TMeta(_,e1) -> can_be_inlined e1

+ 15 - 62
src/optimization/analyzerTexprTransformer.ml

@@ -44,18 +44,7 @@ let rec func ctx bb tf t p =
 	in
 	let bb_root = create_node (BKFunctionBegin tf) tf.tf_expr.etype tf.tf_expr.epos in
 	let bb_exit = create_node BKFunctionEnd tf.tf_expr.etype tf.tf_expr.epos in
-	let coroutine =
-
-		(* | Coro _ ->
-			let v_result = alloc_var VGenerated "_hx_result" t_dynamic p in
-			let v_error = alloc_var VGenerated "_hx_error" t_dynamic p in
-			declare_var ctx.graph v_result bb_root;
-			declare_var ctx.graph v_error bb_root;
-			Some (v_result,v_error)
-		| NotCoro _ -> *)
-			None
-	in
-	add_function g tf t p bb_root coroutine;
+	add_function g tf t p bb_root;
 	add_cfg_edge bb bb_root CFGFunction;
 	let bb_breaks = ref [] in
 	let bb_continue = ref None in
@@ -342,34 +331,8 @@ let rec func ctx bb tf t p =
 		let el = Codegen.UnificationCallback.check_call check el e1.etype in
 		let bb,el = ordered_value_list !bb (e1 :: el) in
 		match el with
-			| efun :: el ->
-				let is_coroutine efun =
-					match follow_with_coro efun.etype with
-					| Coro _ -> true
-					| NotCoro _ -> false
-				in
-				(match coroutine with
-					| Some (vresult,_) when is_coroutine efun ->
-						let bb_next = create_node BKNormal e1.etype e1.epos in
-						add_cfg_edge bb bb_next CFGGoto;
-						let syntax_edge = SESuspend (
-							{
-								efun = efun;
-								args = el;
-								pos = e.epos;
-							},
-							bb_next
-						) in
-						set_syntax_edge bb syntax_edge;
-						close_node bb;
-						let eresult = Texpr.Builder.make_local vresult e.epos in
-						let eresult = mk_cast eresult e.etype e.epos in
-						bb_next,eresult
-					| _ ->
-						bb,{e with eexpr = TCall (efun,el)}
-				)
-			| _ ->
-				die "" __LOC__
+			| e1 :: el -> bb,{e with eexpr = TCall(e1,el)}
+			| _ -> die "" __LOC__
 	and array_assign_op bb op e ea e1 e2 e3 =
 		let bb,e1 = bind_to_temp bb e1 in
 		let bb,e2 = bind_to_temp bb e2 in
@@ -723,6 +686,15 @@ let from_tfunction ctx tf t p =
 	close_node g.g_root;
 	g.g_exit <- bb_exit
 
+let terminator_to_texpr_maybe = function
+	| TermReturn p -> Some (mk (TReturn None) t_dynamic p)
+	| TermBreak p -> Some (mk TBreak t_dynamic p)
+	| TermContinue p -> Some (mk TContinue t_dynamic p)
+	| TermReturnValue(e1,p) -> Some (mk (TReturn (Some e1)) t_dynamic p)
+	| TermThrow(e1,p) -> Some (mk (TThrow e1) t_dynamic p)
+	| TermCondBranch e1 -> Some e1 (* TODO: this shouldn't be here *)
+	| _ -> None
+
 let rec block_to_texpr_el ctx bb =
 	if bb.bb_dominator == ctx.graph.g_unreachable then
 		[]
@@ -758,8 +730,6 @@ let rec block_to_texpr_el ctx bb =
 				}) ss.ss_cases in
 				let switch = mk_switch (get_terminator()) cases (Option.map block ss.ss_default) ss.ss_exhaustive in
 				Some ss.ss_next,Some (mk (TSwitch switch) ctx.com.basic.tvoid ss.ss_pos)
-			| SESuspend _ ->
-				assert false
 		in
 		let bb_next,e_term = loop bb bb.bb_syntax_edge in
 		let el = DynArray.to_list bb.bb_el in
@@ -781,25 +751,8 @@ and block_to_texpr ctx bb =
 	e
 
 and func ctx i =
-	let tfi = Hashtbl.find ctx.graph.g_functions i in
-	let tf = tfi.tf_tf in
-	let bb = tfi.tf_bb in
-	let p = tfi.tf_pos in
-	let e,tf_args,tf_type =
-		match tfi.tf_coroutine with
-		| Some (vresult,verror) ->
-			let vcontinuation = alloc_var VGenerated "_hx_continuation" (tfun [tf.tf_type; t_dynamic] ctx.com.basic.tvoid) p in
-			add_var_flag vcontinuation VCaptured;
-			declare_var ctx.graph vcontinuation bb;
-			let e = AnalyzerCoro.block_to_texpr_coroutine ctx bb vcontinuation vresult verror p in
-			(* All actual arguments will be captured after the transformation. *)
-			List.iter (fun (v,_) -> add_var_flag v VCaptured) tf.tf_args;
-			let tf_args = tf.tf_args @ [(vcontinuation,None)] in
-			let sm_type = tfun [t_dynamic; t_dynamic] ctx.com.basic.tvoid in
-			e, tf_args, sm_type
-		| None ->
-			block_to_texpr ctx bb, tf.tf_args, tf.tf_type
-	in
+	let bb,t,p,tf = Hashtbl.find ctx.graph.g_functions i in
+	let e = block_to_texpr ctx bb in
 	let rec loop e = match e.eexpr with
 		| TLocal v ->
 			{e with eexpr = TLocal (get_var_origin ctx.graph v)}
@@ -842,7 +795,7 @@ and func ctx i =
 			Type.map_expr loop e
 	in
 	let e = loop e in
-	mk (TFunction {tf with tf_args = tf_args; tf_type = tf_type; tf_expr = e}) tfi.tf_t p
+	mk (TFunction {tf with tf_expr = e}) t p
 
 let to_texpr ctx =
 	func ctx ctx.entry.bb_id

+ 4 - 14
src/optimization/analyzerTypes.ml

@@ -73,7 +73,6 @@ module BasicBlock = struct
 		| SEWhile of t * t * pos                                 (* `while` with "body" and "next" *)
 		| SESubBlock of t * t                                    (* "sub" with "next" *)
 		| SEMerge of t                                           (* Merge to same block *)
-		| SESuspend of (suspend_call * t)                        (* Suspension point *)
 		| SENone                                                 (* No syntax exit *)
 
 	and syntax_switch = {
@@ -254,14 +253,7 @@ end
 module Graph = struct
 	open BasicBlock
 
-	type tfunc_info = {
-		tf_bb : BasicBlock.t;
-		tf_t : Type.t;
-		tf_pos : pos;
-		tf_tf : tfunc;
-		tf_coroutine : (tvar * tvar) option;
-	}
-
+	type tfunc_info = BasicBlock.t * Type.t * pos * tfunc
 	type texpr_lookup = BasicBlock.t * texpr_lookup_target
 	type var_write = BasicBlock.t list
 	type 'a itbl = (int,'a) Hashtbl.t
@@ -347,8 +339,8 @@ module Graph = struct
 
 	(* nodes *)
 
-	let add_function g tf_tf tf_t tf_pos tf_bb tf_coroutine =
-		Hashtbl.add g.g_functions tf_bb.bb_id ({tf_bb;tf_t;tf_pos;tf_tf;tf_coroutine})
+	let add_function g tf t p bb =
+		Hashtbl.add g.g_functions bb.bb_id (bb,t,p,tf)
 
 	let alloc_id =
 		let r = ref 1 in
@@ -598,13 +590,11 @@ module Graph = struct
 					loop scopes bb_next
 				| SEMerge bb ->
 					loop scopes bb
-				| SESuspend (_, bb) ->
-					loop scopes bb
 				| SENone ->
 					()
 			end
 		in
-		Hashtbl.iter (fun _ tfi -> loop [0] tfi.tf_bb) g.g_functions
+		Hashtbl.iter (fun _ (bb,_,_,_) -> loop [0] bb) g.g_functions
 end
 
 type analyzer_context = {