PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/compiler/src/compile.erl

https://github.com/erlang/otp
Erlang | 2085 lines | 1616 code | 236 blank | 233 comment | 20 complexity | 9eaeae65ab92d7d9a706fef21a89c01a MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, Unlicense, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  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. -module(compile).
  22. %% High-level interface.
  23. -export([file/1,file/2,noenv_file/2,format_error/1]).
  24. -export([forms/1,forms/2,noenv_forms/2]).
  25. -export([output_generated/1,noenv_output_generated/1]).
  26. -export([options/0]).
  27. -export([env_compiler_options/0]).
  28. %% Erlc interface.
  29. -export([compile/3,compile_asm/3,compile_core/3,compile_abstr/3]).
  30. %% Utility functions for compiler passes.
  31. -export([run_sub_passes/2]).
  32. -export_type([option/0]).
  33. -export_type([forms/0]).
  34. -include("erl_compile.hrl").
  35. -include("core_parse.hrl").
  36. -import(lists, [member/2,reverse/1,reverse/2,keyfind/3,last/1,
  37. map/2,flatmap/2,flatten/1,foreach/2,foldr/3,any/2]).
  38. -define(SUB_PASS_TIMES, compile__sub_pass_times).
  39. %%----------------------------------------------------------------------
  40. -type abstract_code() :: [erl_parse:abstract_form()].
  41. -type forms() :: abstract_code() | cerl:c_module() | beam_disasm:asm_form().
  42. -type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
  43. -type error_description() :: erl_lint:error_description().
  44. -type error_info() :: erl_lint:error_info().
  45. -type errors() :: [{file:filename(), [error_info()]}].
  46. -type warnings() :: [{file:filename(), [error_info()]}].
  47. -type mod_ret() :: {'ok', module()}
  48. | {'ok', module(), cerl:c_module()} %% with option 'to_core'
  49. | {'ok', %% with option 'to_pp'
  50. module() | [], %% module() if 'to_exp'
  51. abstract_code()}
  52. | {'ok', module(), warnings()}.
  53. -type bin_ret() :: {'ok', module(), binary()}
  54. | {'ok', module(), binary(), warnings()}.
  55. -type err_ret() :: 'error' | {'error', errors(), warnings()}.
  56. -type comp_ret() :: mod_ret() | bin_ret() | err_ret().
  57. %%----------------------------------------------------------------------
  58. %%
  59. %% Exported functions
  60. %%
  61. %% file(FileName)
  62. %% file(FileName, Options)
  63. %% Compile the module in file FileName.
  64. -define(DEFAULT_OPTIONS, [verbose,report_errors,report_warnings]).
  65. -spec file(module() | file:filename()) -> comp_ret().
  66. file(File) -> file(File, ?DEFAULT_OPTIONS).
  67. -spec file(module() | file:filename(), [option()] | option()) -> comp_ret().
  68. file(File, Opts) when is_list(Opts) ->
  69. do_compile({file,File}, Opts++env_default_opts());
  70. file(File, Opt) ->
  71. file(File, [Opt|?DEFAULT_OPTIONS]).
  72. -spec forms(abstract_code()) -> comp_ret().
  73. forms(Forms) -> forms(Forms, ?DEFAULT_OPTIONS).
  74. -spec forms(forms(), [option()] | option()) -> comp_ret().
  75. forms(Forms, Opts) when is_list(Opts) ->
  76. do_compile({forms,Forms}, [binary|Opts++env_default_opts()]);
  77. forms(Forms, Opt) when is_atom(Opt) ->
  78. forms(Forms, [Opt|?DEFAULT_OPTIONS]).
  79. %% Given a list of compilation options, returns true if compile:file/2
  80. %% would have generated a Beam file, false otherwise (if only a binary or a
  81. %% listing file would have been generated).
  82. -spec output_generated([option()]) -> boolean().
  83. output_generated(Opts) ->
  84. noenv_output_generated(Opts++env_default_opts()).
  85. %%
  86. %% Variants of the same function that don't consult ERL_COMPILER_OPTIONS
  87. %% for default options.
  88. %%
  89. -spec noenv_file(module() | file:filename(), [option()] | option()) -> comp_ret().
  90. noenv_file(File, Opts) when is_list(Opts) ->
  91. do_compile({file,File}, Opts);
  92. noenv_file(File, Opt) ->
  93. noenv_file(File, [Opt|?DEFAULT_OPTIONS]).
  94. -spec noenv_forms(forms(), [option()] | option()) -> comp_ret().
  95. noenv_forms(Forms, Opts) when is_list(Opts) ->
  96. do_compile({forms,Forms}, [binary|Opts]);
  97. noenv_forms(Forms, Opt) when is_atom(Opt) ->
  98. noenv_forms(Forms, [Opt|?DEFAULT_OPTIONS]).
  99. -spec noenv_output_generated([option()]) -> boolean().
  100. noenv_output_generated(Opts) ->
  101. {_,Passes} = passes(file, expand_opts(Opts)),
  102. any(fun ({save_binary,_T,_F}) -> true;
  103. (_Other) -> false
  104. end, Passes).
  105. %%
  106. %% Retrieve ERL_COMPILER_OPTIONS as a list of terms
  107. %%
  108. -spec env_compiler_options() -> [term()].
  109. env_compiler_options() -> env_default_opts().
  110. %%%
  111. %%% Run sub passes from a compiler pass.
  112. %%%
  113. -spec run_sub_passes([term()], term()) -> term().
  114. run_sub_passes(Ps, St) ->
  115. case get(?SUB_PASS_TIMES) of
  116. undefined ->
  117. Runner = fun(_Name, Run, S) -> Run(S) end,
  118. run_sub_passes_1(Ps, Runner, St);
  119. Times when is_list(Times) ->
  120. Runner = fun(Name, Run, S0) ->
  121. T1 = erlang:monotonic_time(),
  122. S = Run(S0),
  123. T2 = erlang:monotonic_time(),
  124. put(?SUB_PASS_TIMES,
  125. [{Name,T2-T1}|get(?SUB_PASS_TIMES)]),
  126. S
  127. end,
  128. run_sub_passes_1(Ps, Runner, St)
  129. end.
  130. %%
  131. %% Local functions
  132. %%
  133. -define(pass(P), {P,fun P/2}).
  134. -define(pass(P,T), {P,fun T/1,fun P/2}).
  135. env_default_opts() ->
  136. Key = "ERL_COMPILER_OPTIONS",
  137. case os:getenv(Key) of
  138. false -> [];
  139. Str when is_list(Str) ->
  140. case erl_scan:string(Str) of
  141. {ok,Tokens,_} ->
  142. Dot = {dot, erl_anno:new(1)},
  143. case erl_parse:parse_term(Tokens ++ [Dot]) of
  144. {ok,List} when is_list(List) -> List;
  145. {ok,Term} -> [Term];
  146. {error,_Reason} ->
  147. io:format("Ignoring bad term in ~s\n", [Key]),
  148. []
  149. end;
  150. {error, {_,_,_Reason}, _} ->
  151. io:format("Ignoring bad term in ~s\n", [Key]),
  152. []
  153. end
  154. end.
  155. do_compile(Input, Opts0) ->
  156. Opts = expand_opts(Opts0),
  157. IntFun = internal_fun(Input, Opts),
  158. %% Some tools, like Dialyzer, has already spawned workers
  159. %% and spawning extra workers actually slow the compilation
  160. %% down instead of speeding it up, so we provide a mechanism
  161. %% to bypass the compiler process.
  162. case lists:member(no_spawn_compiler_process, Opts) of
  163. true ->
  164. IntFun();
  165. false ->
  166. {Pid,Ref} =
  167. spawn_monitor(fun() ->
  168. exit(IntFun())
  169. end),
  170. receive
  171. {'DOWN',Ref,process,Pid,Rep} -> Rep
  172. end
  173. end.
  174. internal_fun(Input, Opts) ->
  175. fun() ->
  176. try
  177. internal(Input, Opts)
  178. catch
  179. Class:Reason:Stk ->
  180. internal_error(Class, Reason, Stk)
  181. end
  182. end.
  183. internal_error(Class, Reason, Stk) ->
  184. Error = ["\n*** Internal compiler error ***\n",
  185. format_error_reason(Class, Reason, Stk),
  186. "\n"],
  187. io:put_chars(Error),
  188. error.
  189. expand_opts(Opts0) ->
  190. %% {debug_info_key,Key} implies debug_info.
  191. Opts = case {proplists:get_value(debug_info_key, Opts0),
  192. proplists:get_value(encrypt_debug_info, Opts0),
  193. proplists:get_value(debug_info, Opts0)} of
  194. {undefined,undefined,_} -> Opts0;
  195. {_,_,undefined} -> [debug_info|Opts0];
  196. {_,_,_} -> Opts0
  197. end,
  198. %% iff,unless processing is to complex...
  199. Opts1 = case proplists:is_defined(makedep_side_effect,Opts) of
  200. true -> proplists:delete(makedep,Opts);
  201. false -> Opts
  202. end,
  203. foldr(fun expand_opt/2, [], Opts1).
  204. expand_opt(basic_validation, Os) ->
  205. [no_code_generation,to_pp,binary|Os];
  206. expand_opt(strong_validation, Os) ->
  207. [no_code_generation,to_kernel,binary|Os];
  208. expand_opt(report, Os) ->
  209. [report_errors,report_warnings|Os];
  210. expand_opt(return, Os) ->
  211. [return_errors,return_warnings|Os];
  212. expand_opt(no_bsm3, Os) ->
  213. %% The new bsm pass requires bsm3 instructions.
  214. [no_bsm3,no_bsm_opt|expand_opt(no_bsm4, Os)];
  215. expand_opt(no_bsm4, Os) ->
  216. %% bsm4 instructions are only used when type optimization has determined
  217. %% that a match instruction won't fail.
  218. expand_opt(no_type_opt, Os);
  219. expand_opt(r22, Os) ->
  220. expand_opt(r23, [no_bs_create_bin, no_shared_fun_wrappers,
  221. no_swap | expand_opt(no_bsm4, Os)]);
  222. expand_opt(r23, Os) ->
  223. expand_opt(no_make_fun3, [no_bs_create_bin, no_ssa_opt_float,
  224. no_recv_opt, no_init_yregs |
  225. expand_opt(r24, Os)]);
  226. expand_opt(r24, Os) ->
  227. expand_opt(no_type_opt, [no_bs_create_bin | Os]);
  228. expand_opt(no_make_fun3, Os) ->
  229. [no_make_fun3, no_fun_opt | Os];
  230. expand_opt({debug_info_key,_}=O, Os) ->
  231. [encrypt_debug_info,O|Os];
  232. expand_opt(no_type_opt=O, Os) ->
  233. %% Be sure to keep the no_type_opt option so that it will
  234. %% be recorded in the BEAM file, allowing the test suites
  235. %% to recompile the file with this option.
  236. [O,no_ssa_opt_type_start,
  237. no_ssa_opt_type_continue,
  238. no_ssa_opt_type_finish | Os];
  239. expand_opt(no_module_opt=O, Os) ->
  240. [O,no_recv_opt | Os];
  241. expand_opt(O, Os) -> [O|Os].
  242. -spec format_error(error_description()) -> iolist().
  243. format_error({obsolete_option,Ver}) ->
  244. io_lib:fwrite("the ~p option is no longer supported", [Ver]);
  245. format_error(no_crypto) ->
  246. "this system is not configured with crypto support.";
  247. format_error(bad_crypto_key) ->
  248. "invalid crypto key.";
  249. format_error(no_crypto_key) ->
  250. "no crypto key supplied.";
  251. format_error({open,E}) ->
  252. io_lib:format("open error '~ts'", [file:format_error(E)]);
  253. format_error({epp,E}) ->
  254. epp:format_error(E);
  255. format_error(write_error) ->
  256. "error writing file";
  257. format_error({write_error, Error}) ->
  258. io_lib:format("error writing file: ~ts", [file:format_error(Error)]);
  259. format_error({rename,From,To,Error}) ->
  260. io_lib:format("failed to rename ~ts to ~ts: ~ts",
  261. [From,To,file:format_error(Error)]);
  262. format_error({parse_transform,M,{C,R,Stk}}) ->
  263. E = format_error_reason(C, R, Stk),
  264. io_lib:format("error in parse transform '~ts':\n~ts", [M, E]);
  265. format_error({undef_parse_transform,M}) ->
  266. io_lib:format("undefined parse transform '~ts'", [M]);
  267. format_error({core_transform,M,{C,R,Stk}}) ->
  268. E = format_error_reason(C, R, Stk),
  269. io_lib:format("error in core transform '~s':\n~ts", [M, E]);
  270. format_error({crash,Pass,Reason,Stk}) ->
  271. io_lib:format("internal error in pass ~p:\n~ts", [Pass,format_error_reason({Reason, Stk})]);
  272. format_error({bad_return,Pass,Reason}) ->
  273. io_lib:format("internal error in pass ~p: bad return value:\n~tP", [Pass,Reason,20]);
  274. format_error({module_name,Mod,Filename}) ->
  275. io_lib:format("Module name '~s' does not match file name '~ts'", [Mod,Filename]).
  276. format_error_reason({Reason, Stack}) when is_list(Stack) ->
  277. format_error_reason(error, Reason, Stack).
  278. format_error_reason(Class, Reason, Stack) ->
  279. StackFun = fun
  280. (escript, run, 2) -> true;
  281. (escript, start, 1) -> true;
  282. (init, start_it, 1) -> true;
  283. (init, start_em, 1) -> true;
  284. (_Mod, _Fun, _Arity) -> false
  285. end,
  286. FormatFun = fun (Term, _) -> io_lib:format("~tp", [Term]) end,
  287. Opts = #{stack_trim_fun => StackFun,
  288. format_fun => FormatFun},
  289. erl_error:format_exception(Class, Reason, Stack, Opts).
  290. %% The compile state record.
  291. -record(compile, {filename="" :: file:filename(),
  292. dir="" :: file:filename(),
  293. base="" :: file:filename(),
  294. ifile="" :: file:filename(),
  295. ofile="" :: file:filename(),
  296. module=[] :: module() | [],
  297. abstract_code=[] :: abstract_code(), %Abstract code for debugger.
  298. options=[] :: [option()], %Options for compilation
  299. mod_options=[] :: [option()], %Options for module_info
  300. encoding=none :: none | epp:source_encoding(),
  301. errors=[] :: errors(),
  302. warnings=[] :: warnings(),
  303. extra_chunks=[] :: [{binary(), binary()}]}).
  304. internal({forms,Forms}, Opts0) ->
  305. {_,Ps} = passes(forms, Opts0),
  306. Source = proplists:get_value(source, Opts0, ""),
  307. Opts1 = proplists:delete(source, Opts0),
  308. Compile = build_compile(Opts1),
  309. NewForms = case with_columns(Opts0) of
  310. true ->
  311. Forms;
  312. false ->
  313. strip_columns(Forms)
  314. end,
  315. internal_comp(Ps, NewForms, Source, "", Compile);
  316. internal({file,File}, Opts) ->
  317. {Ext,Ps} = passes(file, Opts),
  318. Compile = build_compile(Opts),
  319. internal_comp(Ps, none, File, Ext, Compile).
  320. build_compile(Opts0) ->
  321. ExtraChunks = proplists:get_value(extra_chunks, Opts0, []),
  322. Opts1 = proplists:delete(extra_chunks, Opts0),
  323. #compile{options=Opts1,mod_options=Opts1,extra_chunks=ExtraChunks}.
  324. internal_comp(Passes, Code0, File, Suffix, St0) ->
  325. Dir = filename:dirname(File),
  326. Base = filename:basename(File, Suffix),
  327. St1 = St0#compile{filename=File, dir=Dir, base=Base,
  328. ifile=erlfile(Dir, Base, Suffix),
  329. ofile=objfile(Base, St0)},
  330. Run = runner(File, St1),
  331. case fold_comp(Passes, Run, Code0, St1) of
  332. {ok,Code,St2} -> comp_ret_ok(Code, St2);
  333. {error,St2} -> comp_ret_err(St2)
  334. end.
  335. fold_comp([{delay,Ps0}|Passes], Run, Code, #compile{options=Opts}=St) ->
  336. Ps = select_passes(Ps0, Opts) ++ Passes,
  337. fold_comp(Ps, Run, Code, St);
  338. fold_comp([{Name,Test,Pass}|Ps], Run, Code, St) ->
  339. case Test(St) of
  340. false -> %Pass is not needed.
  341. fold_comp(Ps, Run, Code, St);
  342. true -> %Run pass in the usual way.
  343. fold_comp([{Name,Pass}|Ps], Run, Code, St)
  344. end;
  345. fold_comp([{Name,Pass}|Ps], Run, Code0, St0) ->
  346. try Run({Name,Pass}, Code0, St0) of
  347. {ok,Code,St1} ->
  348. fold_comp(Ps, Run, Code, St1);
  349. {error,_St1}=Error ->
  350. Error
  351. catch
  352. error:Reason:Stk ->
  353. Es = [{St0#compile.ifile,[{none,?MODULE,{crash,Name,Reason,Stk}}]}],
  354. {error,St0#compile{errors=St0#compile.errors ++ Es}}
  355. end;
  356. fold_comp([], _Run, Code, St) -> {ok,Code,St}.
  357. run_sub_passes_1([{Name,Run}|Ps], Runner, St0)
  358. when is_atom(Name), is_function(Run, 1) ->
  359. try Runner(Name, Run, St0) of
  360. St ->
  361. run_sub_passes_1(Ps, Runner, St)
  362. catch
  363. C:E:Stk ->
  364. io:format("Sub pass ~s\n", [Name]),
  365. erlang:raise(C, E, Stk)
  366. end;
  367. run_sub_passes_1([], _, St) -> St.
  368. runner(File, #compile{options=Opts}) ->
  369. Run0 = fun({_Name,Fun}, Code, St) ->
  370. Fun(Code, St)
  371. end,
  372. Run1 = case member(time, Opts) of
  373. true ->
  374. case File of
  375. none -> ok;
  376. _ -> io:format("Compiling ~ts\n", [File])
  377. end,
  378. fun run_tc/3;
  379. false ->
  380. Run0
  381. end,
  382. case keyfind(eprof, 1, Opts) of
  383. {eprof,EprofPass} ->
  384. fun(P, Code, St) ->
  385. run_eprof(P, Code, EprofPass, St)
  386. end;
  387. false ->
  388. Run1
  389. end.
  390. run_tc({Name,Fun}, Code, St) ->
  391. OldTimes = put(?SUB_PASS_TIMES, []),
  392. T1 = erlang:monotonic_time(),
  393. Val = Fun(Code, St),
  394. T2 = erlang:monotonic_time(),
  395. Times = get(?SUB_PASS_TIMES),
  396. case OldTimes of
  397. undefined -> erase(?SUB_PASS_TIMES);
  398. _ -> put(?SUB_PASS_TIMES, OldTimes)
  399. end,
  400. Elapsed = erlang:convert_time_unit(T2 - T1, native, microsecond),
  401. Mem0 = erts_debug:flat_size(Val)*erlang:system_info(wordsize),
  402. Mem = lists:flatten(io_lib:format("~.1f kB", [Mem0/1024])),
  403. io:format(" ~-30s: ~10.3f s ~12s\n",
  404. [Name,Elapsed/1000000,Mem]),
  405. print_times(Times, Name),
  406. Val.
  407. print_times(Times0, Name) ->
  408. Fam0 = rel2fam(Times0),
  409. Fam1 = [{W,lists:sum(Times)} || {W,Times} <- Fam0],
  410. Fam = reverse(lists:keysort(2, Fam1)),
  411. Total = case lists:sum([T || {_,T} <- Fam]) of
  412. 0 -> 1;
  413. Total0 -> Total0
  414. end,
  415. case Fam of
  416. [] ->
  417. ok;
  418. [_|_] ->
  419. io:format(" %% Sub passes of ~s from slowest to fastest:\n", [Name]),
  420. print_times_1(Fam, Total)
  421. end.
  422. print_times_1([{Name,T}|Ts], Total) ->
  423. Elapsed = erlang:convert_time_unit(T, native, microsecond),
  424. io:format(" ~-27s: ~10.3f s ~3w %\n",
  425. [Name,Elapsed/1000000,round(100*T/Total)]),
  426. print_times_1(Ts, Total);
  427. print_times_1([], _Total) -> ok.
  428. run_eprof({Name,Fun}, Code, Name, St) ->
  429. io:format("~p: Running eprof\n", [Name]),
  430. c:appcall(tools, eprof, start_profiling, [[self()]]),
  431. try
  432. Fun(Code, St)
  433. after
  434. c:appcall(tools, eprof, stop_profiling, []),
  435. c:appcall(tools, eprof, analyze, [])
  436. end;
  437. run_eprof({_,Fun}, Code, _, St) ->
  438. Fun(Code, St).
  439. comp_ret_ok(Code, #compile{warnings=Warn0,module=Mod,options=Opts}=St) ->
  440. Warn1 = filter_warnings(Warn0, Opts),
  441. case werror(St) of
  442. true ->
  443. case member(report_warnings, Opts) of
  444. true ->
  445. io:format("~p: warnings being treated as errors\n",
  446. [?MODULE]);
  447. false ->
  448. ok
  449. end,
  450. comp_ret_err(St);
  451. false ->
  452. Warn = messages_per_file(Warn1),
  453. report_warnings(St#compile{warnings = Warn}),
  454. Ret1 = case member(binary, Opts) andalso
  455. not member(no_code_generation, Opts) of
  456. true -> [Code];
  457. false -> []
  458. end,
  459. Ret2 = case member(return_warnings, Opts) of
  460. true -> Ret1 ++ [Warn];
  461. false -> Ret1
  462. end,
  463. list_to_tuple([ok,Mod|Ret2])
  464. end.
  465. comp_ret_err(#compile{warnings=Warn0,errors=Err0,options=Opts}=St) ->
  466. Warn = messages_per_file(Warn0),
  467. Err = messages_per_file(Err0),
  468. report_errors(St#compile{errors=Err}),
  469. report_warnings(St#compile{warnings=Warn}),
  470. case member(return_errors, Opts) of
  471. true -> {error,Err,Warn};
  472. false -> error
  473. end.
  474. not_werror(St) -> not werror(St).
  475. werror(#compile{options=Opts,warnings=Ws}) ->
  476. Ws =/= [] andalso member(warnings_as_errors, Opts).
  477. %% messages_per_file([{File,[Message]}]) -> [{File,[Message]}]
  478. messages_per_file(Ms) ->
  479. T = lists:sort([{File,M} || {File,Messages} <- Ms, M <- Messages]),
  480. PrioMs = [erl_scan, epp, erl_parse],
  481. {Prio0, Rest} =
  482. lists:mapfoldl(fun(M, A) ->
  483. lists:partition(fun({_,{_,Mod,_}}) -> Mod =:= M;
  484. (_) -> false
  485. end, A)
  486. end, T, PrioMs),
  487. Prio = lists:sort(fun({_,{L1,_,_}}, {_,{L2,_,_}}) -> L1 =< L2 end,
  488. lists:append(Prio0)),
  489. flatmap(fun mpf/1, [Prio, Rest]).
  490. mpf(Ms) ->
  491. [{File,[M || {F,M} <- Ms, F =:= File]} ||
  492. File <- lists:usort([F || {F,_} <- Ms])].
  493. %% passes(forms|file, [Option]) -> {Extension,[{Name,PassFun}]}
  494. %% Figure out the extension of the input file and which passes
  495. %% that need to be run.
  496. passes(Type, Opts) ->
  497. {Ext,Passes0} = passes_1(Opts),
  498. Passes1 = case Type of
  499. file ->
  500. Passes0;
  501. forms ->
  502. fix_first_pass(Passes0)
  503. end,
  504. Passes2 = select_passes(Passes1, Opts),
  505. %% If the last pass saves the resulting binary to a file,
  506. %% insert a first pass to remove the file.
  507. Passes = case last(Passes2) of
  508. {save_binary, _TestFun, _Fun} ->
  509. [?pass(remove_file) | Passes2];
  510. _ ->
  511. Passes2
  512. end,
  513. {Ext, Passes}.
  514. passes_1([Opt|Opts]) ->
  515. case pass(Opt) of
  516. {_,_}=Res -> Res;
  517. none -> passes_1(Opts)
  518. end;
  519. passes_1([]) ->
  520. {".erl",[?pass(parse_module)|standard_passes()]}.
  521. pass(from_abstr) ->
  522. {".abstr", [?pass(consult_abstr) | abstr_passes(non_verified_abstr)]};
  523. pass(from_core) ->
  524. {".core",[?pass(parse_core)|core_passes(non_verified_core)]};
  525. pass(from_asm) ->
  526. {".S",[?pass(beam_consult_asm)|asm_passes()]};
  527. pass(_) -> none.
  528. %% For compilation from forms, replace the first pass with a pass
  529. %% that retrieves the module name. The module name is needed for
  530. %% proper diagnostics.
  531. fix_first_pass([{consult_abstr, _} | Passes]) ->
  532. %% Simply remove this pass. The module name will be set after
  533. %% running the v3_core pass.
  534. Passes;
  535. fix_first_pass([{parse_core,_}|Passes]) ->
  536. [?pass(get_module_name_from_core)|Passes];
  537. fix_first_pass([{beam_consult_asm,_}|Passes]) ->
  538. [?pass(get_module_name_from_asm)|Passes];
  539. fix_first_pass([_|Passes]) ->
  540. %% When compiling from abstract code, the module name
  541. %% will be set after running the v3_core pass.
  542. Passes.
  543. %% select_passes([Command], Opts) -> [{Name,Function}]
  544. %% Interpret the lists of commands to return a pure list of passes.
  545. %%
  546. %% Command can be one of:
  547. %%
  548. %% {pass,Mod} Will be expanded to a call to the external
  549. %% function Mod:module(Code, Options). This
  550. %% function must transform the code and return
  551. %% {ok,NewCode} or {ok,NewCode,Warnings}.
  552. %% Example: {pass,beam_ssa_codegen}
  553. %%
  554. %% {Name,Fun} Name is an atom giving the name of the pass.
  555. %% Fun is an 'fun' taking one argument: a #compile{} record.
  556. %% The fun should return {ok,NewCompileRecord} or
  557. %% {error,NewCompileRecord}.
  558. %% Note: ?pass(Name) is equvivalent to {Name,fun Name/1}.
  559. %% Example: ?pass(parse_module)
  560. %%
  561. %% {Name,Test,Fun} Like {Name,Fun} above, but the pass will be run
  562. %% (and listed by the `time' option) only if Test(St)
  563. %% returns true.
  564. %%
  565. %% {src_listing,Ext} Produces an Erlang source listing with the
  566. %% the file extension Ext. (Ext should not contain
  567. %% a period.) No more passes will be run.
  568. %%
  569. %% {listing,Ext} Produce an listing of the terms in the internal
  570. %% representation. The extension of the listing
  571. %% file will be Ext. (Ext should not contain
  572. %% a period.) No more passes will be run.
  573. %%
  574. %% done End compilation at this point.
  575. %%
  576. %% {done,Ext} End compilation at this point. Produce a listing
  577. %% as with {listing,Ext}, unless 'binary' is
  578. %% specified, in which case the current
  579. %% representation of the code is returned without
  580. %% creating an output file.
  581. %%
  582. %% {iff,Flag,Cmd} If the given Flag is given in the option list,
  583. %% Cmd will be interpreted as a command.
  584. %% Otherwise, Cmd will be ignored.
  585. %% Example: {iff,dcg,{listing,"codegen}}
  586. %%
  587. %% {unless,Flag,Cmd} If the given Flag is NOT given in the option list,
  588. %% Cmd will be interpreted as a command.
  589. %% Otherwise, Cmd will be ignored.
  590. %% Example: {unless,no_kernopt,{pass,sys_kernopt}}
  591. %%
  592. select_passes([{pass,Mod}|Ps], Opts) ->
  593. F = fun(Code0, St) ->
  594. case Mod:module(Code0, St#compile.options) of
  595. {ok,Code} ->
  596. {ok,Code,St};
  597. {ok,Code,Ws} ->
  598. {ok,Code,St#compile{warnings=St#compile.warnings++Ws}};
  599. Other ->
  600. Es = [{St#compile.ifile,[{none,?MODULE,{bad_return,Mod,Other}}]}],
  601. {error,St#compile{errors=St#compile.errors ++ Es}}
  602. end
  603. end,
  604. [{Mod,F}|select_passes(Ps, Opts)];
  605. select_passes([{_,Fun}=P|Ps], Opts) when is_function(Fun) ->
  606. [P|select_passes(Ps, Opts)];
  607. select_passes([{_,Test,Fun}=P|Ps], Opts) when is_function(Test),
  608. is_function(Fun) ->
  609. [P|select_passes(Ps, Opts)];
  610. select_passes([{src_listing,Ext}|_], _Opts) ->
  611. [{listing,fun (Code, St) -> src_listing(Ext, Code, St) end}];
  612. select_passes([{listing,Ext}|_], _Opts) ->
  613. [{listing,fun (Code, St) -> listing(Ext, Code, St) end}];
  614. select_passes([done|_], _Opts) ->
  615. [];
  616. select_passes([{done,Ext}|_], Opts) ->
  617. select_passes([{unless,binary,{listing,Ext}}], Opts);
  618. select_passes([{iff,Flag,Pass}|Ps], Opts) ->
  619. select_cond(Flag, true, Pass, Ps, Opts);
  620. select_passes([{unless,Flag,Pass}|Ps], Opts) ->
  621. select_cond(Flag, false, Pass, Ps, Opts);
  622. select_passes([{delay,Passes0}|Ps], Opts) when is_list(Passes0) ->
  623. %% Delay evaluation of compiler options and which compiler passes to run.
  624. %% Since we must know beforehand whether a listing will be produced, we
  625. %% will go through the list of passes and evaluate all conditions that
  626. %% select a list pass.
  627. case select_list_passes(Passes0, Opts) of
  628. {done,Passes} ->
  629. [{delay,Passes}];
  630. {not_done,Passes} ->
  631. [{delay,Passes}|select_passes(Ps, Opts)]
  632. end;
  633. select_passes([], _Opts) ->
  634. [];
  635. select_passes([List|Ps], Opts) when is_list(List) ->
  636. case select_passes(List, Opts) of
  637. [] -> select_passes(Ps, Opts);
  638. Nested ->
  639. case last(Nested) of
  640. {listing,_Fun} -> Nested;
  641. _Other -> Nested ++ select_passes(Ps, Opts)
  642. end
  643. end.
  644. select_cond(Flag, ShouldBe, Pass, Ps, Opts) ->
  645. ShouldNotBe = not ShouldBe,
  646. case member(Flag, Opts) of
  647. ShouldBe -> select_passes([Pass|Ps], Opts);
  648. ShouldNotBe -> select_passes(Ps, Opts)
  649. end.
  650. %% select_list_passes([Pass], Opts) -> {done,[Pass]} | {not_done,[Pass]}
  651. %% Evaluate all conditions having to do with listings in the list of
  652. %% passes.
  653. select_list_passes(Ps, Opts) ->
  654. select_list_passes_1(Ps, Opts, []).
  655. select_list_passes_1([{iff,Flag,{listing,_}=Listing}|Ps], Opts, Acc) ->
  656. case member(Flag, Opts) of
  657. true -> {done,reverse(Acc, [Listing])};
  658. false -> select_list_passes_1(Ps, Opts, Acc)
  659. end;
  660. select_list_passes_1([{iff,Flag,{done,Ext}}|Ps], Opts, Acc) ->
  661. case member(Flag, Opts) of
  662. false ->
  663. select_list_passes_1(Ps, Opts, Acc);
  664. true ->
  665. {done,case member(binary, Opts) of
  666. false -> reverse(Acc, [{listing,Ext}]);
  667. true -> reverse(Acc)
  668. end}
  669. end;
  670. select_list_passes_1([{iff=Op,Flag,List0}|Ps], Opts, Acc) when is_list(List0) ->
  671. case select_list_passes(List0, Opts) of
  672. {done,List} -> {done,reverse(Acc) ++ List};
  673. {not_done,List} -> select_list_passes_1(Ps, Opts, [{Op,Flag,List}|Acc])
  674. end;
  675. select_list_passes_1([{unless=Op,Flag,List0}|Ps], Opts, Acc) when is_list(List0) ->
  676. case select_list_passes(List0, Opts) of
  677. {done,List} -> {done,reverse(Acc) ++ List};
  678. {not_done,List} -> select_list_passes_1(Ps, Opts, [{Op,Flag,List}|Acc])
  679. end;
  680. select_list_passes_1([P|Ps], Opts, Acc) ->
  681. select_list_passes_1(Ps, Opts, [P|Acc]);
  682. select_list_passes_1([], _, Acc) ->
  683. {not_done,reverse(Acc)}.
  684. %% The standard passes (almost) always run.
  685. standard_passes() ->
  686. [?pass(transform_module),
  687. {iff,makedep_side_effect,?pass(makedep_and_output)},
  688. {iff,makedep,[
  689. ?pass(makedep),
  690. {unless,binary,?pass(makedep_output)}
  691. ]},
  692. {iff,makedep,done},
  693. {iff,'dpp',{listing,"pp"}},
  694. ?pass(lint_module),
  695. {iff,'P',{src_listing,"P"}},
  696. {iff,'to_pp',{done,"P"}},
  697. {iff,'dabstr',{listing,"abstr"}}
  698. | abstr_passes(verified_abstr)].
  699. abstr_passes(AbstrStatus) ->
  700. case AbstrStatus of
  701. non_verified_abstr -> [{unless, no_lint, ?pass(lint_module)}];
  702. verified_abstr -> []
  703. end ++
  704. [
  705. %% Add all -compile() directives to #compile.options
  706. ?pass(compile_directives),
  707. {delay,[{iff,debug_info,?pass(save_abstract_code)}]},
  708. ?pass(expand_records),
  709. {iff,'dexp',{listing,"expand"}},
  710. {iff,'E',?pass(legalize_vars)},
  711. {iff,'E',{src_listing,"E"}},
  712. {iff,'to_exp',{done,"E"}},
  713. %% Conversion to Core Erlang.
  714. ?pass(core),
  715. {iff,'dcore',{listing,"core"}},
  716. {iff,'to_core0',{done,"core"}}
  717. | core_passes(verified_core)].
  718. core_passes(CoreStatus) ->
  719. %% Optimization and transforms of Core Erlang code.
  720. case CoreStatus of
  721. non_verified_core ->
  722. [?pass(core_lint_module),
  723. {unless,no_core_prepare,{pass,sys_core_prepare}},
  724. {iff,dprep,{listing,"prepare"}}];
  725. verified_core ->
  726. [{iff,clint0,?pass(core_lint_module)}]
  727. end ++
  728. [
  729. {delay,
  730. [{unless,no_copt,
  731. [{core_old_inliner,fun test_old_inliner/1,fun core_old_inliner/2},
  732. {iff,doldinline,{listing,"oldinline"}},
  733. {unless,no_fold,{pass,sys_core_fold}},
  734. {iff,dcorefold,{listing,"corefold"}},
  735. {core_inline_module,fun test_core_inliner/1,fun core_inline_module/2},
  736. {iff,dinline,{listing,"inline"}},
  737. {core_fold_after_inlining,fun test_any_inliner/1,
  738. fun core_fold_module_after_inlining/2},
  739. {iff,dcopt,{listing,"copt"}},
  740. {unless,no_alias,{pass,sys_core_alias}},
  741. {iff,dalias,{listing,"core_alias"}},
  742. ?pass(core_transforms)]},
  743. {iff,'to_core',{done,"core"}}]}
  744. | kernel_passes()].
  745. kernel_passes() ->
  746. %% Optimizations that must be done after all other optimizations.
  747. [{pass,sys_core_bsm},
  748. {iff,dcbsm,{listing,"core_bsm"}},
  749. {iff,clint,?pass(core_lint_module)},
  750. %% Kernel Erlang and code generation.
  751. ?pass(v3_kernel),
  752. {iff,dkern,{listing,"kernel"}},
  753. {iff,'to_kernel',{done,"kernel"}},
  754. {pass,beam_kernel_to_ssa},
  755. {iff,dssa,{listing,"ssa"}},
  756. {iff,ssalint,{pass,beam_ssa_lint}},
  757. {delay,
  758. [{unless,no_bool_opt,{pass,beam_ssa_bool}},
  759. {iff,dbool,{listing,"bool"}},
  760. {unless,no_bool_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
  761. {unless,no_share_opt,{pass,beam_ssa_share}},
  762. {iff,dssashare,{listing,"ssashare"}},
  763. {unless,no_share_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
  764. {unless,no_recv_opt,{pass,beam_ssa_recv}},
  765. {iff,drecv,{listing,"recv"}},
  766. {unless,no_recv_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
  767. {unless,no_bsm_opt,{pass,beam_ssa_bsm}},
  768. {iff,dssabsm,{listing,"ssabsm"}},
  769. {unless,no_bsm_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
  770. {unless,no_fun_opt,{pass,beam_ssa_funs}},
  771. {iff,dssafuns,{listing,"ssafuns"}},
  772. {unless,no_fun_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
  773. {unless,no_ssa_opt,{pass,beam_ssa_opt}},
  774. {iff,dssaopt,{listing,"ssaopt"}},
  775. {unless,no_ssa_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
  776. {unless,no_throw_opt,{pass,beam_ssa_throw}},
  777. {iff,dthrow,{listing,"throw"}},
  778. {unless,no_throw_opt,{iff,ssalint,{pass,beam_ssa_lint}}}]},
  779. {pass,beam_ssa_pre_codegen},
  780. {iff,dprecg,{listing,"precodegen"}},
  781. {iff,ssalint,{pass,beam_ssa_lint}},
  782. {pass,beam_ssa_codegen},
  783. {iff,dcg,{listing,"codegen"}},
  784. {iff,doldcg,{listing,"codegen"}},
  785. ?pass(beam_validator_strong)
  786. | asm_passes()].
  787. asm_passes() ->
  788. %% Assembly level optimisations.
  789. [{delay,
  790. [{pass,beam_a},
  791. {iff,da,{listing,"a"}},
  792. {unless,no_postopt,
  793. [{pass,beam_block},
  794. {iff,dblk,{listing,"block"}},
  795. {unless,no_jopt,{pass,beam_jump}},
  796. {iff,djmp,{listing,"jump"}},
  797. {pass,beam_clean},
  798. {iff,dclean,{listing,"clean"}},
  799. {unless,no_stack_trimming,{pass,beam_trim}},
  800. {iff,dtrim,{listing,"trim"}},
  801. {pass,beam_flatten}]},
  802. %% If post optimizations are turned off, we still
  803. %% need to do a few clean-ups to code.
  804. {iff,no_postopt,[{pass,beam_clean}]},
  805. {iff,diffable,?pass(diffable)},
  806. {pass,beam_z},
  807. {iff,diffable,{listing,"S"}},
  808. {iff,dz,{listing,"z"}},
  809. {iff,dopt,{listing,"optimize"}},
  810. {iff,'S',{listing,"S"}},
  811. {iff,'to_asm',{done,"S"}}]},
  812. ?pass(beam_validator_weak),
  813. ?pass(beam_asm)
  814. | binary_passes()].
  815. binary_passes() ->
  816. [{iff,'to_dis',?pass(to_dis)},
  817. {unless,binary,?pass(save_binary,not_werror)}
  818. ].
  819. %%%
  820. %%% Compiler passes.
  821. %%%
  822. %% Remove the target file so we don't have an old one if the compilation fail.
  823. remove_file(Code, St) ->
  824. _ = file:delete(St#compile.ofile),
  825. {ok,Code,St}.
  826. -record(asm_module, {module,
  827. exports,
  828. labels,
  829. functions=[],
  830. attributes=[]}).
  831. preprocess_asm_forms(Forms) ->
  832. R = #asm_module{},
  833. R1 = collect_asm(Forms, R),
  834. {R1#asm_module.module,
  835. {R1#asm_module.module,
  836. R1#asm_module.exports,
  837. R1#asm_module.attributes,
  838. reverse(R1#asm_module.functions),
  839. R1#asm_module.labels}}.
  840. collect_asm([{module,M} | Rest], R) ->
  841. collect_asm(Rest, R#asm_module{module=M});
  842. collect_asm([{exports,M} | Rest], R) ->
  843. collect_asm(Rest, R#asm_module{exports=M});
  844. collect_asm([{labels,M} | Rest], R) ->
  845. collect_asm(Rest, R#asm_module{labels=M});
  846. collect_asm([{function,A,B,C} | Rest0], R0) ->
  847. {Code,Rest} = collect_asm_function(Rest0, []),
  848. Func = {function,A,B,C,Code},
  849. R = R0#asm_module{functions=[Func | R0#asm_module.functions]},
  850. collect_asm(Rest, R);
  851. collect_asm([{attributes, Attr} | Rest], R) ->
  852. collect_asm(Rest, R#asm_module{attributes=Attr});
  853. collect_asm([], R) -> R.
  854. collect_asm_function([{function,_,_,_}|_]=Is, Acc) ->
  855. {reverse(Acc),Is};
  856. collect_asm_function([I|Is], Acc) ->
  857. collect_asm_function(Is, [I|Acc]);
  858. collect_asm_function([], Acc) ->
  859. {reverse(Acc),[]}.
  860. beam_consult_asm(_Code, St) ->
  861. case file:consult(St#compile.ifile) of
  862. {ok,Forms0} ->
  863. Encoding = epp:read_encoding(St#compile.ifile),
  864. {Module,Forms} = preprocess_asm_forms(Forms0),
  865. {ok,Forms,St#compile{module=Module,encoding=Encoding}};
  866. {error,E} ->
  867. Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
  868. {error,St#compile{errors=St#compile.errors ++ Es}}
  869. end.
  870. get_module_name_from_asm({Mod,_,_,_,_}=Asm, St) ->
  871. {ok,Asm,St#compile{module=Mod}};
  872. get_module_name_from_asm(Asm, St) ->
  873. %% Invalid Beam assembly code. Let it crash in a later pass.
  874. {ok,Asm,St}.
  875. parse_module(_Code, St) ->
  876. case do_parse_module(utf8, St) of
  877. {ok,_,_}=Ret ->
  878. Ret;
  879. {error,_}=Ret ->
  880. Ret
  881. end.
  882. do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
  883. SourceName0 = proplists:get_value(source, Opts, File),
  884. SourceName = case member(deterministic, Opts) of
  885. true ->
  886. filename:basename(SourceName0);
  887. false ->
  888. case member(absolute_source, Opts) of
  889. true -> paranoid_absname(SourceName0);
  890. false -> SourceName0
  891. end
  892. end,
  893. StartLocation = case with_columns(Opts) of
  894. true ->
  895. {1,1};
  896. false ->
  897. 1
  898. end,
  899. R = epp:parse_file(File,
  900. [{includes,[".",Dir|inc_paths(Opts)]},
  901. {source_name, SourceName},
  902. {macros,pre_defs(Opts)},
  903. {default_encoding,DefEncoding},
  904. {location,StartLocation},
  905. extra]),
  906. case R of
  907. {ok,Forms0,Extra} ->
  908. Encoding = proplists:get_value(encoding, Extra),
  909. Forms = case with_columns(Opts ++ compile_options(Forms0)) of
  910. true ->
  911. Forms0;
  912. false ->
  913. strip_columns(Forms0)
  914. end,
  915. {ok,Forms,St#compile{encoding=Encoding}};
  916. {error,E} ->
  917. Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
  918. {error,St#compile{errors=St#compile.errors ++ Es}}
  919. end.
  920. with_columns(Opts) ->
  921. case proplists:get_value(error_location, Opts, column) of
  922. column -> true;
  923. line -> false
  924. end.
  925. consult_abstr(_Code, St) ->
  926. case file:consult(St#compile.ifile) of
  927. {ok,Forms} ->
  928. Encoding = epp:read_encoding(St#compile.ifile),
  929. {ok,Forms,St#compile{encoding=Encoding}};
  930. {error,E} ->
  931. Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
  932. {error,St#compile{errors=St#compile.errors ++ Es}}
  933. end.
  934. parse_core(_Code, St) ->
  935. case file:read_file(St#compile.ifile) of
  936. {ok,Bin} ->
  937. case core_scan:string(binary_to_list(Bin)) of
  938. {ok,Toks,_} ->
  939. case core_parse:parse(Toks) of
  940. {ok,Mod} ->
  941. Name = (Mod#c_module.name)#c_literal.val,
  942. {ok,Mod,St#compile{module=Name}};
  943. {error,E} ->
  944. Es = [{St#compile.ifile,[E]}],
  945. {error,St#compile{errors=St#compile.errors ++ Es}}
  946. end;
  947. {error,E,_} ->
  948. Es = [{St#compile.ifile,[E]}],
  949. {error,St#compile{errors=St#compile.errors ++ Es}}
  950. end;
  951. {error,E} ->
  952. Es = [{St#compile.ifile,[{none,compile,{open,E}}]}],
  953. {error,St#compile{errors=St#compile.errors ++ Es}}
  954. end.
  955. get_module_name_from_core(Core, St) ->
  956. try
  957. Mod = cerl:concrete(cerl:module_name(Core)),
  958. {ok,Core,St#compile{module=Mod}}
  959. catch
  960. _:_ ->
  961. %% Invalid Core Erlang code. Let it crash in a later pass.
  962. {ok,Core,St}
  963. end.
  964. compile_options([{attribute,_L,compile,C}|Fs]) when is_list(C) ->
  965. C ++ compile_options(Fs);
  966. compile_options([{attribute,_L,compile,C}|Fs]) ->
  967. [C|compile_options(Fs)];
  968. compile_options([_F|Fs]) -> compile_options(Fs);
  969. compile_options([]) -> [].
  970. clean_parse_transforms(Fs) ->
  971. clean_parse_transforms_1(Fs, []).
  972. clean_parse_transforms_1([{attribute,L,compile,C0}|Fs], Acc) when is_list(C0) ->
  973. C = lists:filter(fun({parse_transform,_}) -> false;
  974. (_) -> true
  975. end, C0),
  976. clean_parse_transforms_1(Fs, [{attribute,L,compile,C}|Acc]);
  977. clean_parse_transforms_1([{attribute,_,compile,{parse_transform,_}}|Fs], Acc) ->
  978. clean_parse_transforms_1(Fs, Acc);
  979. clean_parse_transforms_1([F|Fs], Acc) ->
  980. clean_parse_transforms_1(Fs, [F|Acc]);
  981. clean_parse_transforms_1([], Acc) -> reverse(Acc).
  982. transforms(Os) -> [ M || {parse_transform,M} <- Os ].
  983. transform_module(Code0, #compile{options=Opt}=St) ->
  984. %% Extract compile options from code into options field.
  985. case transforms(Opt ++ compile_options(Code0)) of
  986. [] ->
  987. %% No parse transforms.
  988. {ok,Code0,St};
  989. Ts ->
  990. %% Remove parse_transform attributes from the abstract code to
  991. %% prevent parse transforms to be run more than once.
  992. Code = clean_parse_transforms(Code0),
  993. foldl_transform(Ts, Code, St)
  994. end.
  995. foldl_transform([T|Ts], Code0, St) ->
  996. Name = "transform " ++ atom_to_list(T),
  997. case code:ensure_loaded(T) =:= {module,T} andalso
  998. erlang:function_exported(T, parse_transform, 2) of
  999. true ->
  1000. Fun = fun(Code, S) ->
  1001. T:parse_transform(Code, S#compile.options)
  1002. end,
  1003. Run = runner(none, St),
  1004. StrippedCode = maybe_strip_columns(Code0, T, St),
  1005. try Run({Name, Fun}, StrippedCode, St) of
  1006. {error,Es,Ws} ->
  1007. {error,St#compile{warnings=St#compile.warnings ++ Ws,
  1008. errors=St#compile.errors ++ Es}};
  1009. {warning, Forms, Ws} ->
  1010. foldl_transform(Ts, Forms,
  1011. St#compile{warnings=St#compile.warnings ++ Ws});
  1012. Forms ->
  1013. foldl_transform(Ts, Forms, St)
  1014. catch
  1015. Class:Reason:Stk ->
  1016. Es = [{St#compile.ifile,[{none,compile,
  1017. {parse_transform,T,{Class,Reason,Stk}}}]}],
  1018. {error,St#compile{errors=St#compile.errors ++ Es}}
  1019. end;
  1020. false ->
  1021. Es = [{St#compile.ifile,[{none,compile,
  1022. {undef_parse_transform,T}}]}],
  1023. {error,St#compile{errors=St#compile.errors ++ Es}}
  1024. end;
  1025. foldl_transform([], Code, St) ->
  1026. %% We may need to strip columns added by parse transforms before returning
  1027. %% them back to the compiler. We pass ?MODULE as a bit of a hack to get the
  1028. %% correct default.
  1029. {ok, maybe_strip_columns(Code, ?MODULE, St), St}.
  1030. %%% If a parse transform does not support column numbers it can say so using
  1031. %%% the parse_transform_info callback. The error_location is taken from both
  1032. %%% compiler options and from the parse transform and if either of them want
  1033. %%% to only use lines, we strip columns.
  1034. maybe_strip_columns(Code, T, St) ->
  1035. PTErrorLocation =
  1036. case erlang:function_exported(T, parse_transform_info, 0) of
  1037. true ->
  1038. maps:get(error_location, T:parse_transform_info(), column);
  1039. false ->
  1040. column
  1041. end,
  1042. ConfigErrorLocation = proplists:get_value(error_location, St#compile.options, column),
  1043. if
  1044. PTErrorLocation =:= line; ConfigErrorLocation =:= line ->
  1045. strip_columns(Code);
  1046. true -> Code
  1047. end.
  1048. strip_columns(Code) ->
  1049. F = fun(A) -> erl_anno:set_location(erl_anno:line(A), A) end,
  1050. [case Form of
  1051. {eof,{Line,_Col}} ->
  1052. {eof,Line};
  1053. {ErrorOrWarning,{{Line,_Col},Module,Reason}}
  1054. when ErrorOrWarning =:= error;
  1055. ErrorOrWarning =:= warning ->
  1056. {ErrorOrWarning,{Line,Module,Reason}};
  1057. Form ->
  1058. erl_parse:map_anno(F, Form)
  1059. end || Form <- Code].
  1060. get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts].
  1061. core_transforms(Code, St) ->
  1062. %% The options field holds the complete list of options at this
  1063. Ts = get_core_transforms(St#compile.options),
  1064. foldl_core_transforms(Ts, Code, St).
  1065. foldl_core_transforms([T|Ts], Code0, St) ->
  1066. Name = "core transform " ++ atom_to_list(T),
  1067. Fun = fun(Code, S) -> T:core_transform(Code, S#compile.options) end,
  1068. Run = runner(none, St),
  1069. try Run({Name, Fun}, Code0, St) of
  1070. Forms ->
  1071. foldl_core_transforms(Ts, Forms, St)
  1072. catch
  1073. Class:Reason:Stk ->
  1074. Es = [{St#compile.ifile,[{none,compile,
  1075. {core_transform,T,{Class,Reason,Stk}}}]}],
  1076. {error,St#compile{errors=St#compile.errors ++ Es}}
  1077. end;
  1078. foldl_core_transforms([], Code, St) -> {ok,Code,St}.
  1079. %%% Fetches the module name from a list of forms. The module attribute must
  1080. %%% be present.
  1081. get_module([{attribute,_,module,M} | _]) -> M;
  1082. get_module([_ | Rest]) ->
  1083. get_module(Rest).
  1084. %%% A #compile state is returned, where St.base has been filled in
  1085. %%% with the module name from Forms, as a string, in case it wasn't
  1086. %%% set in St (i.e., it was "").
  1087. add_default_base(St, Forms) ->
  1088. F = St#compile.filename,
  1089. case F of
  1090. "" ->
  1091. M = get_module(Forms),
  1092. St#compile{base=atom_to_list(M)};
  1093. _ ->
  1094. St
  1095. end.
  1096. lint_module(Code, St) ->
  1097. case erl_lint:module(Code, St#compile.ifile, St#compile.options) of
  1098. {ok,Ws} ->
  1099. %% Insert name of module as base name, if needed. This is
  1100. %% for compile:forms to work with listing files.
  1101. St1 = add_default_base(St, Code),
  1102. {ok,Code,St1#compile{warnings=St1#compile.warnings ++ Ws}};
  1103. {error,Es,Ws} ->
  1104. {error,St#compile{warnings=St#compile.warnings ++ Ws,
  1105. errors=St#compile.errors ++ Es}}
  1106. end.
  1107. core_lint_module(Code, St) ->
  1108. case core_lint:module(Code, St#compile.options) of
  1109. {ok,Ws} ->
  1110. {ok,Code,St#compile{warnings=St#compile.warnings ++ Ws}};
  1111. {error,Es,Ws} ->
  1112. {error,St#compile{warnings=St#compile.warnings ++ Ws,
  1113. errors=St#compile.errors ++ Es}}
  1114. end.
  1115. %% makedep + output and continue
  1116. makedep_and_output(Code0, St) ->
  1117. {ok,DepCode,St1} = makedep(Code0,St),
  1118. case makedep_output(DepCode, St1) of
  1119. {ok,_IgnoreCode,St2} ->
  1120. {ok,Code0,St2};
  1121. {error,St2} ->
  1122. {error,St2}
  1123. end.
  1124. makedep(Code0, #compile{ifile=Ifile,ofile=Ofile,options=Opts}=St) ->
  1125. %% Get the target of the Makefile rule.
  1126. Target0 =
  1127. case proplists:get_value(makedep_target, Opts) of
  1128. undefined ->
  1129. %% The target is derived from the output filename: possibly
  1130. %% remove the current working directory to obtain a relative
  1131. %% path.
  1132. shorten_filename(Ofile);
  1133. T ->
  1134. %% The caller specified one.
  1135. T
  1136. end,
  1137. %% Quote the target is the called asked for this.
  1138. Target1 = case proplists:get_value(makedep_quote_target, Opts) of
  1139. true ->
  1140. %% For now, only "$" is replaced by "$$".
  1141. Fun = fun
  1142. ($$) -> "$$";
  1143. (C) -> C
  1144. end,
  1145. map(Fun, Target0);
  1146. _ ->
  1147. Target0
  1148. end,
  1149. Target = Target1 ++ ":",
  1150. %% List the dependencies (includes) for this target.
  1151. {MainRule,PhonyRules} = makedep_add_headers(
  1152. Ifile, % The input file name.
  1153. Code0, % The parsed source.
  1154. [], % The list of dependencies already added.
  1155. length(Target), % The current line length.
  1156. Target, % The target.
  1157. "", % Phony targets.
  1158. Opts),
  1159. %% Prepare the content of the Makefile. For instance:
  1160. %% hello.erl: hello.hrl common.hrl
  1161. %%
  1162. %% Or if phony targets are enabled:
  1163. %% hello.erl: hello.hrl common.hrl
  1164. %%
  1165. %% hello.hrl:
  1166. %%
  1167. %% common.hrl:
  1168. Makefile = case proplists:get_value(makedep_phony, Opts) of
  1169. true -> MainRule ++ PhonyRules;
  1170. _ -> MainRule
  1171. end,
  1172. Code = unicode:characters_to_binary([Makefile,"\n"]),
  1173. {ok,Code,St}.
  1174. makedep_add_headers(Ifile, [{attribute,_,file,{File,_}}|Rest],
  1175. Included, LineLen, MainTarget, Phony, Opts) ->
  1176. %% The header "File" exists, add it to the dependencies.
  1177. {Included1,LineLen1,MainTarget1,Phony1} =
  1178. makedep_add_header(Ifile, Included, LineLen, MainTarget, Phony, File),
  1179. makedep_add_headers(Ifile, Rest, Included1, LineLen1,
  1180. MainTarget1, Phony1, Opts);
  1181. makedep_add_headers(Ifile, [{error,{_,epp,{include,file,File}}}|Rest],
  1182. Included, LineLen, MainTarget, Phony, Opts) ->
  1183. %% The header "File" doesn't exist, do we add it to the dependencies?
  1184. case proplists:get_value(makedep_add_missing, Opts) of
  1185. true ->
  1186. {Included1,LineLen1,MainTarget1,Phony1} =
  1187. makedep_add_header(Ifile, Included, LineLen, MainTarget,
  1188. Phony, File),
  1189. makedep_add_headers(Ifile, Rest, Included1, LineLen1,
  1190. MainTarget1, Phony1, Opts);
  1191. _ ->
  1192. makedep_add_headers(Ifile, Rest, Included, LineLen,
  1193. MainTarget, Phony, Opts)
  1194. end;
  1195. makedep_add_headers(Ifile, [_|Rest], Included, LineLen,
  1196. MainTarget, Phony, Opts) ->
  1197. makedep_add_headers(Ifile, Rest, Included,
  1198. LineLen, MainTarget, Phony, Opts);
  1199. makedep_add_headers(_Ifile, [], _Included, _LineLen,
  1200. MainTarget, Phony, _Opts) ->
  1201. {MainTarget,Phony}.
  1202. makedep_add_header(Ifile, Included, LineLen, MainTarget, Phony, File) ->
  1203. case member(File, Included) of
  1204. true ->
  1205. %% This file was already listed in the dependencies, skip it.
  1206. {Included,LineLen,MainTarget,Phony};
  1207. false ->
  1208. Included1 = [File|Included],
  1209. %% Remove "./" in front of the dependency filename.
  1210. File1 = case File of
  1211. "./" ++ File0 -> File0;
  1212. _ -> File
  1213. end,
  1214. %% Prepare the phony target name.
  1215. Phony1 = case File of
  1216. Ifile -> Phony;
  1217. _ -> Phony ++ "\n\n" ++ File1 ++ ":"
  1218. end,
  1219. %% Add the file to the dependencies. Lines longer than 76 columns
  1220. %% are split.
  1221. if
  1222. LineLen + 1 + length(File1) > 76 ->
  1223. LineLen1 = 2 + length(File1),
  1224. MainTarget1 = MainTarget ++ " \\\n " ++ File1,
  1225. {Included1,LineLen1,MainTarget1,Phony1};
  1226. true ->
  1227. LineLen1 = LineLen + 1 + length(File1),
  1228. MainTarget1 = MainTarget ++ " " ++ File1,
  1229. {Included1,LineLen1,MainTarget1,Phony1}
  1230. end
  1231. end.
  1232. makedep_output(Code, #compile{options=Opts,ofile=Ofile}=St) ->
  1233. %% Write this Makefile (Code) to the selected output.
  1234. %% If no output is specified, the default is to write to a file named after
  1235. %% the output file.
  1236. Output = case proplists:get_value(makedep_output, Opts) of
  1237. undefined ->
  1238. %% Prepare the default filename.
  1239. outfile(filename:basename(Ofile, ".beam"), "Pbeam", Opts);
  1240. Other ->
  1241. Other
  1242. end,
  1243. if
  1244. is_list(Output) ->
  1245. %% Write the depedencies to a file.
  1246. case file:write_file(Output, Code) of
  1247. ok ->
  1248. {ok,Code,St};
  1249. {error,Reason} ->
  1250. Err = {St#compile.ifile,[{none,?MODULE,{write_error,Reason}}]},
  1251. {error,St#compile{errors=St#compile.errors++[Err]}}
  1252. end;
  1253. true ->
  1254. %% Write the depedencies to a device.
  1255. try io:fwrite(Output, "~ts", [Code]) of
  1256. ok ->
  1257. {ok,Code,St}
  1258. catch
  1259. error:_ ->
  1260. Err = {St#compile.ifile,[{none,?MODULE,write_error}]},
  1261. {error,St#compile{errors=St#compile.errors++[Err]}}
  1262. end
  1263. end.
  1264. expand_records(Code0, #compile{options=Opts}=St) ->
  1265. Code = erl_expand_records:module(Code0, Opts),
  1266. {ok,Code,St}.
  1267. legalize_vars(Code0, St) ->
  1268. Code = map(fun(F={function,_,_,_,_}) ->
  1269. erl_pp:legalize_vars(F);
  1270. (F) ->
  1271. F
  1272. end, Code0),
  1273. {ok,Code,St}.
  1274. compile_directives(Forms, #compile{options=Opts0}=St0) ->
  1275. Opts1 = expand_opts(flatten([C || {attribute,_,compile,C} <- Forms])),
  1276. Opts = Opts1 ++ Opts0,
  1277. St1 = St0#compile{options=Opts},
  1278. case any_obsolete_option(Opts) of
  1279. {yes,Opt} ->
  1280. Error = {St1#compile.ifile,[{none,?MODULE,{obsolete_option,Opt}}]},
  1281. St = St1#compile{errors=[Error|St1#compile.errors]},
  1282. {error,St};
  1283. no ->
  1284. {ok,Forms,St1}
  1285. end.
  1286. any_obsolete_option([Opt|Opts]) ->
  1287. case is_obsolete(Opt) of
  1288. true -> {yes,Opt};
  1289. false -> any_obsolete_option(Opts)
  1290. end;
  1291. any_obsolete_option([]) -> no.
  1292. is_obsolete(r18) -> true;
  1293. is_obsolete(r19) -> true;
  1294. is_obsolete(r20) -> true;
  1295. is_obsolete(r21) -> true;
  1296. is_obsolete(no_bsm3) -> true;
  1297. is_obsolete(no_get_hd_…

Large files files are truncated, but you can click here to view the full file