diff options
author | Frej Drejhammar <frej.drejhammar@gmail.com> | 2022-11-30 14:59:44 +0100 |
---|---|---|
committer | Frej Drejhammar <frej.drejhammar@gmail.com> | 2023-01-19 14:34:24 +0100 |
commit | dae4eda4983741e5631f90c52811fe2aeab84634 (patch) | |
tree | 1611d9bde209cb92e9e57b05f72d81260262144b /lib/compiler/src/compile.erl | |
parent | 0341cdfca0dcff05b629c9e3c0ff77f4b6a593b3 (diff) | |
download | erlang-dae4eda4983741e5631f90c52811fe2aeab84634.tar.gz |
compiler: Implement SSA checking pass
This patch adds a new pass, enabled by `+{check_ssa,post_ssa_opt}`,
which runs after the ssa_opt pass. The pass uses SSA check directives
embedded as comments in the source file and parsed by erl_parse to
check the structure of the emitted BEAM SSA.
In the SSA checker, match rules are applied sequentially on the SSA
representation for a function, in the same order as if it had been
dumped to disk. If the current pattern doesn't match, the checker
tries with the next instruction. If the checker reaches the end of the
SSA representation without having matched all patterns, the check is
considered failed.
When a pattern is matched against an SSA instruction, the values of
variables already bound are considered and if the patterns matches,
free variables introduced in the successfully matched pattern are
bound to the values they have in the matched instruction.
Diffstat (limited to 'lib/compiler/src/compile.erl')
-rw-r--r-- | lib/compiler/src/compile.erl | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 61c2512222..390effeb41 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -291,6 +291,8 @@ expand_opt(no_type_opt=O, Os) -> no_ssa_opt_type_finish | Os]; expand_opt(no_module_opt=O, Os) -> [O,no_recv_opt | Os]; +expand_opt({check_ssa,Tag}, Os) -> + [check_ssa, Tag | Os]; expand_opt(O, Os) -> [O|Os]. -spec format_error(error_description()) -> iolist(). @@ -773,6 +775,16 @@ select_list_passes_1([P|Ps], Opts, Acc) -> select_list_passes_1([], _, Acc) -> {not_done,reverse(Acc)}. +make_ssa_check_pass(PassFlag) -> + F = fun (Code, St) -> + case beam_ssa_check:module(Code, PassFlag) of + ok -> {ok, Code, St}; + {error, Errors} -> + {error, St#compile{errors=St#compile.errors++Errors}} + end + end, + {iff, PassFlag, {PassFlag, F}}. + %% The standard passes (almost) always run. standard_passes() -> @@ -877,6 +889,7 @@ kernel_passes() -> {unless,no_bsm_opt,{iff,ssalint,{pass,beam_ssa_lint}}}, {unless,no_ssa_opt,{pass,beam_ssa_opt}}, + make_ssa_check_pass(post_ssa_opt), {iff,dssaopt,{listing,"ssaopt"}}, {unless,no_ssa_opt,{iff,ssalint,{pass,beam_ssa_lint}}}, @@ -1029,7 +1042,13 @@ do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) -> {location,StartLocation}, {reserved_word_fun, ResWordFun}, {features, Features}, - extra]), + extra| + case member(check_ssa, Opts) of + true -> + [{compiler_internal,[ssa_checks]}]; + false -> + [] + end]), case R of %% FIXME Extra should include used features as well {ok,Forms0,Extra} -> |