diff options
-rw-r--r-- | erts/emulator/test/binary_SUITE.erl | 2 | ||||
-rw-r--r-- | erts/test/otp_SUITE.erl | 80 | ||||
-rw-r--r-- | lib/common_test/src/ct_netconfc.erl | 10 | ||||
-rw-r--r-- | lib/diameter/src/Makefile | 5 | ||||
-rw-r--r-- | lib/diameter/src/app.sed | 40 | ||||
-rw-r--r-- | lib/diameter/src/diameter.app.src | 19 | ||||
-rw-r--r-- | lib/diameter/test/diameter_app_SUITE.erl | 66 | ||||
-rw-r--r-- | lib/hipe/llvm/hipe_llvm_main.erl | 30 | ||||
-rw-r--r-- | lib/hipe/llvm/hipe_rtl_to_llvm.erl | 9 | ||||
-rw-r--r-- | lib/hipe/main/hipe.erl | 32 |
10 files changed, 225 insertions, 68 deletions
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 5da69c2cab..7aba367e33 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -1266,7 +1266,7 @@ deep(Config) when is_list(Config) -> deep_roundtrip(T) -> B = term_to_binary(T), - T = binary_to_term_stress(B). + T = binary_to_term(B). obsolete_funs(Config) when is_list(Config) -> erts_debug:set_internal_state(available_internal_state, true), diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index cd5cfcbab4..229d10ccee 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -392,12 +392,18 @@ is_bad_encoding(File) -> end. runtime_dependencies(Config) -> + %% Ignore applications intentionally not declaring dependencies + %% found by xref. + IgnoreApps = [diameter], + + %% Verify that (at least) OTP application runtime dependencies found %% by xref are listed in the runtime_dependencies field of the .app file %% of each application. Server = ?config(xref_server, Config), {ok, AE} = xref:q(Server, "AE"), SAE = lists:keysort(1, AE), + put(ignored_failures, []), {AppDep, AppDeps} = lists:foldl(fun ({App, App}, Acc) -> Acc; ({App, Dep}, {undefined, []}) -> @@ -409,8 +415,45 @@ runtime_dependencies(Config) -> end, {undefined, []}, SAE), - [] = check_apps_deps([AppDep|AppDeps]), - ok. + [] = lists:filter(fun ({missing_runtime_dependency, + AppFile, + common_test}) -> + %% The test_server app is contaminated by + %% common_test when run in a source tree. It + %% should however *not* be contaminated + %% when run in an installation. + case {filename:basename(AppFile), + is_run_in_src_tree()} of + {"test_server.app", true} -> + false; + _ -> + true + end; + (_) -> + true + end, + check_apps_deps([AppDep|AppDeps], IgnoreApps)), + case IgnoreApps of + [] -> + ok; + _ -> + Comment = lists:flatten(io_lib:format("Ignored applications: ~p " + "Ignored failures: ~p", + [IgnoreApps, + get(ignored_failures)])), + {comment, Comment} + end. + +is_run_in_src_tree() -> + %% At least currently run_erl is not present in <code-root>/bin + %% in the source tree, but present in <code-root>/bin of an + %% ordinary installation. + case file:read_file_info(filename:join([code:root_dir(), + "bin", + "run_erl"])) of + {ok, _} -> false; + {error, _} -> true + end. have_rdep(_App, [], _Dep) -> false; @@ -424,28 +467,43 @@ have_rdep(App, [RDep | RDeps], Dep) -> have_rdep(App, RDeps, Dep) end. -check_app_deps(_App, _AppFile, _AFDeps, []) -> +check_app_deps(_App, _AppFile, _AFDeps, [], _IgnoreApps) -> []; -check_app_deps(App, AppFile, AFDeps, [XRDep | XRDeps]) -> - ResOtherDeps = check_app_deps(App, AppFile, AFDeps, XRDeps), +check_app_deps(App, AppFile, AFDeps, [XRDep | XRDeps], IgnoreApps) -> + ResOtherDeps = check_app_deps(App, AppFile, AFDeps, XRDeps, IgnoreApps), case have_rdep(App, AFDeps, XRDep) of true -> ResOtherDeps; false -> - [{missing_runtime_dependency, AppFile, XRDep} | ResOtherDeps] + Failure = {missing_runtime_dependency, AppFile, XRDep}, + case lists:member(App, IgnoreApps) of + true -> + put(ignored_failures, [Failure | get(ignored_failures)]), + ResOtherDeps; + false -> + [Failure | ResOtherDeps] + end end. -check_apps_deps([]) -> +check_apps_deps([], _IgnoreApps) -> []; -check_apps_deps([{App, Deps}|AppDeps]) -> - ResOtherApps = check_apps_deps(AppDeps), +check_apps_deps([{App, Deps}|AppDeps], IgnoreApps) -> + ResOtherApps = check_apps_deps(AppDeps, IgnoreApps), AppFile = code:where_is_file(atom_to_list(App) ++ ".app"), {ok,[{application, App, Info}]} = file:consult(AppFile), case lists:keyfind(runtime_dependencies, 1, Info) of {runtime_dependencies, RDeps} -> - check_app_deps(App, AppFile, RDeps, Deps) ++ ResOtherApps; + check_app_deps(App, AppFile, RDeps, Deps, IgnoreApps) + ++ ResOtherApps; false -> - [{missing_runtime_dependencies_key, AppFile} | ResOtherApps] + Failure = {missing_runtime_dependencies_key, AppFile}, + case lists:member(App, IgnoreApps) of + true -> + put(ignored_failures, [Failure | get(ignored_failures)]), + ResOtherApps; + false -> + [Failure | ResOtherApps] + end end. %%% diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 6fc840745d..a3861dc745 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -536,7 +536,7 @@ send(Client, SimpleXml) -> Client :: client(), SimpleXml :: simple_xml(), Timeout :: timeout(), - Result :: ok | {error,error_reason()}. + Result :: simple_xml() | {error,error_reason()}. %% @doc Send an XML document to the server. %% %% The given XML document is sent as is to the server. This function @@ -556,7 +556,7 @@ send_rpc(Client, SimpleXml) -> Client :: client(), SimpleXml :: simple_xml(), Timeout :: timeout(), - Result :: ok | {error,error_reason()}. + Result :: [simple_xml()] | {error,error_reason()}. %% @doc Send a Netconf <code>rpc</code> request to the server. %% %% The given XML document is wrapped in a valid Netconf @@ -635,7 +635,7 @@ get(Client, Filter) -> Client :: client(), Filter :: simple_xml() | xpath(), Timeout :: timeout(), - Result :: {ok,simple_xml()} | {error,error_reason()}. + Result :: {ok,[simple_xml()]} | {error,error_reason()}. %% @doc Get data. %% %% This operation returns both configuration and state data from the @@ -661,7 +661,7 @@ get_config(Client, Source, Filter) -> Source :: netconf_db(), Filter :: simple_xml() | xpath(), Timeout :: timeout(), - Result :: {ok,simple_xml()} | {error,error_reason()}. + Result :: {ok,[simple_xml()]} | {error,error_reason()}. %% @doc Get configuration data. %% %% To be able to access another source than `running', the server @@ -759,7 +759,7 @@ action(Client,Action) -> Client :: client(), Action :: simple_xml(), Timeout :: timeout(), - Result :: {ok,simple_xml()} | {error,error_reason()}. + Result :: {ok,[simple_xml()]} | {error,error_reason()}. %% @doc Execute an action. %% %% @end diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile index 127406ae23..9afccf298c 100644 --- a/lib/diameter/src/Makefile +++ b/lib/diameter/src/Makefile @@ -148,7 +148,7 @@ gen/$(DICT_YRL).erl: compiler/$(DICT_YRL).yrl $(ERLC) -Werror -o $(@D) $< # Generate the app file. -$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk +$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk app.sed $(gen_verbose) \ M=`echo $(notdir $(APP_MODULES)) | tr ' ' ,`; \ C=`echo $(COMPILER_MODULES) | tr ' ' ,`; \ @@ -159,7 +159,8 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk -e "s;%COMPILER%;$$C;" \ -e "s;%INFO%;$$I;" \ -e "s;%REGISTERED%;$$R;" \ - $< > $@ + $< \ + | sed -f app.sed > $@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk $(vsn_verbose) \ diff --git a/lib/diameter/src/app.sed b/lib/diameter/src/app.sed new file mode 100644 index 0000000000..7916f65002 --- /dev/null +++ b/lib/diameter/src/app.sed @@ -0,0 +1,40 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2014. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +# +# Generate runtime_dependencies from applications to avoid having to +# specify the same application more than once. +# + +/{runtime_dependencies,/b v +/{[-a-z]*, "[0-9.]*"}/!b +/{vsn,/b + +/%%/!H +s/{\([^,]*\)[^}]*}/\1/g +s/%%/%,/ +b + +:v + +p +x +s/\n// +s/%//g +s/\n */ /g +s/{\([^,]*\), "\([^"]*"\)}/"\1-\2/g diff --git a/lib/diameter/src/diameter.app.src b/lib/diameter/src/diameter.app.src index d2290aeccc..ac1d847753 100644 --- a/lib/diameter/src/diameter.app.src +++ b/lib/diameter/src/diameter.app.src @@ -27,13 +27,20 @@ ]}, {registered, [%REGISTERED%]}, {applications, [ - stdlib, kernel - %, syntax_tools - %, runtime_tools - %, ssl + {stdlib, "2.0"}, {kernel, "3.0"}%, {erts, "6.0"} + %% {syntax-tools, "1.6.14"} + %% {runtime-tools, "1.8.14"} + %, {ssl, "5.3.4"} ]}, {env, []}, {mod, {diameter_app, []}}, - {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.0","ssl-5.3.4", - "runtime_tools-1.8.14","kernel-3.0","erts-6.0"]} + {runtime_dependencies, [ + ]} + %% + %% Note that ssl is only required if configured on TCP transports, + %% and syntax-tools and runtime-tools are only required if the + %% dictionary compiler and debug modules (respectively) are + %% needed/wanted at runtime, which they typically aren't. These + %% modules are the two commented lines in the 'modules' tuple. + %% ]}. diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl index 1e262895a6..f68a18b5c2 100644 --- a/lib/diameter/test/diameter_app_SUITE.erl +++ b/lib/diameter/test/diameter_app_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -50,7 +50,7 @@ diameter_exprecs, diameter_make]). --define(HELP_MODULES, [diameter_dbg, +-define(INFO_MODULES, [diameter_dbg, diameter_info]). %% =========================================================================== @@ -99,13 +99,13 @@ vsn(Config) -> %% # modules/1 %% %% Ensure that the app file modules and installed modules differ by -%% compiler/help modules. +%% compiler/info modules. %% =========================================================================== modules(Config) -> Mods = fetch(modules, fetch(app, Config)), Installed = code_mods(), - Help = lists:sort(?HELP_MODULES ++ ?COMPILER_MODULES), + Help = lists:sort(?INFO_MODULES ++ ?COMPILER_MODULES), {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}. @@ -158,12 +158,15 @@ appvsn(Name) -> %% # xref/1 %% %% Ensure that no function in our application calls an undefined function -%% or one in an application we haven't specified as a dependency. (Almost.) +%% or one in an application we haven't declared as a dependency. (Almost.) %% =========================================================================== xref(Config) -> App = fetch(app, Config), - Mods = fetch(modules, App), + Mods = fetch(modules, App), %% modules listed in the app file + + %% List of application names extracted from runtime_dependencies. + Deps = lists:map(fun unversion/1, fetch(runtime_dependencies, App)), {ok, XRef} = xref:start(make_name(xref_test_name)), ok = xref:set_default(XRef, [{verbose, false}, {warnings, false}]), @@ -178,7 +181,9 @@ xref(Config) -> [?APP, erts | fetch(applications, App)]), {ok, Undefs} = xref:analyze(XRef, undefined_function_calls), - {ok, Called} = xref:analyze(XRef, {module_call, ?COMPILER_MODULES}), + {ok, RTmods} = xref:analyze(XRef, {module_use, Mods}), + {ok, CTmods} = xref:analyze(XRef, {module_use, ?COMPILER_MODULES}), + {ok, RTdeps} = xref:analyze(XRef, {module_call, Mods}), xref:stop(XRef), @@ -190,18 +195,41 @@ xref(Config) -> Undefs), %% diameter_tcp does call ssl despite the latter not being listed %% as a dependency in the app file since ssl is only required for - %% TLS security: it's up to a client who wants TLS it to start - %% ssl. - - [] = lists:filter(fun is_bad_dependency/1, Called). - -%% It's not strictly necessary that diameter compiler modules not -%% depend on other diameter modules but it's a simple source of build -%% errors if not encoded in the makefile (hence the test) so guard -%% against it. -is_bad_dependency(Mod) -> - lists:prefix("diameter", atom_to_list(Mod)) - andalso not lists:member(Mod, ?COMPILER_MODULES). + %% TLS security: it's up to a client who wants TLS to start ssl. + + %% Ensure that only runtime or info modules call runtime modules. + %% It's not strictly necessary that diameter compiler modules not + %% depend on other diameter modules but it's a simple source of + %% build errors if not properly encoded in the makefile so guard + %% against it. + [] = (RTmods -- Mods) -- ?INFO_MODULES, + + %% Ensure that runtime modules don't call compiler modules. + CTmods = CTmods -- Mods, + + %% Ensure that runtime modules only call other runtime modules, or + %% applications declared as in runtime_dependencies in the app + %% file. Note that the declared application versions are ignored + %% since we only know what we can see now. + [] = lists:filter(fun(M) -> not lists:member(app(M), Deps) end, + RTdeps -- Mods). + +unversion(App) -> + T = lists:dropwhile(fun is_vsn_ch/1, lists:reverse(App)), + lists:reverse(case T of [$-|TT] -> TT; _ -> T end). + +is_vsn_ch(C) -> + $0 =< C andalso C =< $9 orelse $. == C. + +app('$M_EXPR') -> %% could be anything but assume it's ok + "erts"; +app(Mod) -> + case code:which(Mod) of + preloaded -> + "erts"; + Path -> + unversion(lists:nth(3, lists:reverse(filename:split(Path)))) + end. add_application(XRef, App) -> add_application(XRef, App, code:lib_dir(App)). diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index e911fb89c9..0e50c9539b 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -342,8 +342,8 @@ create_sdesc_list([{ExnLbl, SPOff} | MoreExnAndSPOffs], %% (thus, some of their arguments are passed to the stack). Because of the %% Reserved Call Frame feature that the LLVM uses, the stack descriptors %% are not correct since at the point of call the frame size is reduced -%% proportionally to the number of arguments that are passed on the stack. -%% Also the offsets of the roots need to be re-adjusted. +%% by the number of arguments that are passed on the stack. Also, the +%% offsets of the roots need to be re-adjusted. fix_stack_descriptors(_, _, [], _) -> []; fix_stack_descriptors(RelocsDict, Relocs, SDescs, ExposedClosures) -> @@ -427,30 +427,22 @@ find_offsets([{Off,Arity}|Rest], Offsets, Acc) -> [I | RestOffsets] = lists:dropwhile(fun (Y) -> Y<Off end, Offsets), find_offsets(Rest, RestOffsets, [{I, Arity}|Acc]). -%% The functions below correct the arity of calls, that are identified -%% by offset, in the stack descriptors. +%% The function below corrects the stack descriptors of calls with arguments +%% that are passed on the stack (more than NR_ARG_REGS) by subtracting the +%% number of stacked arguments from the frame size and from the offset of the +%% roots. fix_sdescs([], SDescs) -> SDescs; fix_sdescs([{Offset, Arity} | Rest], SDescs) -> case lists:keyfind(Offset, 2, SDescs) of false -> fix_sdescs(Rest, SDescs); - {?SDESC, Offset, SDesc} -> - {ExnHandler, FrameSize, StkArity, Roots} = SDesc, - DecRoot = fun(X) -> X-Arity end, - NewRootsList = lists:map(DecRoot, tuple_to_list(Roots)), - NewSDesc = - case length(NewRootsList) > 0 andalso hd(NewRootsList) >= 0 of - true -> - {?SDESC, Offset, {ExnHandler, FrameSize-Arity, StkArity, - list_to_tuple(NewRootsList)}}; - false -> - {?SDESC, Offset, {ExnHandler, FrameSize, StkArity, Roots}} - end, - RestSDescs = lists:keydelete(Offset, 2, SDescs), - fix_sdescs(Rest, [NewSDesc | RestSDescs]) + {?SDESC, Offset, {ExnHandler, FrameSize, StkArity, Roots}} -> + FixedRoots = list_to_tuple([Ri - Arity || Ri <- tuple_to_list(Roots)]), + FixedSDesc = + {?SDESC, Offset, {ExnHandler, FrameSize - Arity, StkArity, FixedRoots}}, + fix_sdescs(Rest, [FixedSDesc | lists:keydelete(Offset, 2, SDescs)]) end. - %%------------------------------------------------------------------------------ %% Miscellaneous functions %%------------------------------------------------------------------------------ diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index ba76e1d815..d7d8d1b049 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -430,12 +430,13 @@ trans_call_name(RtlCallName, Relocs, CallArgs, FinalArgs) -> case RtlCallName of PrimOp when is_atom(PrimOp) -> LlvmName = trans_prim_op(PrimOp), - Relocs1 = relocs_store(LlvmName, {call, {bif, PrimOp, length(CallArgs)}}, - Relocs), + Relocs1 = + relocs_store(LlvmName, {call, {bif, PrimOp, length(CallArgs)}}, Relocs), {"@" ++ LlvmName, [], Relocs1}; {M, F, A} when is_atom(M), is_atom(F), is_integer(A) -> - LlvmName = trans_mfa_name({M,F,A}), - Relocs1 = relocs_store(LlvmName, {call, {M,F,A}}, Relocs), + LlvmName = trans_mfa_name({M, F, A}), + Relocs1 = + relocs_store(LlvmName, {call, {M, F, length(CallArgs)}}, Relocs), {"@" ++ LlvmName, [], Relocs1}; Reg -> case hipe_rtl:is_reg(Reg) of diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index d47eced6d8..539ce883c0 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -200,6 +200,7 @@ compile_core/4, file/1, file/2, + llvm_support_available/0, load/1, help/0, help_hiper/0, @@ -648,7 +649,18 @@ run_compiler_1(DisasmFun, IcodeFun, Options) -> %% The full option expansion is not done %% until the DisasmFun returns. {Code, CompOpts} = DisasmFun(Options), - Opts = expand_options(Options ++ CompOpts), + Opts0 = expand_options(Options ++ CompOpts), + Opts = + case proplists:get_bool(to_llvm, Opts0) andalso + not llvm_support_available() of + true -> + ?error_msg("No LLVM version 3.4 or greater " + "found in $PATH; aborting " + "native code compilation.\n", []), + ?EXIT(cant_find_required_llvm_version); + false -> + Opts0 + end, check_options(Opts), ?when_option(verbose, Options, ?debug_msg("Options: ~p.\n",[Opts])), @@ -1537,4 +1549,22 @@ check_options(Opts) -> ok end. +-spec llvm_support_available() -> boolean(). + +llvm_support_available() -> + get_llvm_version() >= 3.4. + +get_llvm_version() -> + OptStr = os:cmd("opt -version"), + SubStr = "LLVM version ", N = length(SubStr), + case string:str(OptStr, SubStr) of + 0 -> % No opt available + 0.0; + S -> + case string:to_float(string:sub_string(OptStr, S + N)) of + {error, _} -> 0.0; %XXX: Assumes no revision numbers in versioning + {Float, _} -> Float + end + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |