2
0
Эх сурвалжийг харах

make `map_values` smarter to avoid temp vars

Simon Krajewski 9 жил өмнө
parent
commit
acb3585c7d
1 өөрчлөгдсөн 38 нэмэгдсэн , 12 устгасан
  1. 38 12
      analyzer.ml

+ 38 - 12
analyzer.ml

@@ -38,12 +38,24 @@ let rec is_const_expression e = match e.eexpr with
 		false
 
 let map_values ?(allow_control_flow=true) f e =
+	let branching = ref false in
+	let efinal = ref None in
+	let f e =
+		if !branching then
+			f e
+		else begin
+			efinal := Some e;
+			mk (TConst TNull) e.etype e.epos
+		end
+	in
 	let rec loop complex e = match e.eexpr with
 		| TIf(e1,e2,Some e3) ->
+			branching := true;
 			let e2 = loop true e2 in
 			let e3 = loop true e3 in
 			{e with eexpr = TIf(e1,e2,Some e3)}
 		| TSwitch(e1,cases,edef) ->
+			branching := true;
 			let cases = List.map (fun (el,e) -> el,loop true e) cases in
 			let edef = Option.map (loop true) edef in
 			{e with eexpr = TSwitch(e1,cases,edef)}
@@ -53,11 +65,13 @@ let map_values ?(allow_control_flow=true) f e =
 			begin match List.rev el with
 			| e1 :: el ->
 				let e1 = loop true e1 in
-				{e with eexpr = TBlock (List.rev (e1 :: el))}
+				let e = {e with eexpr = TBlock (List.rev (e1 :: el))} in
+				{e with eexpr = TMeta((Meta.MergeBlock,[],e.epos),e)}
 			| [] ->
 				f e
 			end
 		| TTry(e1,catches) ->
+			branching := true;
 			let e1 = loop true e1 in
 			let catches = List.map (fun (v,e) -> v,loop true e) catches in
 			{e with eexpr = TTry(e1,catches)}
@@ -72,7 +86,8 @@ let map_values ?(allow_control_flow=true) f e =
 			if not complex then raise Exit;
 			f e
 	in
-	loop false e
+	let e = loop false e in
+	e,!efinal
 
 let can_throw e =
 	let rec loop e = match e.eexpr with
@@ -371,7 +386,7 @@ module TexprFilter = struct
 						| TBinop(OpAssign,{eexpr = TLocal v2},e2) when v1 == v2 -> incr i; e2
 						| _ -> raise Exit
 					in
-					let e = map_values ~allow_control_flow:false check_assign e2 in
+					let e,_ = map_values ~allow_control_flow:false check_assign e2 in
 					let e = match follow e.etype with
 						| TAbstract({a_path=[],"Void"},_) -> {e with etype = v1.v_type}
 						| _ -> e
@@ -435,6 +450,8 @@ module TexprFilter = struct
 							let e2 = replace e2 in
 							let e1 = replace e1 in
 							{e with eexpr = TBinop(op,e1,e2)}
+						| TCall({eexpr = TLocal v},_) when is_unbound v ->
+							e
 						| _ ->
 							Type.map_expr replace e
 					in
@@ -455,6 +472,7 @@ module TexprFilter = struct
 					let e2,f = match e2.eexpr with
 						| TReturn (Some e2) -> e2,(fun e -> {e2 with eexpr = TReturn (Some e)})
 						| TBinop(OpAssign,e21,e22) -> e22,(fun e -> {e2 with eexpr = TBinop(OpAssign,e21,e)})
+						| TVar(v,Some e2) -> e2,(fun e -> {e2 with eexpr = TVar(v,Some e)})
 						| _ -> raise Exit
 					in
 					let ops_match op1 op2 = match op1,op2 with
@@ -987,14 +1005,23 @@ module TexprTransformer = struct
 				mk (TBinop(OpAssign,ev,e)) ev.etype e.epos
 			in
 			begin try
-				let e = map_values assign e in
-				block_element bb e
+				block_element_plus bb (map_values assign e) (fun e -> mk (TVar(v,Some e)) ctx.com.basic.tvoid e.epos)
 			with Exit ->
 				let bb,e = value bb e in
 				add_var_def g bb v;
 				add_texpr g bb (mk (TVar(v,Some e)) ctx.com.basic.tvoid ev.epos);
 				bb
-			end;
+			end
+		and block_element_plus bb (e,efinal) f =
+			let bb = block_element bb e in
+			let bb = match efinal with
+				| None -> bb
+				| Some e -> block_element bb (f e)
+			in
+			bb
+		and block_element_value bb e f =
+			let e,efinal = map_values f e in
+			block_element_plus bb (e,efinal) f
 		and call bb e e1 el =
 			begin match e1.eexpr with
 				| TConst TSuper when ctx.com.platform = Java || ctx.com.platform = Cs ->
@@ -1026,8 +1053,7 @@ module TexprTransformer = struct
 					mk (TBinop(OpAssign,e1,e)) e.etype e.epos
 				in
 				begin try
-					let e = map_values assign e2 in
-					block_element bb e
+					block_element_value bb e2 assign
 				with Exit ->
 					let bb,e2 = value bb e2 in
 					add_var_def g bb v;
@@ -1035,6 +1061,8 @@ module TexprTransformer = struct
 					bb
 				end
 			(* branching *)
+			| TMeta((Meta.MergeBlock,_,_),{eexpr = TBlock el}) ->
+				block_el bb el
 			| TBlock el ->
 				let scope = increase_scope() in
 				let bb_sub = create_node BKSub bb e.etype e.epos in
@@ -1171,8 +1199,7 @@ module TexprTransformer = struct
 			| TReturn (Some e1) ->
 				begin try
 					let mk_return e1 = mk (TReturn (Some e1)) t_dynamic e.epos in
-					let e1 = map_values mk_return e1 in
-					block_element bb e1
+					block_element_value bb e1 mk_return
 				with Exit ->
 					let bb,e1 = value bb e1 in
 					add_cfg_edge g bb bb_exit CFGGoto;
@@ -1193,8 +1220,7 @@ module TexprTransformer = struct
 			| TThrow e1 ->
 				begin try
 					let mk_throw e1 = mk (TThrow e1) t_dynamic e.epos in
-					let e1 = map_values mk_throw e1 in
-					block_element bb e1
+					block_element_value bb e1 mk_throw
 				with Exit ->
 					let bb,e1 = value bb e1 in
 					begin match !b_try_stack with