summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asmcomp/closure.ml40
1 files changed, 33 insertions, 7 deletions
diff --git a/asmcomp/closure.ml b/asmcomp/closure.ml
index e12fa3bbc..e76907ba3 100644
--- a/asmcomp/closure.ml
+++ b/asmcomp/closure.ml
@@ -530,6 +530,13 @@ let approx_ulam = function
Uconst c -> Value_const c
| _ -> Value_unknown
+let find_action idxs acts tag =
+ let res = ref None in
+ for i = 0 to Array.length idxs - 1 do
+ if idxs.(i) = tag then res := Some acts.(i)
+ done;
+ !res
+
let rec substitute fpc sb ulam =
match ulam with
Uvar v ->
@@ -574,13 +581,32 @@ let rec substitute fpc sb ulam =
simplif_prim fpc p (sargs, List.map approx_ulam sargs) dbg in
res
| Uswitch(arg, sw) ->
- Uswitch(substitute fpc sb arg,
- { sw with
- us_actions_consts =
- Array.map (substitute fpc sb) sw.us_actions_consts;
- us_actions_blocks =
- Array.map (substitute fpc sb) sw.us_actions_blocks;
- })
+ let sarg = substitute fpc sb arg in
+ let action =
+ (* Unfortunately, we cannot easily deal with the
+ case of a constructed block (makeblock) bound to a local
+ identifier. This would require to keep track of
+ local let bindings (at least their approximations)
+ in this substitute function.
+ *)
+ match sarg with
+ | Uconst (Uconst_ref (_, Uconst_block (tag, _))) ->
+ find_action sw.us_index_blocks sw.us_actions_blocks tag
+ | Uconst (Uconst_ptr tag) ->
+ find_action sw.us_index_consts sw.us_actions_consts tag
+ | _ -> None
+ in
+ begin match action with
+ | Some u -> substitute fpc sb u
+ | None ->
+ Uswitch(sarg,
+ { sw with
+ us_actions_consts =
+ Array.map (substitute fpc sb) sw.us_actions_consts;
+ us_actions_blocks =
+ Array.map (substitute fpc sb) sw.us_actions_blocks;
+ })
+ end
| Ustringswitch(arg,sw,d) ->
Ustringswitch
(substitute fpc sb arg,