1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
16
%% $Id: compile.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
18
%% Purpose: Run the Erlang compiler.
21
-include("erl_compile.hrl").
22
-include("core_parse.hrl").
24
%% High-level interface.
25
-export([file/1,file/2,format_error/1,iofile/1]).
26
-export([forms/1,forms/2]).
27
-export([output_generated/1]).
31
-export([compile/3,compile_beam/3,compile_asm/3,compile_core/3]).
34
-import(lists, [member/2,reverse/1,keysearch/3,last/1,
35
map/2,flatmap/2,foreach/2,foldr/3,any/2,filter/2]).
38
%% file(FileName, Options)
39
%% Compile the module in file FileName.
41
-define(DEFAULT_OPTIONS, [verbose,report_errors,report_warnings]).
43
-define(pass(P), {P,fun P/1}).
45
file(File) -> file(File, ?DEFAULT_OPTIONS).
47
file(File, Opts) when list(Opts) ->
48
do_compile({file,File}, Opts++env_default_opts());
50
file(File, [Opt|?DEFAULT_OPTIONS]).
52
forms(File) -> forms(File, ?DEFAULT_OPTIONS).
54
forms(Forms, Opts) when list(Opts) ->
55
do_compile({forms,Forms}, [binary|Opts++env_default_opts()]);
56
forms(Forms, Opts) when atom(Opts) ->
57
forms(Forms, [Opts|?DEFAULT_OPTIONS]).
60
Key = "ERL_COMPILER_OPTIONS",
61
case os:getenv(Key) of
64
case erl_scan:string(Str) of
66
case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of
67
{ok,List} when list(List) -> List;
70
io:format("Ignoring bad term in ~s\n", [Key]),
73
{error, {_,_,_Reason}, _} ->
74
io:format("Ignoring bad term in ~s\n", [Key]),
79
do_compile(Input, Opts0) ->
80
Opts = expand_opts(Opts0),
82
Serv = spawn_link(fun() -> internal(Self, Input, Opts) end),
87
%% Given a list of compilation options, returns true if compile:file/2
88
%% would have generated a Beam file, false otherwise (if only a binary or a
89
%% listing file would have been generated).
91
output_generated(Opts) ->
92
any(fun ({save_binary,_F}) -> true;
94
end, passes(file, expand_opts(Opts))).
97
foldr(fun expand_opt/2, [], Opts).
99
expand_opt(basic_validation, Os) ->
100
[no_code_generation,to_pp,binary|Os];
101
expand_opt(strong_validation, Os) ->
102
[no_code_generation,to_kernel,binary|Os];
103
expand_opt(report, Os) ->
104
[report_errors,report_warnings|Os];
105
expand_opt(return, Os) ->
106
[return_errors,return_warnings|Os];
107
expand_opt(r7, Os) ->
108
[no_float_opt,no_new_funs,no_new_binaries,no_new_apply|Os];
109
expand_opt(O, Os) -> [O|Os].
111
filter_opts(Opts0) ->
112
%% Native code generation is not supported if no_new_funs is given.
113
case member(no_new_funs, Opts0) of
115
true -> Opts0 -- [native]
118
%% format_error(ErrorDescriptor) -> string()
120
format_error(no_native_support) ->
121
"this system is not configured for native-code compilation.";
122
format_error({native, E}) ->
123
io_lib:fwrite("native-code compilation failed with reason: ~P.",
125
format_error({native_crash, E}) ->
126
io_lib:fwrite("native-code compilation crashed with reason: ~P.",
128
format_error({open,E}) ->
129
io_lib:format("open error '~s'", [file:format_error(E)]);
130
format_error({epp,E}) ->
132
format_error(write_error) ->
133
"error writing file";
134
format_error({rename,S}) ->
135
io_lib:format("error renaming ~s", [S]);
136
format_error({parse_transform,M,R}) ->
137
io_lib:format("error in parse transform '~s': ~p", [M, R]);
138
format_error({core_transform,M,R}) ->
139
io_lib:format("error in core transform '~s': ~p", [M, R]);
140
format_error({crash,Pass,Reason}) ->
141
io_lib:format("internal error in ~p;\ncrash reason: ~p", [Pass,Reason]);
142
format_error({bad_return,Pass,Reason}) ->
143
io_lib:format("internal error in ~p;\nbad return value: ~p", [Pass,Reason]).
145
%% The compile state record.
146
-record(compile, {filename="",
154
abstract_code=[], %Abstract code for debugger.
159
internal(Master, Input, Opts) ->
161
case catch internal(Input, Opts) of
168
internal({forms,Forms}, Opts) ->
169
Ps = passes(forms, Opts),
170
internal_comp(Ps, "", "", #compile{code=Forms,options=Opts});
171
internal({file,File}, Opts) ->
172
Ps = passes(file, Opts),
173
Compile = #compile{options=Opts},
174
case member(from_core, Opts) of
175
true -> internal_comp(Ps, File, ".core", Compile);
177
case member(from_beam, Opts) of
179
internal_comp(Ps, File, ".beam", Compile);
181
case member(from_asm, Opts) orelse member(asm, Opts) of
183
internal_comp(Ps, File, ".S", Compile);
185
internal_comp(Ps, File, ".erl", Compile)
190
internal_comp(Passes, File, Suffix, St0) ->
191
Dir = filename:dirname(File),
192
Base = filename:basename(File, Suffix),
193
St1 = St0#compile{filename=File, dir=Dir, base=Base,
194
ifile=erlfile(Dir, Base, Suffix),
195
ofile=objfile(Base, St0)},
196
Run = case member(time, St1#compile.options) of
198
io:format("Compiling ~p\n", [File]),
200
false -> fun({_Name,Fun}, St) -> catch Fun(St) end
202
case fold_comp(Passes, Run, St1) of
203
{ok,St2} -> comp_ret_ok(St2);
204
{error,St2} -> comp_ret_err(St2)
207
fold_comp([{Name,Test,Pass}|Ps], Run, St) ->
209
false -> %Pass is not needed.
210
fold_comp(Ps, Run, St);
211
true -> %Run pass in the usual way.
212
fold_comp([{Name,Pass}|Ps], Run, St)
214
fold_comp([{Name,Pass}|Ps], Run, St0) ->
215
case Run({Name,Pass}, St0) of
216
{ok,St1} -> fold_comp(Ps, Run, St1);
217
{error,St1} -> {error,St1};
219
Es = [{St0#compile.ifile,[{none,?MODULE,{crash,Name,Reason}}]}],
220
{error,St0#compile{errors=St0#compile.errors ++ Es}};
222
Es = [{St0#compile.ifile,[{none,?MODULE,{bad_return,Name,Other}}]}],
223
{error,St0#compile{errors=St0#compile.errors ++ Es}}
225
fold_comp([], _Run, St) -> {ok,St}.
230
Size = os:cmd("ps -o vsz -p " ++ os:getpid() ++ " | tail -1"),
231
list_to_integer(lib:nonl(Size));
236
run_tc({Name,Fun}, St) ->
237
Before0 = statistics(runtime),
238
Val = (catch Fun(St)),
239
After0 = statistics(runtime),
240
{Before_c, _} = Before0,
241
{After_c, _} = After0,
242
io:format(" ~-30s: ~10.3f s (~w k)\n",
243
[Name, (After_c-Before_c) / 1000, os_process_size()]),
246
comp_ret_ok(#compile{code=Code,warnings=Warn,module=Mod,options=Opts}=St) ->
248
Ret1 = case member(binary, Opts) andalso not member(no_code_generation, Opts) of
252
Ret2 = case member(return_warnings, Opts) of
253
true -> Ret1 ++ [Warn];
256
list_to_tuple([ok,Mod|Ret2]).
261
case member(return_errors, St#compile.options) of
262
true -> {error,St#compile.errors,St#compile.warnings};
266
%% passes(form|file, [Option]) -> [{Name,PassFun}]
267
%% Figure out which passes that need to be run.
269
passes(forms, Opts) ->
270
select_passes(standard_passes(), Opts);
271
passes(file, Opts) ->
272
case member(from_beam, Opts) of
274
Ps = [?pass(read_beam_file)|binary_passes()],
275
select_passes(Ps, Opts);
277
Ps = case member(from_asm, Opts) orelse member(asm, Opts) of
279
[?pass(beam_consult_asm)|asm_passes()];
281
case member(from_core, Opts) of
283
[?pass(parse_core)|core_passes()];
285
[?pass(parse_module)|standard_passes()]
288
Fs = select_passes(Ps, Opts),
290
%% If the last pass saves the resulting binary to a file,
291
%% insert a first pass to remove the file.
293
{save_binary,_Fun} -> [?pass(remove_file)|Fs];
298
%% select_passes([Command], Opts) -> [{Name,Function}]
299
%% Interpret the lists of commands to return a pure list of passes.
301
%% Command can be one of:
303
%% {pass,Mod} Will be expanded to a call to the external
304
%% function Mod:module(Code, Options). This
305
%% function must transform the code and return
306
%% {ok,NewCode} or {error,Term}.
307
%% Example: {pass,beam_codegen}
309
%% {Name,Fun} Name is an atom giving the name of the pass.
310
%% Fun is an 'fun' taking one argument: a compile record.
311
%% The fun should return {ok,NewCompileRecord} or
312
%% {error,NewCompileRecord}.
313
%% Note: ?pass(Name) is equvivalent to {Name,fun Name/1}.
314
%% Example: ?pass(parse_module)
316
%% {Name,Test,Fun} Like {Name,Fun} above, but the pass will be run
317
%% (and listed by the `time' option) only if Test(St)
320
%% {src_listing,Ext} Produces an Erlang source listing with the
321
%% the file extension Ext. (Ext should not contain
322
%% a period.) No more passes will be run.
324
%% {listing,Ext} Produce an listing of the terms in the internal
325
%% representation. The extension of the listing
326
%% file will be Ext. (Ext should not contain
327
%% a period.) No more passes will be run.
329
%% {done,Ext} End compilation at this point. Produce a listing
330
%% as with {listing,Ext}, unless 'binary' is
331
%% specified, in which case the current
332
%% representation of the code is returned without
333
%% creating an output file.
335
%% {iff,Flag,Cmd} If the given Flag is given in the option list,
336
%% Cmd will be interpreted as a command.
337
%% Otherwise, Cmd will be ignored.
338
%% Example: {iff,dcg,{listing,"codegen}}
340
%% {unless,Flag,Cmd} If the given Flag is NOT given in the option list,
341
%% Cmd will be interpreted as a command.
342
%% Otherwise, Cmd will be ignored.
343
%% Example: {unless,no_kernopt,{pass,sys_kernopt}}
346
select_passes([{pass,Mod}|Ps], Opts) ->
348
case catch Mod:module(St#compile.code, St#compile.options) of
350
{ok,St#compile{code=Code}};
352
{error,St#compile{errors=St#compile.errors ++ Es}}
355
[{Mod,F}|select_passes(Ps, Opts)];
356
select_passes([{src_listing,Ext}|_], _Opts) ->
357
[{listing,fun (St) -> src_listing(Ext, St) end}];
358
select_passes([{listing,Ext}|_], _Opts) ->
359
[{listing,fun (St) -> listing(Ext, St) end}];
360
select_passes([{done,Ext}|_], Opts) ->
361
select_passes([{unless,binary,{listing,Ext}}], Opts);
362
select_passes([{iff,Flag,Pass}|Ps], Opts) ->
363
select_cond(Flag, true, Pass, Ps, Opts);
364
select_passes([{unless,Flag,Pass}|Ps], Opts) ->
365
select_cond(Flag, false, Pass, Ps, Opts);
366
select_passes([{_,Fun}=P|Ps], Opts) when is_function(Fun) ->
367
[P|select_passes(Ps, Opts)];
368
select_passes([{_,Test,Fun}=P|Ps], Opts) when is_function(Test),
370
[P|select_passes(Ps, Opts)];
371
select_passes([], _Opts) ->
373
select_passes([List|Ps], Opts) when is_list(List) ->
374
case select_passes(List, Opts) of
375
[] -> select_passes(Ps, Opts);
378
{listing,_Fun} -> Nested;
379
_Other -> Nested ++ select_passes(Ps, Opts)
383
select_cond(Flag, ShouldBe, Pass, Ps, Opts) ->
384
ShouldNotBe = not ShouldBe,
385
case member(Flag, Opts) of
386
ShouldBe -> select_passes([Pass|Ps], Opts);
387
ShouldNotBe -> select_passes(Ps, Opts)
390
%% The standard passes (almost) always run.
393
[?pass(transform_module),
394
{iff,'dpp',{listing,"pp"}},
396
{iff,'P',{src_listing,"P"}},
397
{iff,'to_pp',{done,"P"}},
399
{iff,'dabstr',{listing,"abstr"}},
400
{iff,debug_info,?pass(save_abstract_code)},
402
?pass(expand_module),
403
{iff,'dexp',{listing,"expand"}},
404
{iff,'E',{src_listing,"E"}},
405
{iff,'to_exp',{done,"E"}},
407
%% Conversion to Core Erlang.
409
{iff,'dcore',{listing,"core"}},
410
{iff,'to_core0',{done,"core"}}
414
%% Optimization and transforms of Core Erlang code.
416
[{core_old_inliner,fun test_old_inliner/1,fun core_old_inliner/1},
417
?pass(core_fold_module),
418
{core_inline_module,fun test_core_inliner/1,fun core_inline_module/1},
419
{core_fold_after_inline,fun test_core_inliner/1,fun core_fold_module/1},
420
?pass(core_transforms)]},
421
{iff,dcopt,{listing,"copt"}},
422
{iff,'to_core',{done,"core"}}
426
%% Destructive setelement/3 optimization and core lint.
427
[?pass(core_dsetel_module),
428
{iff,clint,?pass(core_lint_module)},
429
{iff,core,?pass(save_core_code)},
431
%% Kernel Erlang and code generation.
432
?pass(kernel_module),
433
{iff,dkern,{listing,"kernel"}},
434
{iff,'to_kernel',{done,"kernel"}},
436
{iff,dlife,{listing,"life"}},
438
{iff,dcg,{listing,"codegen"}}
442
%% Assembly level optimisations.
445
{iff,dblk,{listing,"block"}},
446
{unless,no_bopt,{pass,beam_bool}},
447
{iff,dbool,{listing,"bool"}},
448
{unless,no_topt,{pass,beam_type}},
449
{iff,dtype,{listing,"type"}},
450
{pass,beam_dead}, %Must always run since it splits blocks.
451
{iff,ddead,{listing,"dead"}},
452
{unless,no_jopt,{pass,beam_jump}},
453
{iff,djmp,{listing,"jump"}},
455
{iff,dclean,{listing,"clean"}},
456
{pass,beam_flatten}]},
458
%% If post optimizations are turned off, we still coalesce
459
%% adjacent labels and remove unused labels to keep the
460
%% HiPE compiler happy.
462
[?pass(beam_unused_labels),
465
{iff,dopt,{listing,"optimize"}},
466
{iff,'S',{listing,"S"}},
467
{iff,'to_asm',{done,"S"}},
469
{pass,beam_validator},
474
[{native_compile,fun test_native/1,fun native_compile/1},
475
{unless,binary,?pass(save_binary)}].
481
%% Remove the target file so we don't have an old one if the compilation fail.
483
file:delete(St#compile.ofile),
486
-record(asm_module, {module,
494
preprocess_asm_forms(Forms) ->
496
R1 = collect_asm(Forms, R),
497
{R1#asm_module.module,
498
{R1#asm_module.module,
499
R1#asm_module.exports,
500
R1#asm_module.attributes,
501
R1#asm_module.functions,
502
R1#asm_module.labels}}.
504
collect_asm([], R) ->
505
case R#asm_module.cfun of
509
R#asm_module{functions=R#asm_module.functions++
510
[{function,A,B,C,R#asm_module.code}]}
512
collect_asm([{module,M} | Rest], R) ->
513
collect_asm(Rest, R#asm_module{module=M});
514
collect_asm([{exports,M} | Rest], R) ->
515
collect_asm(Rest, R#asm_module{exports=M});
516
collect_asm([{labels,M} | Rest], R) ->
517
collect_asm(Rest, R#asm_module{labels=M});
518
collect_asm([{function,A,B,C} | Rest], R) ->
519
R1 = case R#asm_module.cfun of
523
R#asm_module{functions=R#asm_module.functions++
524
[{function,A0,B0,C0,R#asm_module.code}]}
526
collect_asm(Rest, R1#asm_module{cfun={A,B,C}, code=[]});
527
collect_asm([{attributes, Attr} | Rest], R) ->
528
collect_asm(Rest, R#asm_module{attributes=Attr});
529
collect_asm([X | Rest], R) ->
530
collect_asm(Rest, R#asm_module{code=R#asm_module.code++[X]}).
532
beam_consult_asm(St) ->
533
case file:consult(St#compile.ifile) of
535
{Module, Forms} = preprocess_asm_forms(Forms0),
536
{ok,St#compile{module=Module, code=Forms}};
538
Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
539
{error,St#compile{errors=St#compile.errors ++ Es}}
542
read_beam_file(St) ->
543
case file:read_file(St#compile.ifile) of
545
Infile = St#compile.ifile,
546
case is_too_old(Infile) of
548
{ok,St#compile{module=none,code=none}};
550
Mod0 = filename:rootname(filename:basename(Infile)),
551
Mod = list_to_atom(Mod0),
552
{ok,St#compile{module=Mod,code=Beam,ofile=Infile}}
555
Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
556
{error,St#compile{errors=St#compile.errors ++ Es}}
559
is_too_old(BeamFile) ->
560
case beam_lib:chunks(BeamFile, ["CInf"]) of
561
{ok,{_,[{"CInf",Term0}]}} ->
562
Term = binary_to_term(Term0),
563
Opts = proplists:get_value(options, Term, []),
564
lists:member(no_new_funs, Opts);
569
Opts = St#compile.options,
571
IncludePath = [Cwd, St#compile.dir|inc_paths(Opts)],
572
Tab = ets:new(compiler__tab, [protected,named_table]),
573
ets:insert(Tab, {compiler_options,Opts}),
574
R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)),
578
{ok,St#compile{code=Forms}};
580
Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
581
{error,St#compile{errors=St#compile.errors ++ Es}}
585
case file:read_file(St#compile.ifile) of
587
case core_scan:string(binary_to_list(Bin)) of
589
case core_parse:parse(Toks) of
591
Name = (Mod#c_module.name)#c_atom.val,
592
{ok,St#compile{module=Name,code=Mod}};
594
Es = [{St#compile.ifile,[E]}],
595
{error,St#compile{errors=St#compile.errors ++ Es}}
598
Es = [{St#compile.ifile,[E]}],
599
{error,St#compile{errors=St#compile.errors ++ Es}}
602
Es = [{St#compile.ifile,[{none,compile,{open,E}}]}],
603
{error,St#compile{errors=St#compile.errors ++ Es}}
606
compile_options([{attribute,_L,compile,C}|Fs]) when is_list(C) ->
607
C ++ compile_options(Fs);
608
compile_options([{attribute,_L,compile,C}|Fs]) ->
609
[C|compile_options(Fs)];
610
compile_options([_F|Fs]) -> compile_options(Fs);
611
compile_options([]) -> [].
613
transforms(Os) -> [ M || {parse_transform,M} <- Os ].
615
transform_module(St) ->
616
%% Extract compile options from code into options field.
617
Ts = transforms(St#compile.options ++ compile_options(St#compile.code)),
618
foldl_transform(St, Ts).
620
foldl_transform(St, [T|Ts]) ->
621
Name = "transform " ++ atom_to_list(T),
622
Fun = fun(S) -> T:parse_transform(S#compile.code, S#compile.options) end,
623
Run = case member(time, St#compile.options) of
624
true -> fun run_tc/2;
625
false -> fun({_Name,F}, S) -> catch F(S) end
627
case Run({Name, Fun}, St) of
629
{error,St#compile{warnings=St#compile.warnings ++ Ws,
630
errors=St#compile.errors ++ Es}};
632
Es = [{St#compile.ifile,[{none,compile,{parse_transform,T,R}}]}],
633
{error,St#compile{errors=St#compile.errors ++ Es}};
635
foldl_transform(St#compile{code=Forms}, Ts)
637
foldl_transform(St, []) -> {ok,St}.
639
get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts].
641
core_transforms(St) ->
642
%% The options field holds the complete list of options at this
644
Ts = get_core_transforms(St#compile.options),
645
foldl_core_transforms(St, Ts).
647
foldl_core_transforms(St, [T|Ts]) ->
648
Name = "core transform " ++ atom_to_list(T),
649
Fun = fun(S) -> T:core_transform(S#compile.code, S#compile.options) end,
650
Run = case member(time, St#compile.options) of
651
true -> fun run_tc/2;
652
false -> fun({_Name,F}, S) -> catch F(S) end
654
case Run({Name, Fun}, St) of
656
Es = [{St#compile.ifile,[{none,compile,{core_transform,T,R}}]}],
657
{error,St#compile{errors=St#compile.errors ++ Es}};
659
foldl_core_transforms(St#compile{code=Forms}, Ts)
661
foldl_core_transforms(St, []) -> {ok,St}.
663
%%% Fetches the module name from a list of forms. The module attribute must
665
get_module([{attribute,_,module,{M,_As}} | _]) -> M;
666
get_module([{attribute,_,module,M} | _]) -> M;
667
get_module([_ | Rest]) ->
670
%%% A #compile state is returned, where St.base has been filled in
671
%%% with the module name from Forms, as a string, in case it wasn't
672
%%% set in St (i.e., it was "").
673
add_default_base(St, Forms) ->
674
F = St#compile.filename,
677
M = get_module(Forms),
678
St#compile{base = atom_to_list(M)};
684
case erl_lint:module(St#compile.code,
685
St#compile.ifile, St#compile.options) of
687
%% Insert name of module as base name, if needed. This is
688
%% for compile:forms to work with listing files.
689
St1 = add_default_base(St, St#compile.code),
690
{ok,St1#compile{warnings=St1#compile.warnings ++ Ws}};
692
{error,St#compile{warnings=St#compile.warnings ++ Ws,
693
errors=St#compile.errors ++ Es}}
696
core_lint_module(St) ->
697
case core_lint:module(St#compile.code, St#compile.options) of
699
{ok,St#compile{warnings=St#compile.warnings ++ Ws}};
701
{error,St#compile{warnings=St#compile.warnings ++ Ws,
702
errors=St#compile.errors ++ Es}}
705
%% expand_module(State) -> State'
706
%% Do the common preprocessing of the input forms.
708
expand_module(#compile{code=Code,options=Opts0}=St0) ->
709
{Mod,Exp,Forms,Opts1} = sys_pre_expand:module(Code, Opts0),
710
Opts2 = expand_opts(Opts1),
711
Opts = filter_opts(Opts2),
712
{ok,St0#compile{module=Mod,options=Opts,code={Mod,Exp,Forms}}}.
714
core_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
715
{ok,Code,Ws} = v3_core:module(Code0, Opts),
716
{ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
718
core_fold_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
719
{ok,Code,Ws} = sys_core_fold:module(Code0, Opts),
720
{ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
722
test_old_inliner(#compile{options=Opts}) ->
723
%% The point of this test is to avoid loading the old inliner
724
%% if we know that it will not be used.
725
case any(fun(no_inline) -> true;
730
any(fun({inline,_}) -> true;
735
test_core_inliner(#compile{options=Opts}) ->
736
case any(fun(no_inline) -> true;
741
any(fun(inline) -> true;
746
core_old_inliner(#compile{code=Code0,options=Opts}=St) ->
747
case catch sys_core_inline:module(Code0, Opts) of
749
{ok,St#compile{code=Code}};
751
{error,St#compile{errors=St#compile.errors ++ Es}}
754
core_inline_module(#compile{code=Code0,options=Opts}=St) ->
755
Code = cerl_inline:core_transform(Code0, Opts),
756
{ok,St#compile{code=Code}}.
758
core_dsetel_module(#compile{code=Code0,options=Opts}=St) ->
759
{ok,Code} = sys_core_dsetel:module(Code0, Opts),
760
{ok,St#compile{code=Code}}.
762
kernel_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
763
{ok,Code,Ws} = v3_kernel:module(Code0, Opts),
764
{ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
766
save_abstract_code(St) ->
767
{ok,St#compile{abstract_code=abstract_code(St)}}.
769
abstract_code(#compile{code=Code}) ->
770
Abstr = {raw_abstract_v1,Code},
771
case catch erlang:term_to_binary(Abstr, [compressed]) of
772
{'EXIT',_} -> term_to_binary(Abstr);
776
save_core_code(St) ->
777
{ok,St#compile{core_code=cerl:from_records(St#compile.code)}}.
779
beam_unused_labels(#compile{code=Code0}=St) ->
780
Code = beam_jump:module_labels(Code0),
781
{ok,St#compile{code=Code}}.
783
beam_asm(#compile{ifile=File,code=Code0,abstract_code=Abst,options=Opts0}=St) ->
784
Source = filename:absname(File),
785
Opts = filter(fun is_informative_option/1, Opts0),
786
case beam_asm:module(Code0, Abst, Source, Opts) of
787
{ok,Code} -> {ok,St#compile{code=Code,abstract_code=[]}};
788
{error,Es} -> {error,St#compile{errors=St#compile.errors ++ Es}}
791
test_native(#compile{options=Opts}) ->
792
%% This test must be made late, because the r7 or no_new_funs options
793
%% will turn off the native option.
794
member(native, Opts).
796
native_compile(#compile{code=none}=St) -> {ok,St};
797
native_compile(St) ->
798
case erlang:system_info(hipe_architecture) of
800
Ws = [{St#compile.ifile,[{none,compile,no_native_support}]}],
801
{ok,St#compile{warnings=St#compile.warnings ++ Ws}};
806
native_compile_1(St) ->
807
Opts0 = [no_new_binaries|St#compile.options],
808
IgnoreErrors = member(ignore_native_errors, Opts0),
809
Opts = case keysearch(hipe, 1, Opts0) of
810
{value,{hipe,L}} when list(L) -> L;
811
{value,{hipe,X}} -> [X];
814
case catch hipe:compile(St#compile.module,
815
St#compile.core_code,
818
{ok, {Type,Bin}} when binary(Bin) ->
819
{ok, embed_native_code(St, {Type,Bin})};
823
Ws = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
824
{ok,St#compile{warnings=St#compile.warnings ++ Ws}};
826
Es = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
827
{error,St#compile{errors=St#compile.errors ++ Es}}
832
Ws = [{St#compile.ifile,[{none,?MODULE,{native_crash,R}}]}],
833
{ok,St#compile{warnings=St#compile.warnings ++ Ws}};
839
embed_native_code(St, {Architecture,NativeCode}) ->
840
{ok, _, Chunks0} = beam_lib:all_chunks(St#compile.code),
841
ChunkName = hipe_unified_loader:chunk_name(Architecture),
842
Chunks1 = lists:keydelete(ChunkName, 1, Chunks0),
843
Chunks = Chunks1 ++ [{ChunkName,NativeCode}],
844
{ok, BeamPlusNative} = beam_lib:build_module(Chunks),
845
St#compile{code=BeamPlusNative}.
847
%% Returns true if the option is informative and therefore should be included
848
%% in the option list of the compiled module.
850
is_informative_option(beam) -> false;
851
is_informative_option(report_warnings) -> false;
852
is_informative_option(report_errors) -> false;
853
is_informative_option(binary) -> false;
854
is_informative_option(verbose) -> false;
855
is_informative_option(_) -> true.
857
save_binary(#compile{code=none}=St) -> {ok,St};
859
Tfile = tmpfile(St#compile.ofile), %Temp working file
860
case write_binary(Tfile, St#compile.code, St) of
862
case file:rename(Tfile, St#compile.ofile) of
867
Es = [{St#compile.ofile,[{none,?MODULE,{rename,Tfile}}]}],
868
{error,St#compile{errors=St#compile.errors ++ Es}}
871
Es = [{Tfile,[{compile,write_error}]}],
872
{error,St#compile{errors=St#compile.errors ++ Es}}
875
write_binary(Name, Bin, St) ->
876
Opts = case member(compressed, St#compile.options) of
877
true -> [compressed];
880
case file:write_file(Name, Bin, Opts) of
882
{error,_}=Error -> Error
885
%% report_errors(State) -> ok
886
%% report_warnings(State) -> ok
889
case member(report_errors, St#compile.options) of
891
foreach(fun ({{F,_L},Eds}) -> list_errors(F, Eds);
892
({F,Eds}) -> list_errors(F, Eds) end,
897
report_warnings(#compile{options=Opts,warnings=Ws0}) ->
898
case member(report_warnings, Opts) of
900
Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, Eds);
901
({F,Eds}) -> format_message(F, Eds) end,
903
Ws = ordsets:from_list(Ws1),
904
foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws);
908
format_message(F, [{Line,Mod,E}|Es]) ->
909
M = {Line,io_lib:format("~s:~w: Warning: ~s\n", [F,Line,Mod:format_error(E)])},
910
[M|format_message(F, Es)];
911
format_message(F, [{Mod,E}|Es]) ->
912
M = {none,io_lib:format("~s: Warning: ~s\n", [F,Mod:format_error(E)])},
913
[M|format_message(F, Es)];
914
format_message(_, []) -> [].
916
%% list_errors(File, ErrorDescriptors) -> ok
918
list_errors(F, [{Line,Mod,E}|Es]) ->
919
io:fwrite("~s:~w: ~s\n", [F,Line,Mod:format_error(E)]),
921
list_errors(F, [{Mod,E}|Es]) ->
922
io:fwrite("~s: ~s\n", [F,Mod:format_error(E)]),
924
list_errors(_F, []) -> ok.
926
%% erlfile(Dir, Base) -> ErlFile
927
%% outfile(Base, Extension, Options) -> OutputFile
928
%% objfile(Base, Target, Options) -> ObjFile
929
%% tmpfile(ObjFile) -> TmpFile
930
%% Work out the correct input and output file names.
932
iofile(File) when atom(File) ->
933
iofile(atom_to_list(File));
935
{filename:dirname(File), filename:basename(File, ".erl")}.
937
erlfile(Dir, Base, Suffix) ->
938
filename:join(Dir, Base++Suffix).
940
outfile(Base, Ext, Opts) when atom(Ext) ->
941
outfile(Base, atom_to_list(Ext), Opts);
942
outfile(Base, Ext, Opts) ->
943
Obase = case keysearch(outdir, 1, Opts) of
944
{value, {outdir, Odir}} -> filename:join(Odir, Base);
945
_Other -> Base % Not found or bad format
950
outfile(Base, "beam", St#compile.options).
953
reverse([$#|tl(reverse(Ofile))]).
956
%% inc_paths(Options)
957
%% Extract the predefined macros and include paths from the option list.
959
pre_defs([{d,M,V}|Opts]) ->
960
[{M,V}|pre_defs(Opts)];
961
pre_defs([{d,M}|Opts]) ->
963
pre_defs([_|Opts]) ->
968
[ P || {i,P} <- Opts, list(P) ].
970
src_listing(Ext, St) ->
971
listing(fun (Lf, {_Mod,_Exp,Fs}) -> do_src_listing(Lf, Fs);
972
(Lf, Fs) -> do_src_listing(Lf, Fs) end,
975
do_src_listing(Lf, Fs) ->
976
foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F),"\n"]) end,
980
listing(fun(Lf, Fs) -> beam_listing:module(Lf, Fs) end, Ext, St).
982
listing(LFun, Ext, St) ->
983
Lfile = outfile(St#compile.base, Ext, St#compile.options),
984
case file:open(Lfile, [write,delayed_write]) of
986
LFun(Lf, St#compile.code),
990
Es = [{Lfile,[{none,compile,write_error}]}],
991
{error,St#compile{errors=St#compile.errors ++ Es}}
995
help(standard_passes()).
997
help([{iff,Flag,{src_listing,Ext}}|T]) ->
998
io:fwrite("~p - Generate .~s source listing file\n", [Flag,Ext]),
1000
help([{iff,Flag,{listing,Ext}}|T]) ->
1001
io:fwrite("~p - Generate .~s file\n", [Flag,Ext]),
1003
help([{iff,Flag,{Name,Fun}}|T]) when function(Fun) ->
1004
io:fwrite("~p - Run ~s\n", [Flag,Name]),
1006
help([{iff,_Flag,Action}|T]) ->
1009
help([{unless,Flag,{pass,Pass}}|T]) ->
1010
io:fwrite("~p - Skip the ~s pass\n", [Flag,Pass]),
1012
help([{unless,no_postopt=Flag,List}|T]) when list(List) ->
1013
%% Hard-coded knowledgde here.
1014
io:fwrite("~p - Skip all post optimisation\n", [Flag]),
1017
help([{unless,_Flag,Action}|T]) ->
1026
%% compile(AbsFileName, Outfilename, Options)
1027
%% Compile entry point for erl_compile.
1029
compile(File0, _OutFile, Options) ->
1030
File = shorten_filename(File0),
1031
case file(File, make_erl_options(Options)) of
1036
compile_beam(File0, _OutFile, Opts) ->
1037
File = shorten_filename(File0),
1038
case file(File, [from_beam|make_erl_options(Opts)]) of
1043
compile_asm(File0, _OutFile, Opts) ->
1044
File = shorten_filename(File0),
1045
case file(File, [asm|make_erl_options(Opts)]) of
1050
compile_core(File0, _OutFile, Opts) ->
1051
File = shorten_filename(File0),
1052
case file(File, [from_core|make_erl_options(Opts)]) of
1057
shorten_filename(Name0) ->
1058
{ok,Cwd} = file:get_cwd(),
1059
case lists:prefix(Cwd, Name0) of
1062
Name = case lists:nthtail(length(Cwd), Name0) of
1069
%% Converts generic compiler options to specific options.
1071
make_erl_options(Opts) ->
1073
%% This way of extracting will work even if the record passed
1074
%% has more fields than known during compilation.
1076
Includes = Opts#options.includes,
1077
Defines = Opts#options.defines,
1078
Outdir = Opts#options.outdir,
1079
Warning = Opts#options.warning,
1080
Verbose = Opts#options.verbose,
1081
Specific = Opts#options.specific,
1082
OutputType = Opts#options.output_type,
1083
Cwd = Opts#options.cwd,
1092
_ -> [report_warnings]
1095
fun ({Name, Value}) ->
1108
Options++[report_errors, {cwd, Cwd}, {outdir, Outdir}|
1109
map(fun(Dir) -> {i, Dir} end, Includes)]++Specific.