summaryrefslogtreecommitdiff
path: root/lib/compiler/src/compile.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src/compile.erl')
-rw-r--r--lib/compiler/src/compile.erl176
1 files changed, 117 insertions, 59 deletions
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 4fc24c43d7..7ef37a6082 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -49,9 +49,7 @@
-type abstract_code() :: [erl_parse:abstract_form()].
-%% Internal representations used for 'from_asm' compilation can also be valid,
-%% but have no relevant types defined.
--type forms() :: abstract_code() | cerl:c_module().
+-type forms() :: abstract_code() | cerl:c_module() | beam_disasm:asm_form().
-type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
@@ -264,25 +262,19 @@ expand_opt(report, Os) ->
[report_errors,report_warnings|Os];
expand_opt(return, Os) ->
[return_errors,return_warnings|Os];
-expand_opt(no_bsm3, Os) ->
- %% The new bsm pass requires bsm3 instructions.
- [no_bsm3,no_bsm_opt|expand_opt(no_bsm4, Os)];
expand_opt(no_bsm4, Os) ->
%% bsm4 instructions are only used when type optimization has determined
%% that a match instruction won't fail.
expand_opt(no_type_opt, Os);
-expand_opt(r18, Os) ->
- expand_opt_before_21(Os);
-expand_opt(r19, Os) ->
- expand_opt_before_21(Os);
-expand_opt(r20, Os) ->
- expand_opt_before_21(Os);
-expand_opt(r21, Os) ->
- expand_opt(r22, [no_put_tuple2 | expand_opt(no_bsm3, Os)]);
expand_opt(r22, Os) ->
- expand_opt(r23, [no_shared_fun_wrappers, no_swap | expand_opt(no_bsm4, Os)]);
+ expand_opt(r23, [no_bs_create_bin, no_shared_fun_wrappers,
+ no_swap | expand_opt(no_bsm4, Os)]);
expand_opt(r23, Os) ->
- expand_opt(no_make_fun3, [no_ssa_opt_float, no_recv_opt, no_init_yregs | Os]);
+ expand_opt(no_make_fun3, [no_bs_create_bin, no_ssa_opt_float,
+ no_recv_opt, no_init_yregs |
+ expand_opt(r24, Os)]);
+expand_opt(r24, Os) ->
+ expand_opt(no_type_opt, [no_bs_create_bin, no_ssa_opt_ranges | Os]);
expand_opt(no_make_fun3, Os) ->
[no_make_fun3, no_fun_opt | Os];
expand_opt({debug_info_key,_}=O, Os) ->
@@ -298,15 +290,10 @@ expand_opt(no_module_opt=O, Os) ->
[O,no_recv_opt | Os];
expand_opt(O, Os) -> [O|Os].
-expand_opt_before_21(Os) ->
- [no_init_yregs, no_make_fun3, no_fun_opt,
- no_shared_fun_wrappers, no_swap,
- no_put_tuple2, no_get_hd_tl, no_ssa_opt_record,
- no_utf8_atoms, no_recv_opt | expand_opt(no_bsm3, Os)].
-
-
-spec format_error(error_description()) -> iolist().
+format_error({obsolete_option,Ver}) ->
+ io_lib:fwrite("the ~p option is no longer supported", [Ver]);
format_error(no_crypto) ->
"this system is not configured with crypto support.";
format_error(bad_crypto_key) ->
@@ -817,6 +804,7 @@ abstr_passes(AbstrStatus) ->
?pass(expand_records),
{iff,'dexp',{listing,"expand"}},
+ {iff,'E',?pass(legalize_vars)},
{iff,'E',{src_listing,"E"}},
{iff,'to_exp',{done,"E"}},
@@ -885,10 +873,6 @@ kernel_passes() ->
{iff,dssabsm,{listing,"ssabsm"}},
{unless,no_bsm_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
- {unless,no_fun_opt,{pass,beam_ssa_funs}},
- {iff,dssafuns,{listing,"ssafuns"}},
- {unless,no_fun_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
-
{unless,no_ssa_opt,{pass,beam_ssa_opt}},
{iff,dssaopt,{listing,"ssaopt"}},
{unless,no_ssa_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
@@ -916,8 +900,6 @@ asm_passes() ->
{iff,dblk,{listing,"block"}},
{unless,no_jopt,{pass,beam_jump}},
{iff,djmp,{listing,"jump"}},
- {unless,no_peep_opt,{pass,beam_peep}},
- {iff,dpeep,{listing,"peep"}},
{pass,beam_clean},
{iff,dclean,{listing,"clean"}},
{unless,no_stack_trimming,{pass,beam_trim}},
@@ -1019,8 +1001,13 @@ parse_module(_Code, St) ->
do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
SourceName0 = proplists:get_value(source, Opts, File),
SourceName = case member(deterministic, Opts) of
- true -> filename:basename(SourceName0);
- false -> SourceName0
+ true ->
+ filename:basename(SourceName0);
+ false ->
+ case member(absolute_source, Opts) of
+ true -> paranoid_absname(SourceName0);
+ false -> SourceName0
+ end
end,
StartLocation = case with_columns(Opts) of
true ->
@@ -1028,28 +1015,66 @@ do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
false ->
1
end,
- R = epp:parse_file(File,
- [{includes,[".",Dir|inc_paths(Opts)]},
- {source_name, SourceName},
- {macros,pre_defs(Opts)},
- {default_encoding,DefEncoding},
- {location,StartLocation},
- extra]),
- case R of
- {ok,Forms0,Extra} ->
- Encoding = proplists:get_value(encoding, Extra),
- Forms = case with_columns(Opts ++ compile_options(Forms0)) of
- true ->
- Forms0;
- false ->
- strip_columns(Forms0)
- end,
- {ok,Forms,St#compile{encoding=Encoding}};
- {error,E} ->
- Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
+ case erl_features:keyword_fun(Opts, fun erl_scan:f_reserved_word/1) of
+ {ok, {Features, ResWordFun}} ->
+ R = epp:parse_file(File,
+ [{includes,[".",Dir|inc_paths(Opts)]},
+ {source_name, SourceName},
+ {deterministic, member(deterministic, Opts)},
+ {macros,pre_defs(Opts)},
+ {default_encoding,DefEncoding},
+ {location,StartLocation},
+ {reserved_word_fun, ResWordFun},
+ {features, Features},
+ extra]),
+ case R of
+ %% FIXME Extra should include used features as well
+ {ok,Forms0,Extra} ->
+ Encoding = proplists:get_value(encoding, Extra),
+ %% Get features used in the module, indicated by
+ %% enabling features with
+ %% -compile({feature, .., enable}).
+ UsedFtrs = proplists:get_value(features, Extra),
+ St1 = metadata_add_features(UsedFtrs, St),
+ Forms = case with_columns(Opts ++ compile_options(Forms0)) of
+ true ->
+ Forms0;
+ false ->
+ strip_columns(Forms0)
+ end,
+ {ok,Forms,St1#compile{encoding=Encoding}};
+ {error,E} ->
+ Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end;
+ {error, {Mod, Reason}} ->
+ Es = [{St#compile.ifile,[{none, Mod, Reason}]}],
+ {error, St#compile{errors = St#compile.errors ++ Es}}
end.
+%% The atom to be used in the proplist of the meta chunk indicating
+%% the features used when compiling the module.
+-define(META_USED_FEATURES, enabled_features).
+-define(META_CHUNK_NAME, <<"Meta">>).
+
+metadata_add_features(Ftrs, #compile{extra_chunks = Extra} = St) ->
+ MetaData =
+ case proplists:get_value(?META_CHUNK_NAME, Extra) of
+ undefined ->
+ [];
+ Bin ->
+ erlang:binary_to_term(Bin)
+ end,
+ OldFtrs = proplists:get_value(?META_USED_FEATURES, MetaData, []),
+ NewFtrs = (Ftrs -- OldFtrs) ++ OldFtrs,
+ MetaData1 =
+ proplists:from_map(maps:put(?META_USED_FEATURES, NewFtrs,
+ proplists:to_map(MetaData))),
+ Extra1 = proplists:from_map(maps:put(?META_CHUNK_NAME,
+ erlang:term_to_binary(MetaData1),
+ proplists:to_map(Extra))),
+ St#compile{extra_chunks = Extra1}.
+
with_columns(Opts) ->
case proplists:get_value(error_location, Opts, column) of
column -> true;
@@ -1406,7 +1431,7 @@ makedep_output(Code, #compile{options=Opts,ofile=Ofile}=St) ->
if
is_list(Output) ->
- %% Write the depedencies to a file.
+ %% Write the dependencies to a file.
case file:write_file(Output, Code) of
ok ->
{ok,Code,St};
@@ -1415,7 +1440,7 @@ makedep_output(Code, #compile{options=Opts,ofile=Ofile}=St) ->
{error,St#compile{errors=St#compile.errors++[Err]}}
end;
true ->
- %% Write the depedencies to a device.
+ %% Write the dependencies to a device.
try io:fwrite(Output, "~ts", [Code]) of
ok ->
{ok,Code,St}
@@ -1430,9 +1455,43 @@ expand_records(Code0, #compile{options=Opts}=St) ->
Code = erl_expand_records:module(Code0, Opts),
{ok,Code,St}.
-compile_directives(Forms, #compile{options=Opts0}=St) ->
- Opts = expand_opts(flatten([C || {attribute,_,compile,C} <- Forms])),
- {ok, Forms, St#compile{options=Opts ++ Opts0}}.
+legalize_vars(Code0, St) ->
+ Code = map(fun(F={function,_,_,_,_}) ->
+ erl_pp:legalize_vars(F);
+ (F) ->
+ F
+ end, Code0),
+ {ok,Code,St}.
+
+compile_directives(Forms, #compile{options=Opts0}=St0) ->
+ Opts1 = expand_opts(flatten([C || {attribute,_,compile,C} <- Forms])),
+ Opts = Opts1 ++ Opts0,
+ St1 = St0#compile{options=Opts},
+ case any_obsolete_option(Opts) of
+ {yes,Opt} ->
+ Error = {St1#compile.ifile,[{none,?MODULE,{obsolete_option,Opt}}]},
+ St = St1#compile{errors=[Error|St1#compile.errors]},
+ {error,St};
+ no ->
+ {ok,Forms,St1}
+ end.
+
+any_obsolete_option([Opt|Opts]) ->
+ case is_obsolete(Opt) of
+ true -> {yes,Opt};
+ false -> any_obsolete_option(Opts)
+ end;
+any_obsolete_option([]) -> no.
+
+is_obsolete(r18) -> true;
+is_obsolete(r19) -> true;
+is_obsolete(r20) -> true;
+is_obsolete(r21) -> true;
+is_obsolete(no_bsm3) -> true;
+is_obsolete(no_get_hd_tl) -> true;
+is_obsolete(no_put_tuple2) -> true;
+is_obsolete(no_utf8_atoms) -> true;
+is_obsolete(_) -> false.
core(Forms, #compile{options=Opts}=St) ->
{ok,Core,Ws} = v3_core:module(Forms, Opts),
@@ -2020,14 +2079,12 @@ pre_load() ->
beam_jump,
beam_kernel_to_ssa,
beam_opcodes,
- beam_peep,
beam_ssa,
beam_ssa_bc_size,
beam_ssa_bool,
beam_ssa_bsm,
beam_ssa_codegen,
beam_ssa_dead,
- beam_ssa_funs,
beam_ssa_opt,
beam_ssa_pre_codegen,
beam_ssa_recv,
@@ -2046,6 +2103,7 @@ pre_load() ->
epp,
erl_bifs,
erl_expand_records,
+ erl_features,
erl_lint,
erl_parse,
erl_scan,