File 3521-compiler-Add-support-for-checking-annotations-in-SSA.patch of Package erlang
From da38a38bf41689e52a50868fc93ba2b065b8bc65 Mon Sep 17 00:00:00 2001
From: Frej Drejhammar <frej.drejhammar@gmail.com>
Date: Thu, 1 Dec 2022 11:29:49 +0100
Subject: [PATCH 11/13] compiler: Add support for checking annotations in SSA
code
Implement support for checking annotations present in SSA code.
---
lib/compiler/src/beam_ssa_check.erl | 43 +++++++++++++------
lib/compiler/test/beam_ssa_check_SUITE.erl | 6 ++-
.../beam_ssa_check_SUITE_data/annotations.erl | 40 +++++++++++++++++
3 files changed, 75 insertions(+), 14 deletions(-)
create mode 100644 lib/compiler/test/beam_ssa_check_SUITE_data/annotations.erl
diff --git a/lib/compiler/src/beam_ssa_check.erl b/lib/compiler/src/beam_ssa_check.erl
index 53cec045f4..05384fc5f0 100644
--- a/lib/compiler/src/beam_ssa_check.erl
+++ b/lib/compiler/src/beam_ssa_check.erl
@@ -117,11 +117,11 @@ check_exprs(Exprs, Env, #b_function{bs=Blocks}=F) ->
{File,_} = beam_ssa:get_anno(location, F),
check_expr_seq(Exprs, Code, Env, never, File).
-check_expr_seq([{check_expr,Loc,Args,_}|Rest]=Checks,
+check_expr_seq([{check_expr,Loc,Args,Anno}|Rest]=Checks,
[First|Code], Env0, LastMatchedLoc, File) ->
Env = try
?DP("trying:~n pat: ~p~n i: ~p~n", [Args, First]),
- op_check(Args, First, Env0)
+ op_check(Args, Anno, First, Env0)
catch
throw:no_match ->
?DP("op_check did not match~n"),
@@ -146,32 +146,38 @@ check_expr_seq([{check_expr,Loc,Args,_}|_], [], Env, LastMatchedLoc, File) ->
[{File,[{Loc,?MODULE,{no_match,Args,LastMatchedLoc,Env}}]}].
-op_check([set,Result,{atom,_,Op}|PArgs],
- #b_set{dst=Dst,args=AArgs,op=Op}=_I, Env) ->
+op_check([set,Result,{atom,_,Op}|PArgs], PAnno,
+ #b_set{dst=Dst,args=AArgs,op=Op,anno=AAnno}=_I, Env0) ->
?DP("trying set ~p:~n res: ~p <-> ~p~n args: ~p <-> ~p~n i: ~p~n",
[Op, Result, Dst, PArgs, AArgs, _I]),
+ Env = check_annos(PAnno, AAnno, Env0),
op_check_call(Op, Result, Dst, PArgs, AArgs, Env);
-op_check([set,Result,{{atom,_,bif},{atom,_,Op}}|PArgs],
- #b_set{dst=Dst,args=AArgs,op={bif,Op}}=_I, Env) ->
+op_check([set,Result,{{atom,_,bif},{atom,_,Op}}|PArgs], PAnno,
+ #b_set{dst=Dst,args=AArgs,op={bif,Op},anno=AAnno}=_I, Env0) ->
?DP("trying bif ~p:~n res: ~p <-> ~p~n args: ~p <-> ~p~n i: ~p~n",
[Op, Result, Dst, PArgs, AArgs, _I]),
+ Env = check_annos(PAnno, AAnno, Env0),
op_check_call(Op, Result, Dst, PArgs, AArgs, Env);
-op_check([none,{atom,_,ret}|PArgs], #b_ret{arg=AArg}=_I, Env) ->
+op_check([none,{atom,_,ret}|PArgs], PAnno,
+ #b_ret{arg=AArg,anno=AAnno}=_I, Env0) ->
?DP("trying return:, arg: ~p <-> ~p~n i: ~p~n",
[PArgs, [AArg], _I]),
+ Env = check_annos(PAnno, AAnno, Env0),
post_args(PArgs, [AArg], Env);
-op_check([none,{atom,_,br}|PArgs],
- #b_br{bool=ABool,succ=ASucc,fail=AFail}=_I, Env) ->
+op_check([none,{atom,_,br}|PArgs], PAnno,
+ #b_br{bool=ABool,succ=ASucc,fail=AFail,anno=AAnno}=_I, Env0) ->
?DP("trying br: arg: ~p <-> ~p~n i: ~p~n",
[PArgs, [ABool,ASucc,AFail], _I]),
+ Env = check_annos(PAnno, AAnno, Env0),
post_args(PArgs, [ABool,#b_literal{val=ASucc},#b_literal{val=AFail}], Env);
-op_check([none,{atom,_,switch},PArg,PFail,{list,_,PArgs}],
- #b_switch{arg=AArg,fail=AFail,list=AList}=_I, Env0) ->
+op_check([none,{atom,_,switch},PArg,PFail,{list,_,PArgs}], PAnno,
+ #b_switch{arg=AArg,fail=AFail,list=AList,anno=AAnno}=_I, Env0) ->
?DP("trying switch: arg: ~p <-> ~p~n i: ~p~n",
[PArgs, [AArg,AFail,AList], _I]),
- Env = env_post(PArg, AArg, env_post(PFail, #b_literal{val=AFail}, Env0)),
+ Env1 = env_post(PArg, AArg, env_post(PFail, #b_literal{val=AFail}, Env0)),
+ Env = check_annos(PAnno, AAnno, Env1),
post_switch_args(PArgs, AList, Env);
-op_check([label,PLbl], {label,ALbl}, Env) when is_integer(ALbl) ->
+op_check([label,PLbl], _Anno, {label,ALbl}, Env) when is_integer(ALbl) ->
env_post(PLbl, #b_literal{val=ALbl}, Env).
op_check_call(Op, PResult, AResult, PArgs, AArgs, Env0) ->
@@ -345,6 +351,17 @@ build_map_key_list([]) ->
build_map_key_list(E) ->
build_map_key(E).
+check_annos([{term,{atom,_,Key},PTerm}|Patterns], Actual, Env0) ->
+ ?DP("Checking term anno ~p: ~p~nkeys: ~p~n",
+ [Key, PTerm, maps:keys(Actual)]),
+ #{ Key := ATerm } = Actual,
+ ?DP("~p <-> ~p~n", [PTerm, ATerm]),
+ Env = env_post(PTerm, #b_literal{val=ATerm}, Env0),
+ ?DP("ok~n"),
+ check_annos(Patterns, Actual, Env);
+check_annos([], _, Env) ->
+ Env.
+
-spec format_error(term()) -> nonempty_string().
format_error(xfail_passed) ->
diff --git a/lib/compiler/test/beam_ssa_check_SUITE.erl b/lib/compiler/test/beam_ssa_check_SUITE.erl
index 07b429a202..c5bcb78076 100644
--- a/lib/compiler/test/beam_ssa_check_SUITE.erl
+++ b/lib/compiler/test/beam_ssa_check_SUITE.erl
@@ -28,6 +28,7 @@
init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
+ annotation_checks/1,
sanity_checks/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -36,7 +37,7 @@ all() ->
[{group,post_ssa_opt_static}].
groups() ->
- [{post_ssa_opt_static,test_lib:parallel(),[sanity_checks]}].
+ [{post_ssa_opt_static,test_lib:parallel(),[annotation_checks, sanity_checks]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -51,6 +52,9 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+annotation_checks(Config) when is_list(Config) ->
+ run_post_ssa_opt(annotations, Config).
+
sanity_checks(Config) when is_list(Config) ->
run_post_ssa_opt(sanity_checks, Config).
diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/annotations.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/annotations.erl
new file mode 100644
index 0000000000..5e938c2588
--- /dev/null
+++ b/lib/compiler/test/beam_ssa_check_SUITE_data/annotations.erl
@@ -0,0 +1,40 @@
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+-module(annotations).
+
+-export([t0/0]).
+
+%% Check annotations, do not add lines before this function without
+%% changing the location annotation.
+t0() ->
+%ssa% () when post_ssa_opt ->
+%ssa% _ = call(fun return_int/0) { result_type => {t_integer,{17,17}},
+%ssa% location => {_,32} },
+%ssa% _ = call(fun return_tuple/0) {
+%ssa% result_type => {t_tuple,2,true,#{1 => {t_integer,{1,1}},
+%ssa% 2 => {t_integer,{2,2}}}}
+%ssa% }.
+ X = return_int(),
+ Y = return_tuple(),
+ {X, Y}.
+
+return_int() ->
+ 17.
+
+return_tuple() ->
+ {1,2}.
--
2.35.3