From 042b9ae568fd4d00f2eeed89ae117e898593070d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 24 Nov 2011 14:51:01 +0100 Subject: hipe: Teach hipe to handle slim or stripped BEAM files --- lib/compiler/test/compile_SUITE.erl | 10 ++++++++-- lib/hipe/main/hipe.erl | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 8c6a623dfb..e7d5d9a4c0 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -77,10 +77,16 @@ file_1(Config) when is_list(Config) -> ?line {Simple, Target} = files(Config, "file_1"), ?line {ok, Cwd} = file:get_cwd(), ?line ok = file:set_cwd(filename:dirname(Target)), - ?line {ok,simple} = compile:file(Simple), %Smoke test only. + + %% Native from BEAM without compilation info. ?line {ok,simple} = compile:file(Simple, [slim]), %Smoke test only. - ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test. ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. + + %% Native from BEAM with compilation info. + ?line {ok,simple} = compile:file(Simple), %Smoke test only. + ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. + + ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test. ?line {ok,simple} = compile:file(Simple, [debug_info]), ?line {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage ?line ok = file:set_cwd(Cwd), diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 570e4d9d17..263d2e61a9 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -602,9 +602,13 @@ file(File, Options) when is_atom(File) -> disasm(File) -> case beam_disasm:file(File) of #beam_file{labeled_exports = LabeledExports, - compile_info = CompInfo, + compile_info = CompInfo0, code = BeamCode} -> - {options, CompOpts} = lists:keyfind(options, 1, CompInfo), + CompInfo = case CompInfo0 of + none -> []; + _ -> CompInfo0 + end, + CompOpts = proplists:get_value(options, CompInfo, []), HCompOpts = case lists:keyfind(hipe, 1, CompOpts) of {hipe, L} when is_list(L) -> L; {hipe, X} -> [X]; -- cgit v1.2.3 From 70e44417259e47cc1b170f8c6758771c626ddc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 9 Sep 2011 10:22:40 +0200 Subject: compiler: Don't include source code options in module_info(compile) As far as I know, the purpose of the compiler options included in Mod:module_info(compile) has never been documented. An educated guess is that they are there in case you want to re-compile the module with the same options, and also to aid in debugging when you need to know how a module was compiled. In neither case is there any need to include options given in the source itself in options included in Mod:module_info(compile). Including those options will only waste memory. Therefore, only include in the BEAM file the options that were given to compile:file/2. --- lib/compiler/src/compile.erl | 11 +++++++---- lib/compiler/test/compile_SUITE.erl | 25 ++++++++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index bfa7c6cedd..e737ead023 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -235,7 +235,8 @@ format_error({module_name,Mod,Filename}) -> code=[], core_code=[], abstract_code=[], %Abstract code for debugger. - options=[] :: [option()], + options=[] :: [option()], %Options for compilation + mod_options=[] :: [option()], %Options for module_info errors=[], warnings=[]}). @@ -246,10 +247,11 @@ internal(Master, Input, Opts) -> internal({forms,Forms}, Opts) -> {_,Ps} = passes(forms, Opts), - internal_comp(Ps, "", "", #compile{code=Forms,options=Opts}); + internal_comp(Ps, "", "", #compile{code=Forms,options=Opts, + mod_options=Opts}); internal({file,File}, Opts) -> {Ext,Ps} = passes(file, Opts), - Compile = #compile{options=Opts}, + Compile = #compile{options=Opts,mod_options=Opts}, internal_comp(Ps, File, Ext, Compile). internal_comp(Passes, File, Suffix, St0) -> @@ -1228,7 +1230,8 @@ beam_unused_labels(#compile{code=Code0}=St) -> Code = beam_jump:module_labels(Code0), {ok,St#compile{code=Code}}. -beam_asm(#compile{ifile=File,code=Code0,abstract_code=Abst,options=Opts0}=St) -> +beam_asm(#compile{ifile=File,code=Code0, + abstract_code=Abst,mod_options=Opts0}=St) -> Source = filename:absname(File), Opts1 = lists:map(fun({debug_info_key,_}) -> {debug_info_key,'********'}; (Other) -> Other diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index e7d5d9a4c0..fedbd98f71 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -87,8 +87,12 @@ file_1(Config) when is_list(Config) -> ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test. - ?line {ok,simple} = compile:file(Simple, [debug_info]), + + ?line compile_and_verify(Simple, Target, []), + ?line compile_and_verify(Simple, Target, [native]), + ?line compile_and_verify(Simple, Target, [debug_info]), ?line {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage + ?line ok = file:set_cwd(Cwd), ?line true = exists(Target), ?line passed = run(Target, test, []), @@ -119,10 +123,9 @@ big_file(Config) when is_list(Config) -> ?line Big = filename:join(DataDir, "big.erl"), ?line Target = filename:join(PrivDir, "big.beam"), ?line ok = file:set_cwd(PrivDir), - ?line {ok,big} = compile:file(Big, []), - ?line {ok,big} = compile:file(Big, [r9,debug_info]), - ?line {ok,big} = compile:file(Big, [no_postopt]), - ?line true = exists(Target), + ?line compile_and_verify(Big, Target, []), + ?line compile_and_verify(Big, Target, [debug_info]), + ?line compile_and_verify(Big, Target, [no_postopt]), %% Cleanup. ?line ok = file:delete(Target), @@ -781,3 +784,15 @@ do_asm(Beam, Outdir) -> [M,Class,Error,erlang:get_stacktrace()]), error end. + +%%% +%%% Utilities. +%%% + +compile_and_verify(Name, Target, Opts) -> + Mod = list_to_atom(filename:basename(Name, ".erl")), + {ok,Mod} = compile:file(Name, Opts), + {ok,{Mod,[{compile_info,CInfo}]}} = + beam_lib:chunks(Target, [compile_info]), + {options,BeamOpts} = lists:keyfind(options, 1, CInfo), + Opts = BeamOpts. -- cgit v1.2.3 From 02c4d9a4a08ebb511833539e3937593fb956a6c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 9 Sep 2011 12:09:29 +0200 Subject: compiler: Don't include {cwd,_} in module_info(compile) The {cwd,Dir} option is always included if the module has been compiled by erlc. Since its presence cannot be relied upon and it wastes memory, get rid of it. --- lib/compiler/src/compile.erl | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index e737ead023..1d07672d81 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -1236,7 +1236,7 @@ beam_asm(#compile{ifile=File,code=Code0, Opts1 = lists:map(fun({debug_info_key,_}) -> {debug_info_key,'********'}; (Other) -> Other end, Opts0), - Opts2 = [O || O <- Opts1, is_informative_option(O)], + Opts2 = [O || O <- Opts1, effects_code_generation(O)], case beam_asm:module(Code0, Abst, Source, Opts2) of {ok,Code} -> {ok,St#compile{code=Code,abstract_code=[]}} end. @@ -1306,15 +1306,23 @@ embed_native_code(St, {Architecture,NativeCode}) -> {ok, BeamPlusNative} = beam_lib:build_module(Chunks), St#compile{code=BeamPlusNative}. -%% Returns true if the option is informative and therefore should be included -%% in the option list of the compiled module. - -is_informative_option(beam) -> false; -is_informative_option(report_warnings) -> false; -is_informative_option(report_errors) -> false; -is_informative_option(binary) -> false; -is_informative_option(verbose) -> false; -is_informative_option(_) -> true. +%% effects_code_generation(Option) -> true|false. +%% Determine whether the option could have any effect on the +%% generated code in the BEAM file (as opposed to how +%% errors will be reported). + +effects_code_generation(Option) -> + case Option of + beam -> false; + report_warnings -> false; + report_errors -> false; + return_errors-> false; + return_warnings-> false; + binary -> false; + verbose -> false; + {cwd,_} -> false; + _ -> true + end. save_binary(#compile{code=none}=St) -> {ok,St}; save_binary(#compile{module=Mod,ofile=Outfile, -- cgit v1.2.3 From 04d1fc553183c020bee29db6d3e2af8dc5b7053a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 5 Sep 2011 09:17:14 +0200 Subject: filename.erl:filter_options/1: Remove handling of dead options The 'trace' and 'fast' options are no longer supported. While at it, correct the comment about option filtering. --- lib/stdlib/src/filename.erl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 2fc9128e4e..acd7985c16 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -844,8 +844,7 @@ try_file(Src, _ObjFilename, Mod, _Rules) -> %% Filters the options. %% -%% 1) Remove options that have no effect on the generated code, -%% such as report and verbose. +%% 1) Only keep options that have any effect on code generation. %% %% 2) The paths found in {i, Path} and {outdir, Path} are converted %% to absolute paths. When doing this, it is assumed that relatives @@ -857,14 +856,10 @@ filter_options(Base, [{outdir, Path}|Rest], Result) -> filter_options(Base, Rest, [{outdir, make_abs_path(Base, Path)}|Result]); filter_options(Base, [{i, Path}|Rest], Result) -> filter_options(Base, Rest, [{i, make_abs_path(Base, Path)}|Result]); -filter_options(Base, [Option|Rest], Result) when Option =:= trace -> - filter_options(Base, Rest, [Option|Result]); filter_options(Base, [Option|Rest], Result) when Option =:= export_all -> filter_options(Base, Rest, [Option|Result]); filter_options(Base, [Option|Rest], Result) when Option =:= binary -> filter_options(Base, Rest, [Option|Result]); -filter_options(Base, [Option|Rest], Result) when Option =:= fast -> - filter_options(Base, Rest, [Option|Result]); filter_options(Base, [Tuple|Rest], Result) when element(1, Tuple) =:= d -> filter_options(Base, Rest, [Tuple|Result]); filter_options(Base, [Tuple|Rest], Result) -- cgit v1.2.3 From bc1f3ce3b707f25397a1ff484d34ee406e0db73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 5 Sep 2011 09:21:11 +0200 Subject: filename: Eliminate failing call to Mod:module_info(source_file) Mod:module_info(source_file) is no longer supported (and have not been for a long time), so calling it will always fail. --- lib/stdlib/src/filename.erl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index acd7985c16..7144781843 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -873,12 +873,7 @@ filter_options(_Base, [], Result) -> %% Gets the source file given path of object code and module name. get_source_file(Obj, Mod, Rules) -> - case catch Mod:module_info(source_file) of - {'EXIT', _Reason} -> - source_by_rules(dirname(Obj), packages:last(Mod), Rules); - File -> - {ok, File} - end. + source_by_rules(dirname(Obj), packages:last(Mod), Rules). source_by_rules(Dir, Base, [{From, To}|Rest]) -> case try_rule(Dir, Base, From, To) of -- cgit v1.2.3 From f939cf61d13fe2d753f4c6ec7a47880db083a45f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 11 Nov 2011 16:36:45 +0100 Subject: Teach filename:find_src/1,2 to handle slim or stripped BEAM files filename:find_src/1,2 will crash when asked to find the source corresponding to a BEAM with no compilation options. A BEAM file can be missing compilation options if it has been stripped using beam_lib:strip/1 or compiled using the undocumented 'slim' option. Why this matters: If ERL_COMPILE_OPTIONS is set to +slim before building Erlang/OTP, there will be a crash in 'igor' during the building of the public_key application. ('igor' merges several source code files, and uses filename:find_src/1,2 to find the source code.) Change filename:find_src/1,2 to return an empty option list if there are no options in the BEAM file. Noticed-by: Per Hedeland --- lib/stdlib/src/filename.erl | 7 +++++-- lib/stdlib/test/filename_SUITE.erl | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 7144781843..dbfcbea4f7 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -836,8 +836,11 @@ try_file(undefined, ObjFilename, Mod, Rules) -> Error -> Error end; try_file(Src, _ObjFilename, Mod, _Rules) -> - List = Mod:module_info(compile), - {options, Options} = lists:keyfind(options, 1, List), + List = case Mod:module_info(compile) of + none -> []; + List0 -> List0 + end, + Options = proplists:get_value(options, List, []), {ok, Cwd} = file:get_cwd(), AbsPath = make_abs_path(Cwd, Src), {AbsPath, filter_options(dirname(AbsPath), Options, [])}. diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl index 70b0d413dc..4cfa589660 100644 --- a/lib/stdlib/test/filename_SUITE.erl +++ b/lib/stdlib/test/filename_SUITE.erl @@ -483,6 +483,22 @@ find_src(Config) when is_list(Config) -> %% Try to find the source for a preloaded module. ?line {error,{preloaded,init}} = filename:find_src(init), + + %% Make sure that find_src works for a slim BEAM file. + OldPath = code:get_path(), + try + PrivDir = ?config(priv_dir, Config), + code:add_patha(PrivDir), + Src = "simple", + SrcPath = filename:join(PrivDir, Src) ++ ".erl", + SrcContents = "-module(simple).\n", + ok = file:write_file(SrcPath, SrcContents), + {ok,simple} = compile:file(SrcPath, [slim,{outdir,PrivDir}]), + BeamPath = filename:join(PrivDir, Src), + {BeamPath,[]} = filename:find_src(simple) + after + code:set_path(OldPath) + end, ok. %% -- cgit v1.2.3 From 9ac7e19e35b02c02e15abd3abc4e7b5c8b62752d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 11 Nov 2011 16:57:10 +0100 Subject: filename documentation: Recommend against using filename:find_src/1,2 --- lib/stdlib/doc/src/filename.xml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml index bc3a616d39..9296319b83 100644 --- a/lib/stdlib/doc/src/filename.xml +++ b/lib/stdlib/doc/src/filename.xml @@ -295,6 +295,12 @@

Finds the source filename and compiler options for a module. The result can be fed to compile:file/2 in order to compile the file again.

+ +

We don't recommend using this function. If possible, + use beam_lib(3) to extract + the abstract code format from the BEAM file and compile that + instead.

+

The Beam argument, which can be a string or an atom, specifies either the module name or the path to the source code, with or without the ".erl" extension. In either -- cgit v1.2.3