1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%% Purpose: Run the Erlang compiler.
21
22-module(compile).
23
24%% High-level interface.
25-export([file/1,file/2,noenv_file/2,format_error/1,iofile/1]).
26-export([forms/1,forms/2,noenv_forms/2]).
27-export([output_generated/1,noenv_output_generated/1]).
28-export([options/0]).
29-export([env_compiler_options/0]).
30
31%% Erlc interface.
32-export([compile/3,compile_beam/3,compile_asm/3,compile_core/3]).
33
34%% Utility functions for compiler passes.
35-export([run_sub_passes/2]).
36
37-export_type([option/0]).
38
39-include("erl_compile.hrl").
40-include("core_parse.hrl").
41
42-import(lists, [member/2,reverse/1,reverse/2,keyfind/3,last/1,
43		map/2,flatmap/2,foreach/2,foldr/3,any/2]).
44
45-define(SUB_PASS_TIMES, compile__sub_pass_times).
46
47%%----------------------------------------------------------------------
48
49-type abstract_code() :: [erl_parse:abstract_form()].
50
51%% Internal representations used for 'from_asm' and 'from_beam' compilation can
52%% also be valid, but have no relevant types defined.
53-type forms() :: abstract_code() | cerl:c_module().
54
55-type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
56
57-type err_info() :: {erl_anno:line() | 'none',
58		     module(), term()}. %% ErrorDescriptor
59-type errors()   :: [{file:filename(), [err_info()]}].
60-type warnings() :: [{file:filename(), [err_info()]}].
61-type mod_ret()  :: {'ok', module()}
62                  | {'ok', module(), cerl:c_module()} %% with option 'to_core'
63                  | {'ok',                            %% with option 'to_pp'
64                     module() | [],                   %% module() if 'to_exp'
65                     abstract_code()}
66                  | {'ok', module(), warnings()}.
67-type bin_ret()  :: {'ok', module(), binary()}
68                  | {'ok', module(), binary(), warnings()}.
69-type err_ret()  :: 'error' | {'error', errors(), warnings()}.
70-type comp_ret() :: mod_ret() | bin_ret() | err_ret().
71
72
73%%----------------------------------------------------------------------
74
75%%
76%%  Exported functions
77%%
78
79
80%% file(FileName)
81%% file(FileName, Options)
82%%  Compile the module in file FileName.
83
84-define(DEFAULT_OPTIONS, [verbose,report_errors,report_warnings]).
85
86-spec file(module() | file:filename()) -> comp_ret().
87
88file(File) -> file(File, ?DEFAULT_OPTIONS).
89
90-spec file(module() | file:filename(), [option()] | option()) -> comp_ret().
91
92file(File, Opts) when is_list(Opts) ->
93    do_compile({file,File}, Opts++env_default_opts());
94file(File, Opt) ->
95    file(File, [Opt|?DEFAULT_OPTIONS]).
96
97-spec forms(abstract_code()) -> comp_ret().
98
99forms(Forms) -> forms(Forms, ?DEFAULT_OPTIONS).
100
101-spec forms(forms(), [option()] | option()) -> comp_ret().
102
103forms(Forms, Opts) when is_list(Opts) ->
104    do_compile({forms,Forms}, [binary|Opts++env_default_opts()]);
105forms(Forms, Opt) when is_atom(Opt) ->
106    forms(Forms, [Opt|?DEFAULT_OPTIONS]).
107
108%% Given a list of compilation options, returns true if compile:file/2
109%% would have generated a Beam file, false otherwise (if only a binary or a
110%% listing file would have been generated).
111
112-spec output_generated([option()]) -> boolean().
113
114output_generated(Opts) ->
115    noenv_output_generated(Opts++env_default_opts()).
116
117%%
118%% Variants of the same function that don't consult ERL_COMPILER_OPTIONS
119%% for default options.
120%%
121
122-spec noenv_file(module() | file:filename(), [option()] | option()) -> comp_ret().
123
124noenv_file(File, Opts) when is_list(Opts) ->
125    do_compile({file,File}, Opts);
126noenv_file(File, Opt) ->
127    noenv_file(File, [Opt|?DEFAULT_OPTIONS]).
128
129-spec noenv_forms(forms(), [option()] | option()) -> comp_ret().
130
131noenv_forms(Forms, Opts) when is_list(Opts) ->
132    do_compile({forms,Forms}, [binary|Opts]);
133noenv_forms(Forms, Opt) when is_atom(Opt) ->
134    noenv_forms(Forms, [Opt|?DEFAULT_OPTIONS]).
135
136-spec noenv_output_generated([option()]) -> boolean().
137
138noenv_output_generated(Opts) ->
139    {_,Passes} = passes(file, expand_opts(Opts)),
140    any(fun ({save_binary,_T,_F}) -> true;
141	    (_Other) -> false
142	end, Passes).
143
144%%
145%% Retrieve ERL_COMPILER_OPTIONS as a list of terms
146%%
147
148-spec env_compiler_options() -> [term()].
149
150env_compiler_options() -> env_default_opts().
151
152
153%%%
154%%% Run sub passes from a compiler pass.
155%%%
156
157-spec run_sub_passes([term()], term()) -> term().
158
159run_sub_passes(Ps, St) ->
160    case get(?SUB_PASS_TIMES) of
161        undefined ->
162            Runner = fun(_Name, Run, S) -> Run(S) end,
163            run_sub_passes_1(Ps, Runner, St);
164        Times when is_list(Times) ->
165            Runner = fun(Name, Run, S0) ->
166                             T1 = erlang:monotonic_time(),
167                             S = Run(S0),
168                             T2 = erlang:monotonic_time(),
169                             put(?SUB_PASS_TIMES,
170                                 [{Name,T2-T1}|get(?SUB_PASS_TIMES)]),
171                             S
172                     end,
173            run_sub_passes_1(Ps, Runner, St)
174    end.
175
176%%
177%%  Local functions
178%%
179
180-define(pass(P), {P,fun P/2}).
181-define(pass(P,T), {P,fun T/1,fun P/2}).
182
183env_default_opts() ->
184    Key = "ERL_COMPILER_OPTIONS",
185    case os:getenv(Key) of
186	false -> [];
187	Str when is_list(Str) ->
188	    case erl_scan:string(Str) of
189		{ok,Tokens,_} ->
190                    Dot = {dot, erl_anno:new(1)},
191		    case erl_parse:parse_term(Tokens ++ [Dot]) of
192			{ok,List} when is_list(List) -> List;
193			{ok,Term} -> [Term];
194			{error,_Reason} ->
195			    io:format("Ignoring bad term in ~s\n", [Key]),
196			    []
197		    end;
198		{error, {_,_,_Reason}, _} ->
199		    io:format("Ignoring bad term in ~s\n", [Key]),
200		    []
201	    end
202    end.
203
204do_compile(Input, Opts0) ->
205    Opts = expand_opts(Opts0),
206    IntFun = fun() -> try
207                          internal(Input, Opts)
208                      catch
209                          error:Reason ->
210                              {error,Reason}
211                      end
212             end,
213    %% Some tools, like Dialyzer, has already spawned workers
214    %% and spawning extra workers actually slow the compilation
215    %% down instead of speeding it up, so we provide a mechanism
216    %% to bypass the compiler process.
217    case lists:member(no_spawn_compiler_process, Opts) of
218        true ->
219            IntFun();
220        false ->
221            {Pid,Ref} =
222                spawn_monitor(fun() ->
223                                      exit(IntFun())
224                              end),
225            receive
226                {'DOWN',Ref,process,Pid,Rep} -> Rep
227            end
228    end.
229
230expand_opts(Opts0) ->
231    %% {debug_info_key,Key} implies debug_info.
232    Opts = case {proplists:get_value(debug_info_key, Opts0),
233		 proplists:get_value(encrypt_debug_info, Opts0),
234		 proplists:get_value(debug_info, Opts0)} of
235	       {undefined,undefined,_} -> Opts0;
236	       {_,_,undefined} -> [debug_info|Opts0];
237	       {_,_,_} -> Opts0
238	   end,
239    %% iff,unless processing is to complex...
240    Opts1 = case proplists:is_defined(makedep_side_effect,Opts) of
241                true -> proplists:delete(makedep,Opts);
242                false -> Opts
243            end,
244    foldr(fun expand_opt/2, [], Opts1).
245
246expand_opt(basic_validation, Os) ->
247    [no_code_generation,to_pp,binary|Os];
248expand_opt(strong_validation, Os) ->
249    [no_code_generation,to_kernel,binary|Os];
250expand_opt(report, Os) ->
251    [report_errors,report_warnings|Os];
252expand_opt(return, Os) ->
253    [return_errors,return_warnings|Os];
254expand_opt(no_bsm3, Os) ->
255    %% The new bsm pass requires bsm3 instructions.
256    [no_bsm3,no_bsm_opt|Os];
257expand_opt(r16, Os) ->
258    expand_opt_before_21(Os);
259expand_opt(r17, Os) ->
260    expand_opt_before_21(Os);
261expand_opt(r18, Os) ->
262    expand_opt_before_21(Os);
263expand_opt(r19, Os) ->
264    expand_opt_before_21(Os);
265expand_opt(r20, Os) ->
266    expand_opt_before_21(Os);
267expand_opt(r21, Os) ->
268    [no_put_tuple2 | expand_opt(no_bsm3, Os)];
269expand_opt({debug_info_key,_}=O, Os) ->
270    [encrypt_debug_info,O|Os];
271expand_opt(no_type_opt=O, Os) ->
272    %% Be sure to keep the no_type_opt option so that it will
273    %% be recorded in the BEAM file, allowing the test suites
274    %% to recompile the file with this option.
275    [O,no_ssa_opt_type_start,
276     no_ssa_opt_type_continue,
277     no_ssa_opt_type_finish | Os];
278expand_opt(O, Os) -> [O|Os].
279
280expand_opt_before_21(Os) ->
281    [no_put_tuple2, no_get_hd_tl, no_ssa_opt_record,
282     no_utf8_atoms | expand_opt(no_bsm3, Os)].
283
284%% format_error(ErrorDescriptor) -> string()
285
286-spec format_error(term()) -> iolist().
287
288format_error(no_native_support) ->
289    "this system is not configured for native-code compilation.";
290format_error(no_crypto) ->
291    "this system is not configured with crypto support.";
292format_error(bad_crypto_key) ->
293    "invalid crypto key.";
294format_error(no_crypto_key) ->
295    "no crypto key supplied.";
296format_error({unimplemented_instruction,Instruction}) ->
297    io_lib:fwrite("native-code compilation failed because of an "
298                  "unimplemented instruction (~s).",
299		  [Instruction]);
300format_error({native, E}) ->
301    io_lib:fwrite("native-code compilation failed with reason: ~tP.",
302		  [E, 25]);
303format_error({native_crash,E,Stk}) ->
304    io_lib:fwrite("native-code compilation crashed with reason: ~tP.\n~tP\n",
305		  [E,25,Stk,25]);
306format_error({open,E}) ->
307    io_lib:format("open error '~ts'", [file:format_error(E)]);
308format_error({epp,E}) ->
309    epp:format_error(E);
310format_error(write_error) ->
311    "error writing file";
312format_error({write_error, Error}) ->
313    io_lib:format("error writing file: ~ts", [file:format_error(Error)]);
314format_error({rename,From,To,Error}) ->
315    io_lib:format("failed to rename ~ts to ~ts: ~ts",
316		  [From,To,file:format_error(Error)]);
317format_error({delete,File,Error}) ->
318    io_lib:format("failed to delete file ~ts: ~ts",
319		  [File,file:format_error(Error)]);
320format_error({delete_temp,File,Error}) ->
321    io_lib:format("failed to delete temporary file ~ts: ~ts",
322		  [File,file:format_error(Error)]);
323format_error({parse_transform,M,R}) ->
324    io_lib:format("error in parse transform '~ts': ~tp", [M, R]);
325format_error({undef_parse_transform,M}) ->
326    io_lib:format("undefined parse transform '~ts'", [M]);
327format_error({core_transform,M,R}) ->
328    io_lib:format("error in core transform '~s': ~tp", [M, R]);
329format_error({crash,Pass,Reason}) ->
330    io_lib:format("internal error in ~p;\ncrash reason: ~ts", [Pass,format_error_reason(Reason)]);
331format_error({bad_return,Pass,Reason}) ->
332    io_lib:format("internal error in ~p;\nbad return value: ~ts", [Pass,format_error_reason(Reason)]);
333format_error({module_name,Mod,Filename}) ->
334    io_lib:format("Module name '~s' does not match file name '~ts'", [Mod,Filename]);
335format_error(reparsing_invalid_unicode) ->
336    "Non-UTF-8 character(s) detected, but no encoding declared. Encode the file in UTF-8 or add \"%% coding: latin-1\" at the beginning of the file. Note: The compiler will remove support for latin-1 encoded source files without the \"%% coding: latin-1\" string at the beginning of the file in Erlang/OTP 24! Retrying with latin-1 encoding.".
337
338format_error_reason({Reason, Stack}) when is_list(Stack) ->
339    StackFun = fun
340	(escript, run,      2) -> true;
341	(escript, start,    1) -> true;
342	(init,    start_it, 1) -> true;
343	(init,    start_em, 1) -> true;
344	(_Mod, _Fun, _Arity)   -> false
345    end,
346    FormatFun = fun (Term, _) -> io_lib:format("~tp", [Term]) end,
347    [io_lib:format("~tp", [Reason]),"\n\n",
348     erl_error:format_stacktrace(1, Stack, StackFun, FormatFun)];
349format_error_reason(Reason) ->
350    io_lib:format("~tp", [Reason]).
351
352-type err_warn_info() :: tuple().
353
354%% The compile state record.
355-record(compile, {filename="" :: file:filename(),
356		  dir=""      :: file:filename(),
357		  base=""     :: file:filename(),
358		  ifile=""    :: file:filename(),
359		  ofile=""    :: file:filename(),
360		  module=[]   :: module() | [],
361		  core_code=[] :: cerl:c_module() | [],
362		  abstract_code=[] :: abstract_code(), %Abstract code for debugger.
363		  options=[]  :: [option()],  %Options for compilation
364		  mod_options=[]  :: [option()], %Options for module_info
365                  encoding=none :: none | epp:source_encoding(),
366		  errors=[]     :: [err_warn_info()],
367		  warnings=[]   :: [err_warn_info()],
368		  extra_chunks=[] :: [{binary(), binary()}]}).
369
370internal({forms,Forms}, Opts0) ->
371    {_,Ps} = passes(forms, Opts0),
372    Source = proplists:get_value(source, Opts0, ""),
373    Opts1 = proplists:delete(source, Opts0),
374    Compile = build_compile(Opts1),
375    internal_comp(Ps, Forms, Source, "", Compile);
376internal({file,File}, Opts) ->
377    {Ext,Ps} = passes(file, Opts),
378    Compile = build_compile(Opts),
379    internal_comp(Ps, none, File, Ext, Compile).
380
381build_compile(Opts0) ->
382    ExtraChunks = proplists:get_value(extra_chunks, Opts0, []),
383    Opts1 = proplists:delete(extra_chunks, Opts0),
384    #compile{options=Opts1,mod_options=Opts1,extra_chunks=ExtraChunks}.
385
386internal_comp(Passes, Code0, File, Suffix, St0) ->
387    Dir = filename:dirname(File),
388    Base = filename:basename(File, Suffix),
389    St1 = St0#compile{filename=File, dir=Dir, base=Base,
390		      ifile=erlfile(Dir, Base, Suffix),
391		      ofile=objfile(Base, St0)},
392    Opts = St1#compile.options,
393    Run0 = case member(time, Opts) of
394	       true  ->
395		   io:format("Compiling ~tp\n", [File]),
396		   fun run_tc/3;
397	       false ->
398                   fun({_Name,Fun}, Code, St) ->
399                           catch Fun(Code, St)
400                   end
401	   end,
402    Run = case keyfind(eprof, 1, Opts) of
403	      {eprof,EprofPass} ->
404		  fun(P, Code, St) ->
405			  run_eprof(P, Code, EprofPass, St)
406		  end;
407	      false ->
408		  Run0
409	  end,
410    case fold_comp(Passes, Run, Code0, St1) of
411	{ok,Code,St2} -> comp_ret_ok(Code, St2);
412	{error,St2} -> comp_ret_err(St2)
413    end.
414
415fold_comp([{delay,Ps0}|Passes], Run, Code, #compile{options=Opts}=St) ->
416    Ps = select_passes(Ps0, Opts) ++ Passes,
417    fold_comp(Ps, Run, Code, St);
418fold_comp([{Name,Test,Pass}|Ps], Run, Code, St) ->
419    case Test(St) of
420	false ->				%Pass is not needed.
421	    fold_comp(Ps, Run, Code, St);
422	true ->					%Run pass in the usual way.
423	    fold_comp([{Name,Pass}|Ps], Run, Code, St)
424    end;
425fold_comp([{Name,Pass}|Ps], Run, Code0, St0) ->
426    case Run({Name,Pass}, Code0, St0) of
427	{ok,Code,St1} ->
428            fold_comp(Ps, Run, Code, St1);
429	{error,_St1}=Error ->
430            Error;
431	{'EXIT',Reason} ->
432	    Es = [{St0#compile.ifile,[{none,?MODULE,{crash,Name,Reason}}]}],
433	    {error,St0#compile{errors=St0#compile.errors ++ Es}};
434	Other ->
435	    Es = [{St0#compile.ifile,[{none,?MODULE,{bad_return,Name,Other}}]}],
436	    {error,St0#compile{errors=St0#compile.errors ++ Es}}
437    end;
438fold_comp([], _Run, Code, St) -> {ok,Code,St}.
439
440run_sub_passes_1([{Name,Run}|Ps], Runner, St0)
441  when is_atom(Name), is_function(Run, 1) ->
442    try Runner(Name, Run, St0) of
443        St ->
444            run_sub_passes_1(Ps, Runner, St)
445    catch
446        C:E:Stk ->
447            io:format("Sub pass ~s\n", [Name]),
448            erlang:raise(C, E, Stk)
449    end;
450run_sub_passes_1([], _, St) -> St.
451
452run_tc({Name,Fun}, Code, St) ->
453    put(?SUB_PASS_TIMES, []),
454    T1 = erlang:monotonic_time(),
455    Val = (catch Fun(Code, St)),
456    T2 = erlang:monotonic_time(),
457    Times = erase(?SUB_PASS_TIMES),
458    Elapsed = erlang:convert_time_unit(T2 - T1, native, microsecond),
459    Mem0 = erts_debug:flat_size(Val)*erlang:system_info(wordsize),
460    Mem = lists:flatten(io_lib:format("~.1f kB", [Mem0/1024])),
461    io:format(" ~-30s: ~10.3f s ~12s\n",
462	      [Name,Elapsed/1000000,Mem]),
463    print_times(Times, Name),
464    Val.
465
466print_times(Times0, Name) ->
467    Fam0 = sofs:relation(Times0),
468    Fam1 = sofs:rel2fam(Fam0),
469    Fam2 = sofs:to_external(Fam1),
470    Fam3 = [{W,lists:sum(Times)} || {W,Times} <- Fam2],
471    Fam = reverse(lists:keysort(2, Fam3)),
472    Total = case lists:sum([T || {_,T} <- Fam]) of
473                0 -> 1;
474                Total0 -> Total0
475            end,
476    case Fam of
477        [] ->
478            ok;
479        [_|_] ->
480            io:format("    %% Sub passes of ~s from slowest to fastest:\n", [Name]),
481            print_times_1(Fam, Total)
482    end.
483
484print_times_1([{Name,T}|Ts], Total) ->
485    Elapsed = erlang:convert_time_unit(T, native, microsecond),
486    io:format("    ~-27s: ~10.3f s ~3w %\n",
487              [Name,Elapsed/1000000,round(100*T/Total)]),
488    print_times_1(Ts, Total);
489print_times_1([], _Total) -> ok.
490
491run_eprof({Name,Fun}, Code, Name, St) ->
492    io:format("~p: Running eprof\n", [Name]),
493    c:appcall(tools, eprof, start_profiling, [[self()]]),
494    Val = (catch Fun(Code, St)),
495    c:appcall(tools, eprof, stop_profiling, []),
496    c:appcall(tools, eprof, analyze, []),
497    Val;
498run_eprof({_,Fun}, Code, _, St) ->
499    catch Fun(Code, St).
500
501comp_ret_ok(Code, #compile{warnings=Warn0,module=Mod,options=Opts}=St) ->
502    case werror(St) of
503        true ->
504            case member(report_warnings, Opts) of
505                true ->
506		    io:format("~p: warnings being treated as errors\n",
507			      [?MODULE]);
508                false ->
509		    ok
510            end,
511            comp_ret_err(St);
512        false ->
513            Warn = messages_per_file(Warn0),
514            report_warnings(St#compile{warnings = Warn}),
515            Ret1 = case member(binary, Opts) andalso
516		       not member(no_code_generation, Opts) of
517                       true -> [Code];
518                       false -> []
519                   end,
520            Ret2 = case member(return_warnings, Opts) of
521                       true -> Ret1 ++ [Warn];
522                       false -> Ret1
523                   end,
524            list_to_tuple([ok,Mod|Ret2])
525    end.
526
527comp_ret_err(#compile{warnings=Warn0,errors=Err0,options=Opts}=St) ->
528    Warn = messages_per_file(Warn0),
529    Err = messages_per_file(Err0),
530    report_errors(St#compile{errors=Err}),
531    report_warnings(St#compile{warnings=Warn}),
532    case member(return_errors, Opts) of
533	true -> {error,Err,Warn};
534	false -> error
535    end.
536
537not_werror(St) -> not werror(St).
538
539werror(#compile{options=Opts,warnings=Ws}) ->
540    Ws =/= [] andalso member(warnings_as_errors, Opts).
541
542%% messages_per_file([{File,[Message]}]) -> [{File,[Message]}]
543messages_per_file(Ms) ->
544    T = lists:sort([{File,M} || {File,Messages} <- Ms, M <- Messages]),
545    PrioMs = [erl_scan, epp, erl_parse],
546    {Prio0, Rest} =
547        lists:mapfoldl(fun(M, A) ->
548                               lists:partition(fun({_,{_,Mod,_}}) -> Mod =:= M;
549                                                  (_) -> false
550                                               end, A)
551                       end, T, PrioMs),
552    Prio = lists:sort(fun({_,{L1,_,_}}, {_,{L2,_,_}}) -> L1 =< L2 end,
553                      lists:append(Prio0)),
554    flatmap(fun mpf/1, [Prio, Rest]).
555
556mpf(Ms) ->
557    [{File,[M || {F,M} <- Ms, F =:= File]} ||
558	File <- lists:usort([F || {F,_} <- Ms])].
559
560%% passes(forms|file, [Option]) -> {Extension,[{Name,PassFun}]}
561%%  Figure out the extension of the input file and which passes
562%%  that need to be run.
563
564passes(Type, Opts) ->
565    {Ext,Passes0} = passes_1(Opts),
566    Passes1 = case Type of
567		  file ->
568                      Passes0;
569		  forms ->
570                      fix_first_pass(Passes0)
571	      end,
572    Passes = select_passes(Passes1, Opts),
573
574    %% If the last pass saves the resulting binary to a file,
575    %% insert a first pass to remove the file (unless the
576    %% source file is a BEAM file).
577    {Ext,case last(Passes) of
578	     {save_binary,_TestFun,_Fun} ->
579		 case Passes of
580		     [{read_beam_file,_}|_] ->
581			 %% The BEAM is both input and output.
582			 %% Don't remove it.
583			 Passes;
584		     _ ->
585			 [?pass(remove_file)|Passes]
586		 end;
587	     _ ->
588		 Passes
589	 end}.
590
591passes_1([Opt|Opts]) ->
592    case pass(Opt) of
593	{_,_}=Res -> Res;
594	none -> passes_1(Opts)
595    end;
596passes_1([]) ->
597    {".erl",[?pass(parse_module)|standard_passes()]}.
598
599pass(from_core) ->
600    {".core",[?pass(parse_core)|core_passes(mandatory_core_lint)]};
601pass(from_asm) ->
602    {".S",[?pass(beam_consult_asm)|asm_passes()]};
603pass(from_beam) ->
604    {".beam",[?pass(read_beam_file)|binary_passes()]};
605pass(_) -> none.
606
607%% For compilation from forms, replace the first pass with a pass
608%% that retrieves the module name. The module name is needed for
609%% proper diagnostics and for compilation to native code.
610
611fix_first_pass([{parse_core,_}|Passes]) ->
612    [?pass(get_module_name_from_core)|Passes];
613fix_first_pass([{beam_consult_asm,_}|Passes]) ->
614    [?pass(get_module_name_from_asm)|Passes];
615fix_first_pass([{read_beam_file,_}|Passes]) ->
616    [?pass(get_module_name_from_beam)|Passes];
617fix_first_pass([_|Passes]) ->
618    %% When compiling from abstract code, the module name
619    %% will be set after running the v3_core pass.
620    Passes.
621
622
623%% select_passes([Command], Opts) -> [{Name,Function}]
624%%  Interpret the lists of commands to return a pure list of passes.
625%%
626%%  Command can be one of:
627%%
628%%    {pass,Mod}	Will be expanded to a call to the external
629%%			function Mod:module(Code, Options).  This
630%%			function must transform the code and return
631%%			{ok,NewCode} or {error,Term}.
632%%			Example: {pass,beam_codegen}
633%%
634%%    {Name,Fun}	Name is an atom giving the name of the pass.
635%%    			Fun is an 'fun' taking one argument: a compile record.
636%%			The fun should return {ok,NewCompileRecord} or
637%%			{error,NewCompileRecord}.
638%%			Note: ?pass(Name) is equvivalent to {Name,fun Name/1}.
639%%			Example: ?pass(parse_module)
640%%
641%%    {Name,Test,Fun}	Like {Name,Fun} above, but the pass will be run
642%%			(and listed by the `time' option) only if Test(St)
643%%			returns true.
644%%
645%%    {src_listing,Ext}	Produces an Erlang source listing with the
646%%			the file extension Ext.  (Ext should not contain
647%%			a period.)  No more passes will be run.
648%%
649%%    {listing,Ext}	Produce an listing of the terms in the internal
650%%			representation.  The extension of the listing
651%%			file will be Ext.  (Ext should not contain
652%%			a period.)   No more passes will be run.
653%%
654%%    done              End compilation at this point.
655%%
656%%    {done,Ext}        End compilation at this point. Produce a listing
657%%                      as with {listing,Ext}, unless 'binary' is
658%%                      specified, in which case the current
659%%                      representation of the code is returned without
660%%                      creating an output file.
661%%
662%%    {iff,Flag,Cmd}	If the given Flag is given in the option list,
663%%			Cmd will be interpreted as a command.
664%%			Otherwise, Cmd will be ignored.
665%%			Example: {iff,dcg,{listing,"codegen}}
666%%
667%%    {unless,Flag,Cmd}	If the given Flag is NOT given in the option list,
668%%			Cmd will be interpreted as a command.
669%%			Otherwise, Cmd will be ignored.
670%%			Example: {unless,no_kernopt,{pass,sys_kernopt}}
671%%
672
673select_passes([{pass,Mod}|Ps], Opts) ->
674    F = fun(Code0, St) ->
675		case catch Mod:module(Code0, St#compile.options) of
676		    {ok,Code} ->
677			{ok,Code,St};
678		    {ok,Code,Ws} ->
679			{ok,Code,St#compile{warnings=St#compile.warnings++Ws}};
680		    {error,Es} ->
681			{error,St#compile{errors=St#compile.errors ++ Es}}
682		end
683	end,
684    [{Mod,F}|select_passes(Ps, Opts)];
685select_passes([{src_listing,Ext}|_], _Opts) ->
686    [{listing,fun (Code, St) -> src_listing(Ext, Code, St) end}];
687select_passes([{listing,Ext}|_], _Opts) ->
688    [{listing,fun (Code, St) -> listing(Ext, Code, St) end}];
689select_passes([done|_], _Opts) ->
690    [];
691select_passes([{done,Ext}|_], Opts) ->
692    select_passes([{unless,binary,{listing,Ext}}], Opts);
693select_passes([{iff,Flag,Pass}|Ps], Opts) ->
694    select_cond(Flag, true, Pass, Ps, Opts);
695select_passes([{unless,Flag,Pass}|Ps], Opts) ->
696    select_cond(Flag, false, Pass, Ps, Opts);
697select_passes([{_,Fun}=P|Ps], Opts) when is_function(Fun) ->
698    [P|select_passes(Ps, Opts)];
699select_passes([{delay,Passes0}|Ps], Opts) when is_list(Passes0) ->
700    %% Delay evaluation of compiler options and which compiler passes to run.
701    %% Since we must know beforehand whether a listing will be produced, we
702    %% will go through the list of passes and evaluate all conditions that
703    %% select a list pass.
704    case select_list_passes(Passes0, Opts) of
705	{done,Passes} ->
706	    [{delay,Passes}];
707	{not_done,Passes} ->
708	    [{delay,Passes}|select_passes(Ps, Opts)]
709    end;
710select_passes([{_,Test,Fun}=P|Ps], Opts) when is_function(Test),
711					      is_function(Fun) ->
712    [P|select_passes(Ps, Opts)];
713select_passes([], _Opts) ->
714    [];
715select_passes([List|Ps], Opts) when is_list(List) ->
716    case select_passes(List, Opts) of
717	[] -> select_passes(Ps, Opts);
718	Nested ->
719	    case last(Nested) of
720		{listing,_Fun} -> Nested;
721		_Other         -> Nested ++ select_passes(Ps, Opts)
722	    end
723    end.
724
725select_cond(Flag, ShouldBe, Pass, Ps, Opts) ->
726    ShouldNotBe = not ShouldBe,
727    case member(Flag, Opts) of
728	ShouldBe    -> select_passes([Pass|Ps], Opts);
729	ShouldNotBe -> select_passes(Ps, Opts)
730    end.
731
732%% select_list_passes([Pass], Opts) -> {done,[Pass]} | {not_done,[Pass]}
733%%  Evaluate all conditions having to do with listings in the list of
734%%  passes.
735
736select_list_passes(Ps, Opts) ->
737    select_list_passes_1(Ps, Opts, []).
738
739select_list_passes_1([{iff,Flag,{listing,_}=Listing}|Ps], Opts, Acc) ->
740    case member(Flag, Opts) of
741	true -> {done,reverse(Acc, [Listing])};
742	false -> select_list_passes_1(Ps, Opts, Acc)
743    end;
744select_list_passes_1([{iff,Flag,{done,Ext}}|Ps], Opts, Acc) ->
745    case member(Flag, Opts) of
746	false ->
747	    select_list_passes_1(Ps, Opts, Acc);
748	true ->
749	    {done,case member(binary, Opts) of
750		      false -> reverse(Acc, [{listing,Ext}]);
751		      true -> reverse(Acc)
752		  end}
753    end;
754select_list_passes_1([{iff=Op,Flag,List0}|Ps], Opts, Acc) when is_list(List0) ->
755    case select_list_passes(List0, Opts) of
756	{done,List} -> {done,reverse(Acc) ++ List};
757	{not_done,List} -> select_list_passes_1(Ps, Opts, [{Op,Flag,List}|Acc])
758    end;
759select_list_passes_1([{unless=Op,Flag,List0}|Ps], Opts, Acc) when is_list(List0) ->
760    case select_list_passes(List0, Opts) of
761	{done,List} -> {done,reverse(Acc) ++ List};
762	{not_done,List} -> select_list_passes_1(Ps, Opts, [{Op,Flag,List}|Acc])
763    end;
764select_list_passes_1([P|Ps], Opts, Acc) ->
765    select_list_passes_1(Ps, Opts, [P|Acc]);
766select_list_passes_1([], _, Acc) ->
767    {not_done,reverse(Acc)}.
768
769%% The standard passes (almost) always run.
770
771standard_passes() ->
772    [?pass(transform_module),
773
774     {iff,makedep_side_effect,?pass(makedep_and_output)},
775     {iff,makedep,[
776	 ?pass(makedep),
777	 {unless,binary,?pass(makedep_output)}
778       ]},
779     {iff,makedep,done},
780
781     {iff,'dpp',{listing,"pp"}},
782     ?pass(lint_module),
783     {iff,'P',{src_listing,"P"}},
784     {iff,'to_pp',{done,"P"}},
785
786     {iff,'dabstr',{listing,"abstr"}},
787     {iff,debug_info,?pass(save_abstract_code)},
788
789     ?pass(expand_records),
790     {iff,'dexp',{listing,"expand"}},
791     {iff,'E',{src_listing,"E"}},
792     {iff,'to_exp',{done,"E"}},
793
794     %% Conversion to Core Erlang.
795     ?pass(core),
796     {iff,'dcore',{listing,"core"}},
797     {iff,'to_core0',{done,"core"}}
798     | core_passes(optional_core_lint)].
799
800core_passes(LintOpt) ->
801    %% Optimization and transforms of Core Erlang code.
802    CoreLint = case LintOpt of
803                   mandatory_core_lint ->
804                       ?pass(core_lint_module);
805                   optional_core_lint ->
806                       {iff,clint0,?pass(core_lint_module)}
807               end,
808    [CoreLint,
809     {delay,
810      [{unless,no_copt,
811       [{core_old_inliner,fun test_old_inliner/1,fun core_old_inliner/2},
812	{iff,doldinline,{listing,"oldinline"}},
813	{unless,no_fold,{pass,sys_core_fold}},
814	{iff,dcorefold,{listing,"corefold"}},
815	{core_inline_module,fun test_core_inliner/1,fun core_inline_module/2},
816	{iff,dinline,{listing,"inline"}},
817        {core_fold_after_inlining,fun test_any_inliner/1,
818         fun core_fold_module_after_inlining/2},
819        {iff,dcopt,{listing,"copt"}},
820        {unless,no_alias,{pass,sys_core_alias}},
821        {iff,dalias,{listing,"core_alias"}},
822	?pass(core_transforms)]},
823       {iff,'to_core',{done,"core"}}]}
824     | kernel_passes()].
825
826kernel_passes() ->
827    %% Optimizations that must be done after all other optimizations.
828    [{pass,sys_core_bsm},
829     {iff,dcbsm,{listing,"core_bsm"}},
830
831     {iff,clint,?pass(core_lint_module)},
832     {iff,core,?pass(save_core_code)},
833
834     %% Kernel Erlang and code generation.
835     ?pass(v3_kernel),
836     {iff,dkern,{listing,"kernel"}},
837     {iff,'to_kernel',{done,"kernel"}},
838     {pass,beam_kernel_to_ssa},
839     {iff,dssa,{listing,"ssa"}},
840     {iff,ssalint,{pass,beam_ssa_lint}},
841     {delay,
842      [{unless,no_share_opt,{pass,beam_ssa_share}},
843       {iff,dssashare,{listing,"ssashare"}},
844       {iff,ssalint,{pass,beam_ssa_lint}},
845       {unless,no_bsm_opt,{pass,beam_ssa_bsm}},
846       {iff,dssabsm,{listing,"ssabsm"}},
847       {iff,ssalint,{pass,beam_ssa_lint}},
848       {unless,no_fun_opt,{pass,beam_ssa_funs}},
849       {iff,dssafuns,{listing,"ssafuns"}},
850       {iff,ssalint,{pass,beam_ssa_lint}},
851       {unless,no_ssa_opt,{pass,beam_ssa_opt}},
852       {iff,dssaopt,{listing,"ssaopt"}},
853       {iff,ssalint,{pass,beam_ssa_lint}},
854       {unless,no_recv_opt,{pass,beam_ssa_recv}},
855       {iff,drecv,{listing,"recv"}}]},
856     {pass,beam_ssa_pre_codegen},
857     {iff,dprecg,{listing,"precodegen"}},
858     {iff,ssalint,{pass,beam_ssa_lint}},
859     {pass,beam_ssa_codegen},
860     {iff,dcg,{listing,"codegen"}},
861     {iff,doldcg,{listing,"codegen"}}
862     | asm_passes()].
863
864asm_passes() ->
865    %% Assembly level optimisations.
866    [{delay,
867      [{pass,beam_a},
868       {iff,da,{listing,"a"}},
869       {unless,no_postopt,
870	[{pass,beam_block},
871	 {iff,dblk,{listing,"block"}},
872	 {unless,no_except,{pass,beam_except}},
873	 {iff,dexcept,{listing,"except"}},
874	 {unless,no_jopt,{pass,beam_jump}},
875	 {iff,djmp,{listing,"jump"}},
876	 {unless,no_peep_opt,{pass,beam_peep}},
877	 {iff,dpeep,{listing,"peep"}},
878	 {pass,beam_clean},
879	 {iff,dclean,{listing,"clean"}},
880	 {unless,no_stack_trimming,{pass,beam_trim}},
881	 {iff,dtrim,{listing,"trim"}},
882	 {pass,beam_flatten}]},
883
884       %% If post optimizations are turned off, we still
885       %% need to do a few clean-ups to code.
886       {iff,no_postopt,[{pass,beam_clean}]},
887
888       {iff,diffable,?pass(diffable)},
889       {pass,beam_z},
890       {iff,diffable,{listing,"S"}},
891       {iff,dz,{listing,"z"}},
892       {iff,dopt,{listing,"optimize"}},
893       {iff,'S',{listing,"S"}},
894       {iff,'to_asm',{done,"S"}}]},
895     {pass,beam_validator},
896     ?pass(beam_asm)
897     | binary_passes()].
898
899binary_passes() ->
900    [{iff,'to_dis',?pass(to_dis)},
901     {native_compile,fun test_native/1,fun native_compile/2},
902     {unless,binary,?pass(save_binary,not_werror)}
903    ].
904
905%%%
906%%% Compiler passes.
907%%%
908
909%% Remove the target file so we don't have an old one if the compilation fail.
910remove_file(Code, St) ->
911    _ = file:delete(St#compile.ofile),
912    {ok,Code,St}.
913
914-record(asm_module, {module,
915		     exports,
916		     labels,
917		     functions=[],
918		     cfun,
919		     code,
920		     attributes=[]}).
921
922preprocess_asm_forms(Forms) ->
923    R = #asm_module{},
924    R1 = collect_asm(Forms, R),
925    {R1#asm_module.module,
926     {R1#asm_module.module,
927      R1#asm_module.exports,
928      R1#asm_module.attributes,
929      R1#asm_module.functions,
930      R1#asm_module.labels}}.
931
932collect_asm([], R) ->
933    case R#asm_module.cfun of
934	undefined ->
935	    R;
936	{A,B,C} ->
937	    R#asm_module{functions=R#asm_module.functions++
938			 [{function,A,B,C,R#asm_module.code}]}
939    end;
940collect_asm([{module,M} | Rest], R) ->
941    collect_asm(Rest, R#asm_module{module=M});
942collect_asm([{exports,M} | Rest], R) ->
943    collect_asm(Rest, R#asm_module{exports=M});
944collect_asm([{labels,M} | Rest], R) ->
945    collect_asm(Rest, R#asm_module{labels=M});
946collect_asm([{function,A,B,C} | Rest], R) ->
947    R1 = case R#asm_module.cfun of
948	     undefined ->
949		 R;
950	     {A0,B0,C0} ->
951		 R#asm_module{functions=R#asm_module.functions++
952			      [{function,A0,B0,C0,R#asm_module.code}]}
953	 end,
954    collect_asm(Rest, R1#asm_module{cfun={A,B,C}, code=[]});
955collect_asm([{attributes, Attr} | Rest], R) ->
956    collect_asm(Rest, R#asm_module{attributes=Attr});
957collect_asm([X | Rest], R) ->
958    collect_asm(Rest, R#asm_module{code=R#asm_module.code++[X]}).
959
960beam_consult_asm(_Code, St) ->
961    case file:consult(St#compile.ifile) of
962	{ok,Forms0} ->
963            Encoding = epp:read_encoding(St#compile.ifile),
964	    {Module,Forms} = preprocess_asm_forms(Forms0),
965	    {ok,Forms,St#compile{module=Module,encoding=Encoding}};
966	{error,E} ->
967	    Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
968	    {error,St#compile{errors=St#compile.errors ++ Es}}
969    end.
970
971get_module_name_from_asm({Mod,_,_,_,_}=Asm, St) ->
972    {ok,Asm,St#compile{module=Mod}};
973get_module_name_from_asm(Asm, St) ->
974    %% Invalid Beam assembly code. Let it crash in a later pass.
975    {ok,Asm,St}.
976
977read_beam_file(_Code, St) ->
978    case file:read_file(St#compile.ifile) of
979	{ok,Beam} ->
980	    Infile = St#compile.ifile,
981	    case no_native_compilation(Infile, St) of
982		true ->
983		    {ok,none,St#compile{module=none}};
984		false ->
985		    Mod0 = filename:rootname(filename:basename(Infile)),
986		    Mod = list_to_atom(Mod0),
987		    {ok,Beam,St#compile{module=Mod,ofile=Infile}}
988	    end;
989	{error,E} ->
990	    Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
991	    {error,St#compile{errors=St#compile.errors ++ Es}}
992    end.
993
994get_module_name_from_beam(Beam, St) ->
995    case beam_lib:info(Beam) of
996        {error,beam_lib,Error} ->
997	    Es = [{"((forms))",[{none,beam_lib,Error}]}],
998            {error,St#compile{errors=St#compile.errors ++ Es}};
999        Info ->
1000            {module,Mod} = keyfind(module, 1, Info),
1001            {ok,Beam,St#compile{module=Mod}}
1002    end.
1003
1004no_native_compilation(BeamFile, #compile{options=Opts0}) ->
1005    case beam_lib:chunks(BeamFile, ["CInf"]) of
1006	{ok,{_,[{"CInf",Term0}]}} ->
1007	    Term = binary_to_term(Term0),
1008
1009	    %% Compiler options in the beam file will override
1010	    %% options passed to the compiler.
1011	    Opts = proplists:get_value(options, Term, []) ++ Opts0,
1012	    member(no_new_funs, Opts) orelse not is_native_enabled(Opts);
1013	_ -> false
1014    end.
1015
1016parse_module(_Code, St0) ->
1017    case do_parse_module(utf8, St0) of
1018	{ok,_,_}=Ret ->
1019	    Ret;
1020	{error,_}=Ret ->
1021	    Ret;
1022	{invalid_unicode,File,Line} ->
1023	    case do_parse_module(latin1, St0) of
1024		{ok,Code,St} ->
1025		    Es = [{File,[{Line,?MODULE,reparsing_invalid_unicode}]}],
1026		    {ok,Code,St#compile{warnings=Es++St#compile.warnings}};
1027		{error,St} ->
1028		    Es = [{File,[{Line,?MODULE,reparsing_invalid_unicode}]}],
1029		    {error,St#compile{errors=Es++St#compile.errors}}
1030	    end
1031    end.
1032
1033do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
1034    SourceName0 = proplists:get_value(source, Opts, File),
1035    SourceName = case member(deterministic, Opts) of
1036                     true -> filename:basename(SourceName0);
1037                     false -> SourceName0
1038                 end,
1039    R = epp:parse_file(File,
1040                       [{includes,[".",Dir|inc_paths(Opts)]},
1041                        {source_name, SourceName},
1042                        {macros,pre_defs(Opts)},
1043                        {default_encoding,DefEncoding},
1044                        extra]),
1045    case R of
1046	{ok,Forms,Extra} ->
1047	    Encoding = proplists:get_value(encoding, Extra),
1048	    case find_invalid_unicode(Forms, File) of
1049		none ->
1050		    {ok,Forms,St#compile{encoding=Encoding}};
1051		{invalid_unicode,_,_}=Ret ->
1052		    case Encoding of
1053			none ->
1054			    Ret;
1055			_ ->
1056			    {ok,Forms,St#compile{encoding=Encoding}}
1057		    end
1058	    end;
1059	{error,E} ->
1060	    Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
1061	    {error,St#compile{errors=St#compile.errors ++ Es}}
1062    end.
1063
1064find_invalid_unicode([H|T], File0) ->
1065    case H of
1066	{attribute,_,file,{File,_}} ->
1067	    find_invalid_unicode(T, File);
1068	{error,{Line,file_io_server,invalid_unicode}} ->
1069	    {invalid_unicode,File0,Line};
1070	_Other ->
1071	    find_invalid_unicode(T, File0)
1072    end;
1073find_invalid_unicode([], _) -> none.
1074
1075parse_core(_Code, St) ->
1076    case file:read_file(St#compile.ifile) of
1077	{ok,Bin} ->
1078	    case core_scan:string(binary_to_list(Bin)) of
1079		{ok,Toks,_} ->
1080		    case core_parse:parse(Toks) of
1081			{ok,Mod} ->
1082			    Name = (Mod#c_module.name)#c_literal.val,
1083			    {ok,Mod,St#compile{module=Name}};
1084			{error,E} ->
1085			    Es = [{St#compile.ifile,[E]}],
1086			    {error,St#compile{errors=St#compile.errors ++ Es}}
1087		    end;
1088		{error,E,_} ->
1089		    Es = [{St#compile.ifile,[E]}],
1090		    {error,St#compile{errors=St#compile.errors ++ Es}}
1091	    end;
1092	{error,E} ->
1093	    Es = [{St#compile.ifile,[{none,compile,{open,E}}]}],
1094	    {error,St#compile{errors=St#compile.errors ++ Es}}
1095    end.
1096
1097get_module_name_from_core(Core, St) ->
1098    try
1099        Mod = cerl:concrete(cerl:module_name(Core)),
1100        {ok,Core,St#compile{module=Mod}}
1101    catch
1102        _:_ ->
1103            %% Invalid Core Erlang code. Let it crash in a later pass.
1104            {ok,Core,St}
1105    end.
1106
1107compile_options([{attribute,_L,compile,C}|Fs]) when is_list(C) ->
1108    C ++ compile_options(Fs);
1109compile_options([{attribute,_L,compile,C}|Fs]) ->
1110    [C|compile_options(Fs)];
1111compile_options([_F|Fs]) -> compile_options(Fs);
1112compile_options([]) -> [].
1113
1114clean_parse_transforms(Fs) ->
1115    clean_parse_transforms_1(Fs, []).
1116
1117clean_parse_transforms_1([{attribute,L,compile,C0}|Fs], Acc) when is_list(C0) ->
1118    C = lists:filter(fun({parse_transform,_}) -> false;
1119			(_) -> true
1120		     end, C0),
1121    clean_parse_transforms_1(Fs, [{attribute,L,compile,C}|Acc]);
1122clean_parse_transforms_1([{attribute,_,compile,{parse_transform,_}}|Fs], Acc) ->
1123    clean_parse_transforms_1(Fs, Acc);
1124clean_parse_transforms_1([F|Fs], Acc) ->
1125    clean_parse_transforms_1(Fs, [F|Acc]);
1126clean_parse_transforms_1([], Acc) -> reverse(Acc).
1127
1128transforms(Os) -> [ M || {parse_transform,M} <- Os ].
1129
1130transform_module(Code0, #compile{options=Opt}=St) ->
1131    %% Extract compile options from code into options field.
1132    case transforms(Opt ++ compile_options(Code0)) of
1133	[] ->
1134            %% No parse transforms.
1135            {ok,Code0,St};
1136	Ts ->
1137	    %% Remove parse_transform attributes from the abstract code to
1138	    %% prevent parse transforms to be run more than once.
1139	    Code = clean_parse_transforms(Code0),
1140	    foldl_transform(Ts, Code, St)
1141    end.
1142
1143foldl_transform([T|Ts], Code0, St) ->
1144    Name = "transform " ++ atom_to_list(T),
1145    case code:ensure_loaded(T) =:= {module,T} andalso
1146        erlang:function_exported(T, parse_transform, 2) of
1147        true ->
1148            Fun = fun(Code, S) ->
1149                          T:parse_transform(Code, S#compile.options)
1150                  end,
1151            Run = case member(time, St#compile.options) of
1152                      true  ->
1153                          fun run_tc/3;
1154                      false ->
1155                          fun({_Name,F}, Code, S) ->
1156                                  catch F(Code, S)
1157                          end
1158                  end,
1159            case Run({Name, Fun}, Code0, St) of
1160                {error,Es,Ws} ->
1161                    {error,St#compile{warnings=St#compile.warnings ++ Ws,
1162                                      errors=St#compile.errors ++ Es}};
1163                {'EXIT',R} ->
1164                    Es = [{St#compile.ifile,[{none,compile,
1165                                              {parse_transform,T,R}}]}],
1166                    {error,St#compile{errors=St#compile.errors ++ Es}};
1167                {warning, Forms, Ws} ->
1168                    foldl_transform(Ts, Forms,
1169                                    St#compile{warnings=St#compile.warnings ++ Ws});
1170                Forms ->
1171                    foldl_transform(Ts, Forms, St)
1172            end;
1173        false ->
1174            Es = [{St#compile.ifile,[{none,compile,
1175                                      {undef_parse_transform,T}}]}],
1176            {error,St#compile{errors=St#compile.errors ++ Es}}
1177    end;
1178foldl_transform([], Code, St) -> {ok,Code,St}.
1179
1180get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts].
1181
1182core_transforms(Code, St) ->
1183    %% The options field holds the complete list of options at this
1184    Ts = get_core_transforms(St#compile.options),
1185    foldl_core_transforms(Ts, Code, St).
1186
1187foldl_core_transforms([T|Ts], Code0, St) ->
1188    Name = "core transform " ++ atom_to_list(T),
1189    Fun = fun(Code, S) -> T:core_transform(Code, S#compile.options) end,
1190    Run = case member(time, St#compile.options) of
1191	      true ->
1192                  fun run_tc/3;
1193	      false ->
1194                  fun({_Name,F}, Code, S) ->
1195                          catch F(Code, S)
1196                  end
1197	  end,
1198    case Run({Name, Fun}, Code0, St) of
1199	{'EXIT',R} ->
1200	    Es = [{St#compile.ifile,[{none,compile,{core_transform,T,R}}]}],
1201	    {error,St#compile{errors=St#compile.errors ++ Es}};
1202	Forms ->
1203	    foldl_core_transforms(Ts, Forms, St)
1204    end;
1205foldl_core_transforms([], Code, St) -> {ok,Code,St}.
1206
1207%%% Fetches the module name from a list of forms. The module attribute must
1208%%% be present.
1209get_module([{attribute,_,module,M} | _]) -> M;
1210get_module([_ | Rest]) ->
1211    get_module(Rest).
1212
1213%%% A #compile state is returned, where St.base has been filled in
1214%%% with the module name from Forms, as a string, in case it wasn't
1215%%% set in St (i.e., it was "").
1216add_default_base(St, Forms) ->
1217    F = St#compile.filename,
1218    case F of
1219	"" ->
1220 	    M = get_module(Forms),
1221	    St#compile{base=atom_to_list(M)};
1222	_ ->
1223	    St
1224    end.
1225
1226lint_module(Code, St) ->
1227    case erl_lint:module(Code, St#compile.ifile, St#compile.options) of
1228	{ok,Ws} ->
1229	    %% Insert name of module as base name, if needed. This is
1230	    %% for compile:forms to work with listing files.
1231	    St1 = add_default_base(St, Code),
1232	    {ok,Code,St1#compile{warnings=St1#compile.warnings ++ Ws}};
1233	{error,Es,Ws} ->
1234	    {error,St#compile{warnings=St#compile.warnings ++ Ws,
1235			      errors=St#compile.errors ++ Es}}
1236    end.
1237
1238core_lint_module(Code, St) ->
1239    case core_lint:module(Code, St#compile.options) of
1240	{ok,Ws} ->
1241	    {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}};
1242	{error,Es,Ws} ->
1243	    {error,St#compile{warnings=St#compile.warnings ++ Ws,
1244			      errors=St#compile.errors ++ Es}}
1245    end.
1246
1247%% makedep + output and continue
1248makedep_and_output(Code0, St) ->
1249    {ok,DepCode,St1} = makedep(Code0,St),
1250    case makedep_output(DepCode, St1) of
1251        {ok,_IgnoreCode,St2} ->
1252            {ok,Code0,St2};
1253        {error,St2} ->
1254            {error,St2}
1255    end.
1256
1257makedep(Code0, #compile{ifile=Ifile,ofile=Ofile,options=Opts}=St) ->
1258
1259    %% Get the target of the Makefile rule.
1260    Target0 =
1261	case proplists:get_value(makedep_target, Opts) of
1262	    undefined ->
1263		%% The target is derived from the output filename: possibly
1264		%% remove the current working directory to obtain a relative
1265		%% path.
1266		shorten_filename(Ofile);
1267	    T ->
1268		%% The caller specified one.
1269		T
1270	end,
1271
1272    %% Quote the target is the called asked for this.
1273    Target1 = case proplists:get_value(makedep_quote_target, Opts) of
1274		  true ->
1275		      %% For now, only "$" is replaced by "$$".
1276		      Fun = fun
1277				($$) -> "$$";
1278				(C)  -> C
1279			    end,
1280		      map(Fun, Target0);
1281		  _ ->
1282		      Target0
1283	      end,
1284    Target = Target1 ++ ":",
1285
1286    %% List the dependencies (includes) for this target.
1287    {MainRule,PhonyRules} = makedep_add_headers(
1288      Ifile,          % The input file name.
1289      Code0,          % The parsed source.
1290      [],             % The list of dependencies already added.
1291      length(Target), % The current line length.
1292      Target,         % The target.
1293      "",             % Phony targets.
1294      Opts),
1295
1296    %% Prepare the content of the Makefile. For instance:
1297    %%   hello.erl: hello.hrl common.hrl
1298    %%
1299    %% Or if phony targets are enabled:
1300    %%   hello.erl: hello.hrl common.hrl
1301    %%
1302    %%   hello.hrl:
1303    %%
1304    %%   common.hrl:
1305    Makefile = case proplists:get_value(makedep_phony, Opts) of
1306		   true -> MainRule ++ PhonyRules;
1307		   _ -> MainRule
1308	       end,
1309    Code = iolist_to_binary([Makefile,"\n"]),
1310    {ok,Code,St}.
1311
1312makedep_add_headers(Ifile, [{attribute,_,file,{File,_}}|Rest],
1313		    Included, LineLen, MainTarget, Phony, Opts) ->
1314    %% The header "File" exists, add it to the dependencies.
1315    {Included1,LineLen1,MainTarget1,Phony1} =
1316	makedep_add_header(Ifile, Included, LineLen, MainTarget, Phony, File),
1317    makedep_add_headers(Ifile, Rest, Included1, LineLen1,
1318			MainTarget1, Phony1, Opts);
1319makedep_add_headers(Ifile, [{error,{_,epp,{include,file,File}}}|Rest],
1320		    Included, LineLen, MainTarget, Phony, Opts) ->
1321    %% The header "File" doesn't exist, do we add it to the dependencies?
1322    case proplists:get_value(makedep_add_missing, Opts) of
1323        true ->
1324            {Included1,LineLen1,MainTarget1,Phony1} =
1325		makedep_add_header(Ifile, Included, LineLen, MainTarget,
1326				   Phony, File),
1327            makedep_add_headers(Ifile, Rest, Included1, LineLen1,
1328				MainTarget1, Phony1, Opts);
1329        _ ->
1330            makedep_add_headers(Ifile, Rest, Included, LineLen,
1331				MainTarget, Phony, Opts)
1332    end;
1333makedep_add_headers(Ifile, [_|Rest], Included, LineLen,
1334		    MainTarget, Phony, Opts) ->
1335    makedep_add_headers(Ifile, Rest, Included,
1336			LineLen, MainTarget, Phony, Opts);
1337makedep_add_headers(_Ifile, [], _Included, _LineLen,
1338		    MainTarget, Phony, _Opts) ->
1339    {MainTarget,Phony}.
1340
1341makedep_add_header(Ifile, Included, LineLen, MainTarget, Phony, File) ->
1342    case member(File, Included) of
1343	true ->
1344	    %% This file was already listed in the dependencies, skip it.
1345            {Included,LineLen,MainTarget,Phony};
1346	false ->
1347            Included1 = [File|Included],
1348
1349	    %% Remove "./" in front of the dependency filename.
1350	    File1 = case File of
1351			"./" ++ File0 -> File0;
1352			_ -> File
1353	    end,
1354
1355	    %% Prepare the phony target name.
1356	    Phony1 = case File of
1357			 Ifile -> Phony;
1358			 _     -> Phony ++ "\n\n" ++ File1 ++ ":"
1359	    end,
1360
1361	    %% Add the file to the dependencies. Lines longer than 76 columns
1362	    %% are splitted.
1363	    if
1364		LineLen + 1 + length(File1) > 76 ->
1365                    LineLen1 = 2 + length(File1),
1366                    MainTarget1 = MainTarget ++ " \\\n  " ++ File1,
1367                    {Included1,LineLen1,MainTarget1,Phony1};
1368		true ->
1369                    LineLen1 = LineLen + 1 + length(File1),
1370                    MainTarget1 = MainTarget ++ " " ++ File1,
1371                    {Included1,LineLen1,MainTarget1,Phony1}
1372	    end
1373    end.
1374
1375makedep_output(Code, #compile{options=Opts,ofile=Ofile}=St) ->
1376    %% Write this Makefile (Code) to the selected output.
1377    %% If no output is specified, the default is to write to a file named after
1378    %% the output file.
1379    Output0 = case proplists:get_value(makedep_output, Opts) of
1380		  undefined ->
1381		      %% Prepare the default filename.
1382		      outfile(filename:basename(Ofile, ".beam"), "Pbeam", Opts);
1383		  O ->
1384		      O
1385	      end,
1386
1387    %% If the caller specified an io_device(), there's nothing to do. If he
1388    %% specified a filename, we must create it. Furthermore, this created file
1389    %% must be closed before returning.
1390    Ret = case Output0 of
1391	      _ when is_list(Output0) ->
1392		  case file:delete(Output0) of
1393		      Ret2 when Ret2 =:= ok; Ret2 =:= {error,enoent} ->
1394			  case file:open(Output0, [write]) of
1395			      {ok,IODev} ->
1396				  {ok,IODev,true};
1397			      {error,Reason2} ->
1398				  {error,open,Reason2}
1399			  end;
1400		      {error,Reason1} ->
1401			  {error,delete,Reason1}
1402		  end;
1403	      _ ->
1404		  {ok,Output0,false}
1405	  end,
1406
1407    case Ret of
1408	{ok,Output1,CloseOutput} ->
1409	    try
1410		%% Write the Makefile.
1411		io:fwrite(Output1, "~ts", [Code]),
1412		%% Close the file if relevant.
1413		if
1414		    CloseOutput -> ok = file:close(Output1);
1415		    true -> ok
1416		end,
1417		{ok,Code,St}
1418	    catch
1419		error:_ ->
1420		    %% Couldn't write to output Makefile.
1421		    Err = {St#compile.ifile,[{none,?MODULE,write_error}]},
1422		    {error,St#compile{errors=St#compile.errors++[Err]}}
1423	    end;
1424	{error,open,Reason} ->
1425	    %% Couldn't open output Makefile.
1426	    Err = {St#compile.ifile,[{none,?MODULE,{open,Reason}}]},
1427	    {error,St#compile{errors=St#compile.errors++[Err]}};
1428	{error,delete,Reason} ->
1429	    %% Couldn't open output Makefile.
1430	    Err = {St#compile.ifile,[{none,?MODULE,{delete,Output0,Reason}}]},
1431	    {error,St#compile{errors=St#compile.errors++[Err]}}
1432    end.
1433
1434expand_records(Code0, #compile{options=Opts}=St) ->
1435    Code = erl_expand_records:module(Code0, Opts),
1436    {ok,Code,St}.
1437
1438core(Forms, #compile{options=Opts0}=St) ->
1439    Opts1 = lists:flatten([C || {attribute,_,compile,C} <- Forms] ++ Opts0),
1440    Opts = expand_opts(Opts1),
1441    {ok,Core,Ws} = v3_core:module(Forms, Opts),
1442    Mod = cerl:concrete(cerl:module_name(Core)),
1443    {ok,Core,St#compile{module=Mod,options=Opts,
1444                        warnings=St#compile.warnings++Ws}}.
1445
1446core_fold_module_after_inlining(Code0, #compile{options=Opts}=St) ->
1447    %% Inlining may produce code that generates spurious warnings.
1448    %% Ignore all warnings.
1449    {ok,Code,_Ws} = sys_core_fold:module(Code0, Opts),
1450    {ok,Code,St}.
1451
1452v3_kernel(Code0, #compile{options=Opts,warnings=Ws0}=St) ->
1453    {ok,Code,Ws} = v3_kernel:module(Code0, Opts),
1454    case Ws =:= [] orelse test_core_inliner(St) of
1455	false ->
1456	    {ok,Code,St#compile{warnings=Ws0++Ws}};
1457	true ->
1458	    %% cerl_inline may produce code that generates spurious
1459	    %% warnings. Ignore any such warnings.
1460	    {ok,Code,St}
1461    end.
1462
1463test_old_inliner(#compile{options=Opts}) ->
1464    %% The point of this test is to avoid loading the old inliner
1465    %% if we know that it will not be used.
1466    any(fun({inline,_}) -> true;
1467	   (_) -> false
1468	end, Opts).
1469
1470test_core_inliner(#compile{options=Opts}) ->
1471    case any(fun(no_inline) -> true;
1472		(_) -> false
1473	     end, Opts) of
1474	true -> false;
1475	false ->
1476	    any(fun(inline) -> true;
1477		   (_) -> false
1478		end, Opts)
1479    end.
1480
1481test_any_inliner(St) ->
1482    test_old_inliner(St) orelse test_core_inliner(St).
1483
1484core_old_inliner(Code0, #compile{options=Opts}=St) ->
1485    {ok,Code} = sys_core_inline:module(Code0, Opts),
1486    {ok,Code,St}.
1487
1488core_inline_module(Code0, #compile{options=Opts}=St) ->
1489    Code = cerl_inline:core_transform(Code0, Opts),
1490    {ok,Code,St}.
1491
1492save_abstract_code(Code, St) ->
1493    {ok,Code,St#compile{abstract_code=erl_parse:anno_to_term(Code)}}.
1494
1495debug_info(#compile{module=Module,mod_options=Opts0,ofile=OFile,abstract_code=Abst}) ->
1496    AbstOpts = cleanup_compile_options(Opts0),
1497    Opts1 = proplists:delete(debug_info, Opts0),
1498    {Backend,Metadata,Opts2} =
1499	case proplists:get_value(debug_info, Opts0, false) of
1500	    {OptBackend,OptMetadata} when is_atom(OptBackend) -> {OptBackend,OptMetadata,Opts1};
1501	    false -> {erl_abstract_code,{none,AbstOpts},Opts1};
1502	    true -> {erl_abstract_code,{Abst,AbstOpts},[debug_info | Opts1]}
1503	end,
1504    DebugInfo = erlang:term_to_binary({debug_info_v1,Backend,Metadata}, [compressed]),
1505
1506    case member(encrypt_debug_info, Opts2) of
1507	true ->
1508	    case lists:keytake(debug_info_key, 1, Opts2) of
1509		{value,{_, Key},Opts3} ->
1510		    encrypt_debug_info(DebugInfo, Key, [{debug_info_key,'********'} | Opts3]);
1511		false ->
1512		    Mode = proplists:get_value(crypto_mode, Opts2, des3_cbc),
1513		    case beam_lib:get_crypto_key({debug_info, Mode, Module, OFile}) of
1514			error ->
1515			    {error, [{none,?MODULE,no_crypto_key}]};
1516			Key ->
1517			    encrypt_debug_info(DebugInfo, {Mode, Key}, Opts2)
1518		    end
1519	    end;
1520	false ->
1521	    {ok,DebugInfo,Opts2}
1522    end.
1523
1524encrypt_debug_info(DebugInfo, Key, Opts) ->
1525    try
1526	RealKey = generate_key(Key),
1527	case start_crypto() of
1528	    ok -> {ok,encrypt(RealKey, DebugInfo),Opts};
1529	    {error,_}=E -> E
1530	end
1531    catch
1532	error:_ ->
1533	    {error,[{none,?MODULE,bad_crypto_key}]}
1534    end.
1535
1536cleanup_compile_options(Opts) ->
1537    IsDeterministic = lists:member(deterministic, Opts),
1538    lists:filter(fun(Opt) ->
1539                         keep_compile_option(Opt, IsDeterministic)
1540                 end, Opts).
1541
1542%% Include paths and current directory don't affect compilation, but they might
1543%% be helpful so we include them unless we're doing a deterministic build.
1544keep_compile_option({i, _}, Deterministic) ->
1545    not Deterministic;
1546keep_compile_option({cwd, _}, Deterministic) ->
1547    not Deterministic;
1548%% We are storing abstract, not asm or core.
1549keep_compile_option(from_asm, _Deterministic) ->
1550    false;
1551keep_compile_option(from_core, _Deterministic) ->
1552    false;
1553%% Parse transform and macros have already been applied.
1554keep_compile_option({parse_transform, _}, _Deterministic) ->
1555    false;
1556keep_compile_option({d, _, _}, _Deterministic) ->
1557    false;
1558%% Do not affect compilation result on future calls.
1559keep_compile_option(Option, _Deterministic) ->
1560    effects_code_generation(Option).
1561
1562start_crypto() ->
1563    try crypto:start() of
1564	{error,{already_started,crypto}} -> ok;
1565	ok -> ok
1566    catch
1567	error:_ ->
1568	    {error,[{none,?MODULE,no_crypto}]}
1569    end.
1570
1571generate_key({Type,String}) when is_atom(Type), is_list(String) ->
1572    beam_lib:make_crypto_key(Type, String);
1573generate_key(String) when is_list(String) ->
1574    generate_key({des3_cbc,String}).
1575
1576encrypt({des3_cbc=Type,Key,IVec,BlockSize}, Bin0) ->
1577    Bin1 = case byte_size(Bin0) rem BlockSize of
1578	       0 -> Bin0;
1579	       N -> list_to_binary([Bin0,crypto:strong_rand_bytes(BlockSize-N)])
1580	   end,
1581    Bin = crypto:block_encrypt(Type, Key, IVec, Bin1),
1582    TypeString = atom_to_list(Type),
1583    list_to_binary([0,length(TypeString),TypeString,Bin]).
1584
1585save_core_code(Code, St) ->
1586    {ok,Code,St#compile{core_code=cerl:from_records(Code)}}.
1587
1588beam_asm(Code0, #compile{ifile=File,extra_chunks=ExtraChunks,options=CompilerOpts}=St) ->
1589    case debug_info(St) of
1590	{ok,DebugInfo,Opts0} ->
1591	    Opts1 = [O || O <- Opts0, effects_code_generation(O)],
1592	    Chunks = [{<<"Dbgi">>, DebugInfo} | ExtraChunks],
1593	    CompileInfo = compile_info(File, CompilerOpts, Opts1),
1594	    {ok,Code} = beam_asm:module(Code0, Chunks, CompileInfo, CompilerOpts),
1595	    {ok,Code,St#compile{abstract_code=[]}};
1596	{error,Es} ->
1597	    {error,St#compile{errors=St#compile.errors ++ [{File,Es}]}}
1598    end.
1599
1600compile_info(File, CompilerOpts, Opts) ->
1601    IsSlim = member(slim, CompilerOpts),
1602    IsDeterministic = member(deterministic, CompilerOpts),
1603    Info0 = proplists:get_value(compile_info, Opts, []),
1604    Info1 =
1605	case paranoid_absname(File) of
1606	    [_|_] = Source when not IsSlim, not IsDeterministic ->
1607		[{source,Source} | Info0];
1608	    _ ->
1609		Info0
1610	end,
1611    Info2 =
1612	case IsDeterministic of
1613	    false -> [{options,proplists:delete(compile_info, Opts)} | Info1];
1614	    true -> Info1
1615	end,
1616    Info2.
1617
1618paranoid_absname(""=File) ->
1619    File;
1620paranoid_absname(File) ->
1621    case file:get_cwd() of
1622	{ok,Cwd} ->
1623	    filename:absname(File, Cwd);
1624	_ ->
1625	    File
1626    end.
1627
1628test_native(#compile{options=Opts}) ->
1629    %% This test is done late, in case some other option has turned off native.
1630    %% 'native' given on the command line can be overridden by
1631    %% 'no_native' in the module itself.
1632    is_native_enabled(Opts).
1633
1634is_native_enabled([native|_]) -> true;
1635is_native_enabled([no_native|_]) -> false;
1636is_native_enabled([_|Opts]) -> is_native_enabled(Opts);
1637is_native_enabled([]) -> false.
1638
1639native_compile(none, St) -> {ok,none,St};
1640native_compile(Code, St) ->
1641    case erlang:system_info(hipe_architecture) of
1642	undefined ->
1643	    Ws = [{St#compile.ifile,[{none,compile,no_native_support}]}],
1644	    {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}};
1645	_ ->
1646	    native_compile_1(Code, St)
1647    end.
1648
1649native_compile_1(Code, St) ->
1650    Opts0 = St#compile.options,
1651    IgnoreErrors = member(ignore_native_errors, Opts0),
1652    Opts = case keyfind(hipe, 1, Opts0) of
1653	       {hipe,L} when is_list(L) -> L;
1654	       {hipe,X} -> [X];
1655	       _ -> []
1656	   end,
1657    try hipe:compile(St#compile.module,
1658		     St#compile.core_code,
1659		     Code,
1660		     Opts) of
1661	{ok,{_Type,Bin}=T} when is_binary(Bin) ->
1662	    {ok,embed_native_code(Code, T),St};
1663	{error,R} ->
1664	    case IgnoreErrors of
1665		true ->
1666		    Ws = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
1667		    {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}};
1668		false ->
1669		    Es = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
1670		    {error,St#compile{errors=St#compile.errors ++ Es}}
1671	    end
1672    catch
1673        exit:{unimplemented_instruction,_}=Unimplemented ->
1674            Ws = [{St#compile.ifile,
1675                   [{none,?MODULE,Unimplemented}]}],
1676            {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}};
1677	Class:R:Stack ->
1678	    case IgnoreErrors of
1679		true ->
1680		    Ws = [{St#compile.ifile,
1681			   [{none,?MODULE,{native_crash,R,Stack}}]}],
1682		    {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}};
1683		false ->
1684		    erlang:raise(Class, R, Stack)
1685	    end
1686    end.
1687
1688embed_native_code(Code, {Architecture,NativeCode}) ->
1689    {ok, _, Chunks0} = beam_lib:all_chunks(Code),
1690    ChunkName = hipe_unified_loader:chunk_name(Architecture),
1691    Chunks1 = lists:keydelete(ChunkName, 1, Chunks0),
1692    Chunks = Chunks1 ++ [{ChunkName,NativeCode}],
1693    {ok,BeamPlusNative} = beam_lib:build_module(Chunks),
1694    BeamPlusNative.
1695
1696%% effects_code_generation(Option) -> true|false.
1697%%  Determine whether the option could have any effect on the
1698%%  generated code in the BEAM file (as opposed to how
1699%%  errors will be reported).
1700
1701effects_code_generation(Option) ->
1702    case Option of
1703	beam -> false;
1704	report_warnings -> false;
1705	report_errors -> false;
1706	return_errors-> false;
1707	return_warnings-> false;
1708	warnings_as_errors -> false;
1709	binary -> false;
1710	verbose -> false;
1711	{cwd,_} -> false;
1712	{outdir, _} -> false;
1713	_ -> true
1714    end.
1715
1716save_binary(none, St) -> {ok,none,St};
1717save_binary(Code, #compile{module=Mod,ofile=Outfile,options=Opts}=St) ->
1718    %% Test that the module name and output file name match.
1719    case member(no_error_module_mismatch, Opts) of
1720	true ->
1721	    save_binary_1(Code, St);
1722	false ->
1723	    Base = filename:rootname(filename:basename(Outfile)),
1724	    case atom_to_list(Mod) of
1725		Base ->
1726		    save_binary_1(Code, St);
1727		_ ->
1728		    Es = [{St#compile.ofile,
1729			   [{none,?MODULE,{module_name,Mod,Base}}]}],
1730		    {error,St#compile{errors=St#compile.errors ++ Es}}
1731	    end
1732    end.
1733
1734save_binary_1(Code, St) ->
1735    Ofile = St#compile.ofile,
1736    Tfile = tmpfile(Ofile),		%Temp working file
1737    case write_binary(Tfile, Code, St) of
1738	ok ->
1739	    case file:rename(Tfile, Ofile) of
1740		ok ->
1741		    {ok,none,St};
1742		{error,RenameError} ->
1743		    Es0 = [{Ofile,[{none,?MODULE,{rename,Tfile,Ofile,
1744						  RenameError}}]}],
1745		    Es = case file:delete(Tfile) of
1746			     ok -> Es0;
1747			     {error,DeleteError} ->
1748				 Es0 ++
1749				     [{Ofile,
1750				       [{none,?MODULE,{delete_temp,Tfile,
1751						       DeleteError}}]}]
1752			 end,
1753		    {error,St#compile{errors=St#compile.errors ++ Es}}
1754	    end;
1755	{error,Error} ->
1756	    Es = [{Tfile,[{none,compile,{write_error,Error}}]}],
1757	    {error,St#compile{errors=St#compile.errors ++ Es}}
1758    end.
1759
1760write_binary(Name, Bin, St) ->
1761    Opts = case member(compressed, St#compile.options) of
1762	       true -> [compressed];
1763	       false -> []
1764	   end,
1765    case file:write_file(Name, Bin, Opts) of
1766	ok -> ok;
1767	{error,_}=Error -> Error
1768    end.
1769
1770%% report_errors(State) -> ok
1771%% report_warnings(State) -> ok
1772
1773report_errors(#compile{options=Opts,errors=Errors}) ->
1774    case member(report_errors, Opts) of
1775	true ->
1776	    foreach(fun ({{F,_L},Eds}) -> list_errors(F, Eds);
1777			({F,Eds}) -> list_errors(F, Eds) end,
1778		    Errors);
1779	false -> ok
1780    end.
1781
1782report_warnings(#compile{options=Opts,warnings=Ws0}) ->
1783    Werror = member(warnings_as_errors, Opts),
1784    P = case Werror of
1785	    true -> "";
1786	    false -> "Warning: "
1787	end,
1788    ReportWerror = Werror andalso member(report_errors, Opts),
1789    case member(report_warnings, Opts) orelse ReportWerror of
1790	true ->
1791	    Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, P, Eds);
1792			     ({F,Eds}) -> format_message(F, P, Eds) end,
1793			  Ws0),
1794	    Ws = lists:sort(Ws1),
1795	    foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws);
1796	false -> ok
1797    end.
1798
1799format_message(F, P, [{none,Mod,E}|Es]) ->
1800    M = {none,io_lib:format("~ts: ~s~ts\n", [F,P,Mod:format_error(E)])},
1801    [M|format_message(F, P, Es)];
1802format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) ->
1803    M = {{F,Loc},io_lib:format("~ts:~w:~w ~s~ts\n",
1804                                [F,Line,Column,P,Mod:format_error(E)])},
1805    [M|format_message(F, P, Es)];
1806format_message(F, P, [{Line,Mod,E}|Es]) ->
1807    M = {{F,{Line,0}},io_lib:format("~ts:~w: ~s~ts\n",
1808                                [F,Line,P,Mod:format_error(E)])},
1809    [M|format_message(F, P, Es)];
1810format_message(F, P, [{Mod,E}|Es]) ->
1811    %% Not documented and not expected to be used any more, but
1812    %% keep a while just in case.
1813    M = {none,io_lib:format("~ts: ~s~ts\n", [F,P,Mod:format_error(E)])},
1814    [M|format_message(F, P, Es)];
1815format_message(_, _, []) -> [].
1816
1817%% list_errors(File, ErrorDescriptors) -> ok
1818
1819list_errors(F, [{none,Mod,E}|Es]) ->
1820    io:fwrite("~ts: ~ts\n", [F,Mod:format_error(E)]),
1821    list_errors(F, Es);
1822list_errors(F, [{{Line,Column},Mod,E}|Es]) ->
1823    io:fwrite("~ts:~w:~w: ~ts\n", [F,Line,Column,Mod:format_error(E)]),
1824    list_errors(F, Es);
1825list_errors(F, [{Line,Mod,E}|Es]) ->
1826    io:fwrite("~ts:~w: ~ts\n", [F,Line,Mod:format_error(E)]),
1827    list_errors(F, Es);
1828list_errors(F, [{Mod,E}|Es]) ->
1829    %% Not documented and not expected to be used any more, but
1830    %% keep a while just in case.
1831    io:fwrite("~ts: ~ts\n", [F,Mod:format_error(E)]),
1832    list_errors(F, Es);
1833list_errors(_F, []) -> ok.
1834
1835%% erlfile(Dir, Base) -> ErlFile
1836%% outfile(Base, Extension, Options) -> OutputFile
1837%% objfile(Base, Target, Options) -> ObjFile
1838%% tmpfile(ObjFile) -> TmpFile
1839%%  Work out the correct input and output file names.
1840
1841-spec iofile(atom() | file:filename_all()) ->
1842                    {file:name_all(),file:name_all()}.
1843
1844iofile(File) when is_atom(File) ->
1845    iofile(atom_to_list(File));
1846iofile(File) ->
1847    {filename:dirname(File), filename:basename(File, ".erl")}.
1848
1849erlfile(".", Base, Suffix) ->
1850    Base ++ Suffix;
1851erlfile(Dir, Base, Suffix) ->
1852    filename:join(Dir, Base ++ Suffix).
1853
1854outfile(Base, Ext, Opts) when is_atom(Ext) ->
1855    outfile(Base, atom_to_list(Ext), Opts);
1856outfile(Base, Ext, Opts) ->
1857    Obase = case keyfind(outdir, 1, Opts) of
1858		{outdir, Odir} -> filename:join(Odir, Base);
1859		_Other -> Base			% Not found or bad format
1860	    end,
1861    Obase ++ "." ++ Ext.
1862
1863objfile(Base, St) ->
1864    outfile(Base, "beam", St#compile.options).
1865
1866tmpfile(Ofile) ->
1867    reverse([$#|tl(reverse(Ofile))]).
1868
1869%% pre_defs(Options)
1870%% inc_paths(Options)
1871%%  Extract the predefined macros and include paths from the option list.
1872
1873pre_defs([{d,M,V}|Opts]) ->
1874    [{M,V}|pre_defs(Opts)];
1875pre_defs([{d,M}|Opts]) ->
1876    [M|pre_defs(Opts)];
1877pre_defs([_|Opts]) ->
1878    pre_defs(Opts);
1879pre_defs([]) -> [].
1880
1881inc_paths(Opts) ->
1882    [ P || {i,P} <- Opts, is_list(P) ].
1883
1884src_listing(Ext, Code, St) ->
1885    listing(fun (Lf, {_Mod,_Exp,Fs}) -> do_src_listing(Lf, Fs);
1886		(Lf, Fs) -> do_src_listing(Lf, Fs) end,
1887	    Ext, Code, St).
1888
1889do_src_listing(Lf, Fs) ->
1890    Opts = [lists:keyfind(encoding, 1, io:getopts(Lf))],
1891    foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F, Opts),"\n"]) end,
1892	    Fs).
1893
1894listing(Ext, Code, St0) ->
1895    St = St0#compile{encoding = none},
1896    listing(fun(Lf, Fs) -> beam_listing:module(Lf, Fs) end, Ext, Code, St).
1897
1898listing(LFun, Ext, Code, St) ->
1899    Lfile = outfile(St#compile.base, Ext, St#compile.options),
1900    case file:open(Lfile, [write,delayed_write]) of
1901	{ok,Lf} ->
1902            Code = restore_expanded_types(Ext, Code),
1903            output_encoding(Lf, St),
1904	    LFun(Lf, Code),
1905	    ok = file:close(Lf),
1906	    {ok,Code,St};
1907	{error,Error} ->
1908	    Es = [{Lfile,[{none,compile,{write_error,Error}}]}],
1909	    {error,St#compile{errors=St#compile.errors ++ Es}}
1910    end.
1911
1912to_dis(Code, #compile{module=Module,ofile=Outfile}=St) ->
1913    Loaded = code:is_loaded(Module),
1914    Sticky = code:is_sticky(Module),
1915    _ = [code:unstick_mod(Module) || Sticky],
1916
1917    {module,Module} = code:load_binary(Module, "", Code),
1918    DestDir = filename:dirname(Outfile),
1919    DisFile = filename:join(DestDir, atom_to_list(Module) ++ ".dis"),
1920    ok = erts_debug:dis_to_file(Module, DisFile),
1921
1922    %% Restore loaded module
1923    _ = [{module, Module} = code:load_file(Module) || Loaded =/= false],
1924    [code:stick_mod(Module) || Sticky],
1925    {ok,Code,St}.
1926
1927output_encoding(F, #compile{encoding = none}) ->
1928    ok = io:setopts(F, [{encoding, epp:default_encoding()}]);
1929output_encoding(F, #compile{encoding = Encoding}) ->
1930    ok = io:setopts(F, [{encoding, Encoding}]),
1931    ok = io:fwrite(F, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
1932
1933restore_expanded_types("E", {M,I,Fs0}) ->
1934    Fs = restore_expand_module(Fs0),
1935    {M,I,Fs};
1936restore_expanded_types(_Ext, Code) -> Code.
1937
1938restore_expand_module([{attribute,Line,type,[Type]}|Fs]) ->
1939    [{attribute,Line,type,Type}|restore_expand_module(Fs)];
1940restore_expand_module([{attribute,Line,opaque,[Type]}|Fs]) ->
1941    [{attribute,Line,opaque,Type}|restore_expand_module(Fs)];
1942restore_expand_module([{attribute,Line,spec,[Arg]}|Fs]) ->
1943    [{attribute,Line,spec,Arg}|restore_expand_module(Fs)];
1944restore_expand_module([{attribute,Line,callback,[Arg]}|Fs]) ->
1945    [{attribute,Line,callback,Arg}|restore_expand_module(Fs)];
1946restore_expand_module([{attribute,Line,record,[R]}|Fs]) ->
1947    [{attribute,Line,record,R}|restore_expand_module(Fs)];
1948restore_expand_module([F|Fs]) ->
1949    [F|restore_expand_module(Fs)];
1950restore_expand_module([]) -> [].
1951
1952%%%
1953%%% Transform the BEAM code to make it more friendly for
1954%%% diffing: using function names instead of labels for
1955%%% local calls and number labels relative to each function.
1956%%%
1957
1958diffable(Code0, St) ->
1959    {Mod,Exp,Attr,Fs0,NumLabels} = Code0,
1960    EntryLabels0 = [{Entry,{Name,Arity}} ||
1961                       {function,Name,Arity,Entry,_} <- Fs0],
1962    EntryLabels = maps:from_list(EntryLabels0),
1963    Fs = [diffable_fix_function(F, EntryLabels) || F <- Fs0],
1964    Code = {Mod,Exp,Attr,Fs,NumLabels},
1965    {ok,Code,St}.
1966
1967diffable_fix_function({function,Name,Arity,Entry0,Is0}, LabelMap0) ->
1968    Entry = maps:get(Entry0, LabelMap0),
1969    {Is1,LabelMap} = diffable_label_map(Is0, 1, LabelMap0, []),
1970    Fb = fun(Old) -> error({no_fb,Old}) end,
1971    Is = beam_utils:replace_labels(Is1, [], LabelMap, Fb),
1972    {function,Name,Arity,Entry,Is}.
1973
1974diffable_label_map([{label,Old}|Is], New, Map, Acc) ->
1975    case Map of
1976        #{Old:=NewLabel} ->
1977            diffable_label_map(Is, New, Map, [{label,NewLabel}|Acc]);
1978        #{} ->
1979            diffable_label_map(Is, New+1, Map#{Old=>New}, [{label,New}|Acc])
1980    end;
1981diffable_label_map([I|Is], New, Map, Acc) ->
1982    diffable_label_map(Is, New, Map, [I|Acc]);
1983diffable_label_map([], _New, Map, Acc) ->
1984    {Acc,Map}.
1985
1986-spec options() -> 'ok'.
1987
1988options() ->
1989    help(standard_passes()).
1990
1991help([{delay,Ps}|T]) ->
1992    help(Ps),
1993    help(T);
1994help([{iff,Flag,{src_listing,Ext}}|T]) ->
1995    io:fwrite("~p - Generate .~s source listing file\n", [Flag,Ext]),
1996    help(T);
1997help([{iff,Flag,{listing,Ext}}|T]) ->
1998    io:fwrite("~p - Generate .~s file\n", [Flag,Ext]),
1999    help(T);
2000help([{iff,Flag,{Name,Fun}}|T]) when is_function(Fun) ->
2001    io:fwrite("~p - Run ~s\n", [Flag,Name]),
2002    help(T);
2003help([{iff,_Flag,Action}|T]) ->
2004    help(Action),
2005    help(T);
2006help([{unless,Flag,{pass,Pass}}|T]) ->
2007    io:fwrite("~p - Skip the ~s pass\n", [Flag,Pass]),
2008    help(T);
2009help([{unless,no_postopt=Flag,List}|T]) when is_list(List) ->
2010    %% Hard-coded knowledge here.
2011    io:fwrite("~p - Skip all post optimisation\n", [Flag]),
2012    help(List),
2013    help(T);
2014help([{unless,_Flag,Action}|T]) ->
2015    help(Action),
2016    help(T);
2017help([_|T]) ->
2018    help(T);
2019help(_) ->
2020    ok.
2021
2022
2023%% compile(AbsFileName, Outfilename, Options)
2024%%   Compile entry point for erl_compile.
2025
2026-spec compile(file:filename(), _, #options{}) -> 'ok' | 'error'.
2027
2028compile(File0, _OutFile, Options) ->
2029    pre_load(),
2030    File = shorten_filename(File0),
2031    case file(File, make_erl_options(Options)) of
2032	{ok,_Mod} -> ok;
2033	Other -> Other
2034    end.
2035
2036-spec compile_beam(file:filename(), _, #options{}) -> 'ok' | 'error'.
2037
2038compile_beam(File0, _OutFile, Opts) ->
2039    File = shorten_filename(File0),
2040    case file(File, [from_beam|make_erl_options(Opts)]) of
2041	{ok,_Mod} -> ok;
2042	Other -> Other
2043    end.
2044
2045-spec compile_asm(file:filename(), _, #options{}) -> 'ok' | 'error'.
2046
2047compile_asm(File0, _OutFile, Opts) ->
2048    File = shorten_filename(File0),
2049    case file(File, [from_asm|make_erl_options(Opts)]) of
2050	{ok,_Mod} -> ok;
2051	Other -> Other
2052    end.
2053
2054-spec compile_core(file:filename(), _, #options{}) -> 'ok' | 'error'.
2055
2056compile_core(File0, _OutFile, Opts) ->
2057    File = shorten_filename(File0),
2058    case file(File, [from_core|make_erl_options(Opts)]) of
2059	{ok,_Mod} -> ok;
2060	Other -> Other
2061    end.
2062
2063shorten_filename(Name0) ->
2064    {ok,Cwd} = file:get_cwd(),
2065    case lists:prefix(Cwd, Name0) of
2066	false -> Name0;
2067	true ->
2068	    case lists:nthtail(length(Cwd), Name0) of
2069		"/"++N -> N;
2070		N -> N
2071	    end
2072    end.
2073
2074%% Converts generic compiler options to specific options.
2075
2076make_erl_options(Opts) ->
2077    #options{includes=Includes,
2078	     defines=Defines,
2079	     outdir=Outdir,
2080	     warning=Warning,
2081	     verbose=Verbose,
2082	     specific=Specific,
2083	     output_type=OutputType,
2084	     cwd=Cwd} = Opts,
2085    Options = [verbose || Verbose] ++
2086	[report_warnings || Warning =/= 0] ++
2087	map(fun ({Name,Value}) ->
2088		    {d,Name,Value};
2089		(Name) ->
2090		    {d,Name}
2091	    end, Defines) ++
2092	case OutputType of
2093	    undefined -> [];
2094	    jam -> [jam];
2095	    beam -> [beam];
2096	    native -> [native]
2097	end,
2098    Options ++ [report_errors, {cwd, Cwd}, {outdir, Outdir}|
2099	        [{i, Dir} || Dir <- Includes]] ++ Specific.
2100
2101pre_load() ->
2102    L = [beam_a,
2103	 beam_asm,
2104	 beam_block,
2105	 beam_clean,
2106	 beam_dict,
2107	 beam_except,
2108	 beam_flatten,
2109	 beam_jump,
2110	 beam_kernel_to_ssa,
2111	 beam_opcodes,
2112	 beam_peep,
2113	 beam_ssa,
2114	 beam_ssa_bsm,
2115	 beam_ssa_codegen,
2116	 beam_ssa_dead,
2117         beam_ssa_funs,
2118	 beam_ssa_opt,
2119	 beam_ssa_pre_codegen,
2120	 beam_ssa_recv,
2121	 beam_ssa_share,
2122	 beam_ssa_type,
2123	 beam_trim,
2124	 beam_utils,
2125	 beam_validator,
2126	 beam_z,
2127	 cerl,
2128	 cerl_clauses,
2129	 cerl_sets,
2130	 cerl_trees,
2131	 core_lib,
2132	 epp,
2133	 erl_bifs,
2134	 erl_expand_records,
2135	 erl_lint,
2136	 erl_parse,
2137	 erl_scan,
2138	 sys_core_alias,
2139	 sys_core_bsm,
2140	 sys_core_fold,
2141	 v3_core,
2142	 v3_kernel],
2143    _ = code:ensure_modules_loaded(L),
2144    ok.
2145