Use the fact that SWITCH and JUMPIF can use args and vars
This commit is contained in:
parent
960ffb383f
commit
0ce144db13
@ -14,13 +14,15 @@
|
|||||||
%% -- Preamble ---------------------------------------------------------------
|
%% -- Preamble ---------------------------------------------------------------
|
||||||
|
|
||||||
-type scode() :: [sinstr()].
|
-type scode() :: [sinstr()].
|
||||||
-type sinstr() :: {switch, stype(), [maybe_scode()], maybe_scode()} %% last arg is catch-all
|
-type sinstr() :: {switch, arg(), stype(), [maybe_scode()], maybe_scode()} %% last arg is catch-all
|
||||||
| switch_body
|
| switch_body
|
||||||
| tuple(). %% FATE instruction
|
| tuple(). %% FATE instruction
|
||||||
|
|
||||||
|
-type arg() :: aeb_fate_code:fate_arg().
|
||||||
|
|
||||||
%% Annotated scode
|
%% Annotated scode
|
||||||
-type scode_a() :: [sinstr_a()].
|
-type scode_a() :: [sinstr_a()].
|
||||||
-type sinstr_a() :: {switch, stype(), [maybe_scode_a()], maybe_scode_a()} %% last arg is catch-all
|
-type sinstr_a() :: {switch, arg(), stype(), [maybe_scode_a()], maybe_scode_a()} %% last arg is catch-all
|
||||||
| switch_body
|
| switch_body
|
||||||
| {i, ann(), tuple()}. %% FATE instruction
|
| {i, ann(), tuple()}. %% FATE instruction
|
||||||
|
|
||||||
@ -203,7 +205,7 @@ split_to_scode(Env, {split, {tuple, _}, X, Alts}) ->
|
|||||||
end,
|
end,
|
||||||
case Def == missing andalso Alt /= missing of
|
case Def == missing andalso Alt /= missing of
|
||||||
true -> Alt; % skip the switch if single tuple pattern
|
true -> Alt; % skip the switch if single tuple pattern
|
||||||
false -> [{switch, tuple, [Alt], Def}]
|
false -> [{switch, Arg, tuple, [Alt], Def}]
|
||||||
end;
|
end;
|
||||||
split_to_scode(Env, {split, boolean, X, Alts}) ->
|
split_to_scode(Env, {split, boolean, X, Alts}) ->
|
||||||
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
||||||
@ -214,8 +216,8 @@ split_to_scode(Env, {split, boolean, X, Alts}) ->
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
SAlts = [GetAlt(false), GetAlt(true)],
|
SAlts = [GetAlt(false), GetAlt(true)],
|
||||||
[aeb_fate_code:push(lookup_var(Env, X)),
|
Arg = lookup_var(Env, X),
|
||||||
{switch, boolean, SAlts, Def}];
|
[{switch, Arg, boolean, SAlts, Def}];
|
||||||
split_to_scode(Env, {split, {list, _}, X, Alts}) ->
|
split_to_scode(Env, {split, {list, _}, X, Alts}) ->
|
||||||
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
||||||
Arg = lookup_var(Env, X),
|
Arg = lookup_var(Env, X),
|
||||||
@ -233,10 +235,10 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) ->
|
|||||||
end,
|
end,
|
||||||
SAlts = [GetAlt('::'), GetAlt(nil)],
|
SAlts = [GetAlt('::'), GetAlt(nil)],
|
||||||
[aeb_fate_code:is_nil(?a, Arg),
|
[aeb_fate_code:is_nil(?a, Arg),
|
||||||
{switch, boolean, SAlts, Def}];
|
{switch, ?a, boolean, SAlts, Def}];
|
||||||
split_to_scode(Env, {split, integer, X, Alts}) ->
|
split_to_scode(Env, {split, integer, X, Alts}) ->
|
||||||
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
||||||
literal_split_to_scode(Env, integer, X, Alts1, Def);
|
literal_split_to_scode(Env, integer, lookup_var(Env, X), Alts1, Def);
|
||||||
split_to_scode(Env, {split, {variant, Cons}, X, Alts}) ->
|
split_to_scode(Env, {split, {variant, Cons}, X, Alts}) ->
|
||||||
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
||||||
Arg = lookup_var(Env, X),
|
Arg = lookup_var(Env, X),
|
||||||
@ -252,29 +254,22 @@ split_to_scode(Env, {split, {variant, Cons}, X, Alts}) ->
|
|||||||
case {[GetAlt(I) || I <- lists:seq(0, length(Cons) - 1)], Def} of
|
case {[GetAlt(I) || I <- lists:seq(0, length(Cons) - 1)], Def} of
|
||||||
%% Skip the switch for single constructor datatypes (with no catchall)
|
%% Skip the switch for single constructor datatypes (with no catchall)
|
||||||
{[SAlt], missing} when SAlt /= missing -> SAlt;
|
{[SAlt], missing} when SAlt /= missing -> SAlt;
|
||||||
{[SAlt], _} ->
|
{SAlts, _} -> [{switch, Arg, SType, SAlts, Def}]
|
||||||
%% Single-case switches are not compiled to a SWITCH instruction, so
|
|
||||||
%% we don't need to push the argument. See [SINGLE_CON_SWITCH]
|
|
||||||
%% below. We need the scode switch to keep track of the default
|
|
||||||
%% case though.
|
|
||||||
[{switch, SType, [SAlt], Def}];
|
|
||||||
{SAlts, _} ->
|
|
||||||
[aeb_fate_code:push(Arg), {switch, SType, SAlts, Def}]
|
|
||||||
end;
|
end;
|
||||||
split_to_scode(_, Split = {split, _, _, _}) ->
|
split_to_scode(_, Split = {split, _, _, _}) ->
|
||||||
?TODO({'case', Split}).
|
?TODO({'case', Split}).
|
||||||
|
|
||||||
literal_split_to_scode(_Env, _Type, _X, [], Def) ->
|
literal_split_to_scode(_Env, _Type, Arg, [], Def) ->
|
||||||
{switch, boolean, [missing, missing], Def};
|
{switch, Arg, boolean, [missing, missing], Def};
|
||||||
literal_split_to_scode(Env, integer, X, [{'case', {int, N}, Body} | Alts], Def) ->
|
literal_split_to_scode(Env, integer, Arg, [{'case', {int, N}, Body} | Alts], Def) ->
|
||||||
True = split_to_scode(Env, Body),
|
True = split_to_scode(Env, Body),
|
||||||
False =
|
False =
|
||||||
case Alts of
|
case Alts of
|
||||||
[] -> missing;
|
[] -> missing;
|
||||||
_ -> literal_split_to_scode(Env, integer, X, Alts, missing)
|
_ -> literal_split_to_scode(Env, integer, Arg, Alts, missing)
|
||||||
end,
|
end,
|
||||||
[aeb_fate_code:eq(?a, lookup_var(Env, X), ?i(N)),
|
[aeb_fate_code:eq(?a, Arg, ?i(N)),
|
||||||
{switch, boolean, [False, True], Def}].
|
{switch, ?a, boolean, [False, True], Def}].
|
||||||
|
|
||||||
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
|
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
|
||||||
|
|
||||||
@ -320,8 +315,8 @@ optimize_scode(Funs, Options) ->
|
|||||||
flatten(missing) -> missing;
|
flatten(missing) -> missing;
|
||||||
flatten(Code) -> lists:map(fun flatten_s/1, lists:flatten(Code)).
|
flatten(Code) -> lists:map(fun flatten_s/1, lists:flatten(Code)).
|
||||||
|
|
||||||
flatten_s({switch, Type, Alts, Catch}) ->
|
flatten_s({switch, Arg, Type, Alts, Catch}) ->
|
||||||
{switch, Type, [flatten(Alt) || Alt <- Alts], flatten(Catch)};
|
{switch, Arg, Type, [flatten(Alt) || Alt <- Alts], flatten(Catch)};
|
||||||
flatten_s(I) -> I.
|
flatten_s(I) -> I.
|
||||||
|
|
||||||
-define(MAX_SIMPL_ITERATIONS, 10).
|
-define(MAX_SIMPL_ITERATIONS, 10).
|
||||||
@ -350,16 +345,19 @@ simpl_loop(N, Code, Options) ->
|
|||||||
false -> simpl_loop(N + 1, Code2, Options)
|
false -> simpl_loop(N + 1, Code2, Options)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
pp_ann(Ind, [{switch, Type, Alts, Def} | Code]) ->
|
pp_ann(Ind, [{switch, Arg, Type, Alts, Def} | Code]) ->
|
||||||
Tags =
|
Tags =
|
||||||
case Type of
|
case Type of
|
||||||
boolean -> ["FALSE", "TRUE"];
|
boolean -> ["FALSE", "TRUE"];
|
||||||
tuple -> ["(_)"];
|
tuple -> ["(_)"];
|
||||||
{variant, Ar} -> ["C" ++ integer_to_list(I) || I <- lists:seq(0, length(Ar) - 1)]
|
{variant, Ar} -> ["C" ++ integer_to_list(I) || I <- lists:seq(0, length(Ar) - 1)]
|
||||||
end,
|
end,
|
||||||
[[[Ind, Tag, " =>\n", pp_ann(" " ++ Ind, Alt)]
|
Ind1 = " " ++ Ind,
|
||||||
|
Ind2 = " " ++ Ind1,
|
||||||
|
[Ind, "SWITCH ", pp_arg(Arg), "\n",
|
||||||
|
[[Ind1, Tag, " =>\n", pp_ann(Ind2, Alt)]
|
||||||
|| {Tag, Alt} <- lists:zip(Tags, Alts), Alt /= missing],
|
|| {Tag, Alt} <- lists:zip(Tags, Alts), Alt /= missing],
|
||||||
[[Ind, "_ =>\n", pp_ann(" " ++ Ind, Def)] || Def /= missing],
|
[[Ind1, "_ =>\n", pp_ann(" " ++ Ind, Def)] || Def /= missing],
|
||||||
pp_ann(Ind, Code)];
|
pp_ann(Ind, Code)];
|
||||||
pp_ann(Ind, [switch_body | Code]) ->
|
pp_ann(Ind, [switch_body | Code]) ->
|
||||||
[Ind, "SWITCH-BODY\n", pp_ann(Ind, Code)];
|
[Ind, "SWITCH-BODY\n", pp_ann(Ind, Code)];
|
||||||
@ -373,6 +371,12 @@ pp_ann(Ind, [{i, #{ live_in := In, live_out := Out }, I} | Code]) ->
|
|||||||
pp_ann(Ind, Code)];
|
pp_ann(Ind, Code)];
|
||||||
pp_ann(_, []) -> [].
|
pp_ann(_, []) -> [].
|
||||||
|
|
||||||
|
|
||||||
|
pp_arg(?i(I)) -> io_lib:format("~w", [I]);
|
||||||
|
pp_arg({arg, N}) -> io_lib:format("arg~p", [N]);
|
||||||
|
pp_arg({var, N}) -> io_lib:format("var~p", [N]);
|
||||||
|
pp_arg(?a) -> "a".
|
||||||
|
|
||||||
%% -- Analysis --
|
%% -- Analysis --
|
||||||
|
|
||||||
annotate_code(Code) ->
|
annotate_code(Code) ->
|
||||||
@ -384,11 +388,11 @@ annotate_code(Code) ->
|
|||||||
ann_writes(missing, Writes, []) -> {missing, Writes};
|
ann_writes(missing, Writes, []) -> {missing, Writes};
|
||||||
ann_writes([switch_body | Code], Writes, Acc) ->
|
ann_writes([switch_body | Code], Writes, Acc) ->
|
||||||
ann_writes(Code, Writes, [switch_body | Acc]);
|
ann_writes(Code, Writes, [switch_body | Acc]);
|
||||||
ann_writes([{switch, Type, Alts, Def} | Code], Writes, Acc) ->
|
ann_writes([{switch, Arg, Type, Alts, Def} | Code], Writes, Acc) ->
|
||||||
{Alts1, WritesAlts} = lists:unzip([ ann_writes(Alt, Writes, []) || Alt <- Alts ]),
|
{Alts1, WritesAlts} = lists:unzip([ ann_writes(Alt, Writes, []) || Alt <- Alts ]),
|
||||||
{Def1, WritesDef} = ann_writes(Def, Writes, []),
|
{Def1, WritesDef} = ann_writes(Def, Writes, []),
|
||||||
Writes1 = ordsets:union(Writes, ordsets:intersection([WritesDef | WritesAlts])),
|
Writes1 = ordsets:union(Writes, ordsets:intersection([WritesDef | WritesAlts])),
|
||||||
ann_writes(Code, Writes1, [{switch, Type, Alts1, Def1} | Acc]);
|
ann_writes(Code, Writes1, [{switch, Arg, Type, Alts1, Def1} | Acc]);
|
||||||
ann_writes([I | Code], Writes, Acc) ->
|
ann_writes([I | Code], Writes, Acc) ->
|
||||||
Ws = var_writes(I),
|
Ws = var_writes(I),
|
||||||
Writes1 = ordsets:union(Writes, Ws),
|
Writes1 = ordsets:union(Writes, Ws),
|
||||||
@ -401,11 +405,11 @@ ann_writes([], Writes, Acc) ->
|
|||||||
ann_reads(missing, Reads, []) -> {missing, Reads};
|
ann_reads(missing, Reads, []) -> {missing, Reads};
|
||||||
ann_reads([switch_body | Code], Reads, Acc) ->
|
ann_reads([switch_body | Code], Reads, Acc) ->
|
||||||
ann_reads(Code, Reads, [switch_body | Acc]);
|
ann_reads(Code, Reads, [switch_body | Acc]);
|
||||||
ann_reads([{switch, Type, Alts, Def} | Code], Reads, Acc) ->
|
ann_reads([{switch, Arg, Type, Alts, Def} | Code], Reads, Acc) ->
|
||||||
{Alts1, ReadsAlts} = lists:unzip([ ann_reads(Alt, Reads, []) || Alt <- Alts ]),
|
{Alts1, ReadsAlts} = lists:unzip([ ann_reads(Alt, Reads, []) || Alt <- Alts ]),
|
||||||
{Def1, ReadsDef} = ann_reads(Def, Reads, []),
|
{Def1, ReadsDef} = ann_reads(Def, Reads, []),
|
||||||
Reads1 = ordsets:union([Reads, ReadsDef | ReadsAlts]),
|
Reads1 = ordsets:union([[Arg], Reads, ReadsDef | ReadsAlts]),
|
||||||
ann_reads(Code, Reads1, [{switch, Type, Alts1, Def1} | Acc]);
|
ann_reads(Code, Reads1, [{switch, Arg, Type, Alts1, Def1} | Acc]);
|
||||||
ann_reads([{i, Ann, I} | Code], Reads, Acc) ->
|
ann_reads([{i, Ann, I} | Code], Reads, Acc) ->
|
||||||
#{ writes_in := WritesIn, writes_out := WritesOut } = Ann,
|
#{ writes_in := WritesIn, writes_out := WritesOut } = Ann,
|
||||||
#{ read := Rs, write := W, pure := Pure } = attributes(I),
|
#{ read := Rs, write := W, pure := Pure } = attributes(I),
|
||||||
@ -554,8 +558,8 @@ var_writes(I) ->
|
|||||||
_ -> []
|
_ -> []
|
||||||
end.
|
end.
|
||||||
|
|
||||||
independent({switch, _, _, _}, _) -> false;
|
independent({switch, _, _, _, _}, _) -> false;
|
||||||
independent(_, {switch, _, _, _}) -> false;
|
independent(_, {switch, _, _, _, _}) -> false;
|
||||||
independent(switch_body, _) -> true;
|
independent(switch_body, _) -> true;
|
||||||
independent(_, switch_body) -> true;
|
independent(_, switch_body) -> true;
|
||||||
independent({i, _, I}, {i, _, J}) ->
|
independent({i, _, I}, {i, _, J}) ->
|
||||||
@ -601,8 +605,8 @@ simplify(missing, _) -> missing;
|
|||||||
simplify([I | Code], Options) ->
|
simplify([I | Code], Options) ->
|
||||||
simpl_top(simpl_s(I, Options), simplify(Code, Options), Options).
|
simpl_top(simpl_s(I, Options), simplify(Code, Options), Options).
|
||||||
|
|
||||||
simpl_s({switch, Type, Alts, Def}, Options) ->
|
simpl_s({switch, Arg, Type, Alts, Def}, Options) ->
|
||||||
{switch, Type, [simplify(A, Options) || A <- Alts], simplify(Def, Options)};
|
{switch, Arg, Type, [simplify(A, Options) || A <- Alts], simplify(Def, Options)};
|
||||||
simpl_s(I, _) -> I.
|
simpl_s(I, _) -> I.
|
||||||
|
|
||||||
simpl_top(I, Code, Options) ->
|
simpl_top(I, Code, Options) ->
|
||||||
@ -793,8 +797,8 @@ from_op_view(Op, R, As) -> list_to_tuple([Op, R | As]).
|
|||||||
(sinstr_a()) -> sinstr();
|
(sinstr_a()) -> sinstr();
|
||||||
(missing) -> missing.
|
(missing) -> missing.
|
||||||
unannotate(switch_body) -> [switch_body];
|
unannotate(switch_body) -> [switch_body];
|
||||||
unannotate({switch, Type, Alts, Def}) ->
|
unannotate({switch, Arg, Type, Alts, Def}) ->
|
||||||
[{switch, Type, [unannotate(A) || A <- Alts], unannotate(Def)}];
|
[{switch, Arg, Type, [unannotate(A) || A <- Alts], unannotate(Def)}];
|
||||||
unannotate(missing) -> missing;
|
unannotate(missing) -> missing;
|
||||||
unannotate(Code) when is_list(Code) ->
|
unannotate(Code) when is_list(Code) ->
|
||||||
lists:flatmap(fun unannotate/1, Code);
|
lists:flatmap(fun unannotate/1, Code);
|
||||||
@ -803,8 +807,8 @@ unannotate({i, _Ann, I}) -> [I].
|
|||||||
%% Desugar and specialize
|
%% Desugar and specialize
|
||||||
desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_code:inc()];
|
desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_code:inc()];
|
||||||
desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_code:dec()];
|
desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_code:dec()];
|
||||||
desugar({switch, Type, Alts, Def}) ->
|
desugar({switch, Arg, Type, Alts, Def}) ->
|
||||||
[{switch, Type, [desugar(A) || A <- Alts], desugar(Def)}];
|
[{switch, Arg, Type, [desugar(A) || A <- Alts], desugar(Def)}];
|
||||||
desugar(missing) -> missing;
|
desugar(missing) -> missing;
|
||||||
desugar(Code) when is_list(Code) ->
|
desugar(Code) when is_list(Code) ->
|
||||||
lists:flatmap(fun desugar/1, Code);
|
lists:flatmap(fun desugar/1, Code);
|
||||||
@ -858,7 +862,7 @@ block(#blk{ref = Ref, code = []}, CodeAcc, Blocks, BlockAcc) ->
|
|||||||
block(Blk = #blk{code = [switch_body | Code]}, Acc, Blocks, BlockAcc) ->
|
block(Blk = #blk{code = [switch_body | Code]}, Acc, Blocks, BlockAcc) ->
|
||||||
%% Reached the body of a switch. Clear catchall ref.
|
%% Reached the body of a switch. Clear catchall ref.
|
||||||
block(Blk#blk{code = Code, catchall = none}, Acc, Blocks, BlockAcc);
|
block(Blk#blk{code = Code, catchall = none}, Acc, Blocks, BlockAcc);
|
||||||
block(Blk = #blk{code = [{switch, Type, Alts, Default} | Code],
|
block(Blk = #blk{code = [{switch, Arg, Type, Alts, Default} | Code],
|
||||||
catchall = Catchall}, Acc, Blocks, BlockAcc) ->
|
catchall = Catchall}, Acc, Blocks, BlockAcc) ->
|
||||||
FreshBlk = fun(C, Ca) ->
|
FreshBlk = fun(C, Ca) ->
|
||||||
R = make_ref(),
|
R = make_ref(),
|
||||||
@ -887,7 +891,7 @@ block(Blk = #blk{code = [{switch, Type, Alts, Default} | Code],
|
|||||||
missing -> [{jump, DefRef}];
|
missing -> [{jump, DefRef}];
|
||||||
_ -> FalseCode ++ [{jump, RestRef}]
|
_ -> FalseCode ++ [{jump, RestRef}]
|
||||||
end,
|
end,
|
||||||
{Blk#blk{code = ElseCode}, [{jumpif, ThenRef}], ThenBlk};
|
{Blk#blk{code = ElseCode}, [{jumpif, Arg, ThenRef}], ThenBlk};
|
||||||
tuple ->
|
tuple ->
|
||||||
[TCode] = Alts,
|
[TCode] = Alts,
|
||||||
{Blk#blk{code = TCode ++ [{jump, RestRef}]}, [], []};
|
{Blk#blk{code = TCode ++ [{jump, RestRef}]}, [], []};
|
||||||
@ -901,7 +905,7 @@ block(Blk = #blk{code = [{switch, Type, Alts, Default} | Code],
|
|||||||
(ACode) -> FreshBlk(ACode ++ [{jump, RestRef}], DefRef)
|
(ACode) -> FreshBlk(ACode ++ [{jump, RestRef}], DefRef)
|
||||||
end,
|
end,
|
||||||
{AltRefs, AltBs} = lists:unzip(lists:map(MkBlk, Alts)),
|
{AltRefs, AltBs} = lists:unzip(lists:map(MkBlk, Alts)),
|
||||||
{Blk#blk{code = []}, [{switch, AltRefs}], lists:append(AltBs)}
|
{Blk#blk{code = []}, [{switch, Arg, AltRefs}], lists:append(AltBs)}
|
||||||
end,
|
end,
|
||||||
Blk2 = Blk1#blk{catchall = DefRef}, %% Update catchall ref
|
Blk2 = Blk1#blk{catchall = DefRef}, %% Update catchall ref
|
||||||
block(Blk2, Code1 ++ Acc, DefBlk ++ RestBlk ++ AltBlks ++ Blocks, BlockAcc);
|
block(Blk2, Code1 ++ Acc, DefBlk ++ RestBlk ++ AltBlks ++ Blocks, BlockAcc);
|
||||||
@ -933,7 +937,7 @@ reorder_blocks(Ref, Code, Blocks, Acc) ->
|
|||||||
['RETURN'|_] -> reorder_blocks(Blocks, Acc1);
|
['RETURN'|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{'RETURNR', _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{'RETURNR', _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{'ABORT', _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{'ABORT', _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{switch, _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{switch, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{jump, L}|_] ->
|
[{jump, L}|_] ->
|
||||||
NotL = fun({L1, _}) -> L1 /= L end,
|
NotL = fun({L1, _}) -> L1 /= L end,
|
||||||
case lists:splitwith(NotL, Blocks) of
|
case lists:splitwith(NotL, Blocks) of
|
||||||
@ -962,10 +966,10 @@ remove_dead_blocks(Blocks = [{Top, _} | _]) ->
|
|||||||
chase_labels([], _, Live) -> Live;
|
chase_labels([], _, Live) -> Live;
|
||||||
chase_labels([L | Ls], Map, Live) ->
|
chase_labels([L | Ls], Map, Live) ->
|
||||||
Code = maps:get(L, Map),
|
Code = maps:get(L, Map),
|
||||||
Jump = fun({jump, A}) -> [A || not maps:is_key(A, Live)];
|
Jump = fun({jump, A}) -> [A || not maps:is_key(A, Live)];
|
||||||
({jumpif, A}) -> [A || not maps:is_key(A, Live)];
|
({jumpif, _, A}) -> [A || not maps:is_key(A, Live)];
|
||||||
({switch, As}) -> [A || A <- As, not maps:is_key(A, Live)];
|
({switch, _, As}) -> [A || A <- As, not maps:is_key(A, Live)];
|
||||||
(_) -> [] end,
|
(_) -> [] end,
|
||||||
New = lists:flatmap(Jump, Code),
|
New = lists:flatmap(Jump, Code),
|
||||||
chase_labels(New ++ Ls, Map, Live#{ L => true }).
|
chase_labels(New ++ Ls, Map, Live#{ L => true }).
|
||||||
|
|
||||||
@ -979,12 +983,12 @@ use_returnr(Code) -> Code.
|
|||||||
set_labels(Labels, {Ref, Code}) when is_reference(Ref) ->
|
set_labels(Labels, {Ref, Code}) when is_reference(Ref) ->
|
||||||
{maps:get(Ref, Labels), [ set_labels(Labels, I) || I <- Code ]};
|
{maps:get(Ref, Labels), [ set_labels(Labels, I) || I <- Code ]};
|
||||||
set_labels(Labels, {jump, Ref}) -> aeb_fate_code:jump(maps:get(Ref, Labels));
|
set_labels(Labels, {jump, Ref}) -> aeb_fate_code:jump(maps:get(Ref, Labels));
|
||||||
set_labels(Labels, {jumpif, Ref}) -> aeb_fate_code:jumpif(?a, maps:get(Ref, Labels));
|
set_labels(Labels, {jumpif, Arg, Ref}) -> aeb_fate_code:jumpif(Arg, maps:get(Ref, Labels));
|
||||||
set_labels(Labels, {switch, Refs}) ->
|
set_labels(Labels, {switch, Arg, Refs}) ->
|
||||||
case [ maps:get(Ref, Labels) || Ref <- Refs ] of
|
case [ maps:get(Ref, Labels) || Ref <- Refs ] of
|
||||||
[R1, R2] -> aeb_fate_code:switch(?a, R1, R2);
|
[R1, R2] -> aeb_fate_code:switch(Arg, R1, R2);
|
||||||
[R1, R2, R3] -> aeb_fate_code:switch(?a, R1, R2, R3);
|
[R1, R2, R3] -> aeb_fate_code:switch(Arg, R1, R2, R3);
|
||||||
Rs -> aeb_fate_code:switch(?a, Rs)
|
Rs -> aeb_fate_code:switch(Arg, Rs)
|
||||||
end;
|
end;
|
||||||
set_labels(_, I) -> I.
|
set_labels(_, I) -> I.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user