diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_dict.erl | 20 | ||||
-rw-r--r-- | lib/compiler/src/beam_disasm.erl | 11 | ||||
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 20 | ||||
-rw-r--r-- | lib/compiler/src/cerl.erl | 17 | ||||
-rw-r--r-- | lib/compiler/src/cerl_inline.erl | 26 | ||||
-rw-r--r-- | lib/compiler/src/cerl_trees.erl | 20 | ||||
-rw-r--r-- | lib/compiler/src/compile.erl | 9 | ||||
-rw-r--r-- | lib/compiler/src/compiler.appup.src | 22 | ||||
-rw-r--r-- | lib/compiler/src/rec_env.erl | 5 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 12 | ||||
-rw-r--r-- | lib/compiler/test/Makefile | 1 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/compiler/test/map_SUITE.erl | 24 | ||||
-rw-r--r-- | lib/compiler/test/record_SUITE.erl | 8 |
14 files changed, 141 insertions, 62 deletions
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl index 212b9fb03a..ea51673fa3 100644 --- a/lib/compiler/src/beam_dict.erl +++ b/lib/compiler/src/beam_dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-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 @@ -29,16 +29,24 @@ -type label() :: non_neg_integer(). +-type index() :: non_neg_integer(). + +-type atom_tab() :: gb_trees:tree(atom(), index()). +-type import_tab() :: gb_trees:tree(mfa(), index()). +-type fname_tab() :: gb_trees:tree(Name :: term(), index()). +-type line_tab() :: gb_trees:tree({Fname :: index(), Line :: term()}, index()). +-type literal_tab() :: dict:dict(Literal :: term(), index()). + -record(asm, - {atoms = gb_trees:empty() :: gb_tree(), %{Atom,Index} + {atoms = gb_trees:empty() :: atom_tab(), exports = [] :: [{label(), arity(), label()}], locals = [] :: [{label(), arity(), label()}], - imports = gb_trees:empty() :: gb_tree(), %{{M,F,A},Index} + imports = gb_trees:empty() :: import_tab(), strings = <<>> :: binary(), %String pool lambdas = [], %[{...}] - literals = dict:new() :: dict(), %Format: {Literal,Number} - fnames = gb_trees:empty() :: gb_tree(), %{Name,Index} - lines = gb_trees:empty() :: gb_tree(), %{{Fname,Line},Index} + literals = dict:new() :: literal_tab(), + fnames = gb_trees:empty() :: fname_tab(), + lines = gb_trees:empty() :: line_tab(), num_lines = 0 :: non_neg_integer(), %Number of line instructions next_import = 0 :: non_neg_integer(), string_offset = 0 :: non_neg_integer(), diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl index 363989f4c9..4bdfe4e0c2 100644 --- a/lib/compiler/src/beam_disasm.erl +++ b/lib/compiler/src/beam_disasm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-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 @@ -37,7 +37,8 @@ %%----------------------------------------------------------------------- --type literals() :: 'none' | gb_tree(). +-type index() :: non_neg_integer(). +-type literals() :: 'none' | gb_trees:tree(index(), term()). -type symbolic_tag() :: 'a' | 'f' | 'h' | 'i' | 'u' | 'x' | 'y' | 'z'. -type disasm_tag() :: symbolic_tag() | 'fr' | 'atom' | 'float' | 'literal'. -type disasm_term() :: 'nil' | {disasm_tag(), _}. @@ -216,7 +217,8 @@ optional_chunk(F, ChunkTag) -> %%----------------------------------------------------------------------- -type l_info() :: {non_neg_integer(), {_,_,_,_,_,_}}. --spec beam_disasm_lambdas('none' | binary(), gb_tree()) -> 'none' | [l_info()]. +-spec beam_disasm_lambdas('none' | binary(), gb_trees:tree(index(), _)) -> + 'none' | [l_info()]. beam_disasm_lambdas(none, _) -> none; beam_disasm_lambdas(<<_:32,Tab/binary>>, Atoms) -> @@ -435,7 +437,8 @@ decode_arg([B|Bs]) -> decode_int(Tag, B, Bs) end. --spec decode_arg([byte(),...], gb_tree(), literals()) -> {disasm_term(), [byte()]}. +-spec decode_arg([byte(),...], gb_trees:tree(index(), _), literals()) -> + {disasm_term(), [byte()]}. decode_arg([B|Bs0], Atoms, Literals) -> Tag = decode_tag(B band 2#111), diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 7e1324cf61..9d5563d13b 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-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 @@ -213,9 +213,12 @@ validate_error_1(Error, Module, Name, Ar) -> {{Module,Name,Ar}, {internal_error,'_',{Error,erlang:get_stacktrace()}}}. +-type index() :: non_neg_integer(). +-type reg_tab() :: gb_trees:tree(index(), 'none' | {'value', _}). + -record(st, %Emulation state - {x=init_regs(0, term) :: gb_tree(), %x register info. - y=init_regs(0, initialized) :: gb_tree(), %y register info. + {x=init_regs(0, term) :: reg_tab(),%x register info. + y=init_regs(0, initialized) :: reg_tab(),%y register info. f=init_fregs(), % numy=none, %Number of y registers. h=0, %Available heap size. @@ -227,11 +230,16 @@ validate_error_1(Error, Module, Name, Ar) -> setelem=false %Previous instruction was setelement/3. }). +-type label() :: integer(). +-type label_set() :: gb_sets:set(label()). +-type branched_tab() :: gb_trees:tree(label(), #st{}). +-type ft_tab() :: gb_trees:tree(). + -record(vst, %Validator state {current=none :: #st{} | 'none', %Current state - branched=gb_trees:empty() :: gb_tree(), %States at jumps - labels=gb_sets:empty() :: gb_set(), %All defined labels - ft=gb_trees:empty() :: gb_tree() %Some other functions + branched=gb_trees:empty() :: branched_tab(), %States at jumps + labels=gb_sets:empty() :: label_set(), %All defined labels + ft=gb_trees:empty() :: ft_tab() %Some other functions % in the module (those that start with bs_start_match2). }). diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index 60a8559950..3c121f3b04 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -124,8 +124,9 @@ %% keep map exports here for now map_es/1, - update_c_map/2, - ann_c_map/2, + map_val/1, + update_c_map/3, + ann_c_map/3, map_pair_op/1,map_pair_key/1,map_pair_val/1, update_c_map_pair/4, ann_c_map_pair/4 @@ -1579,11 +1580,15 @@ ann_make_list(_, [], Node) -> map_es(#c_map{es = Es}) -> Es. -ann_c_map(As, Es) -> - #c_map{es = Es, anno = As }. +-spec map_val(c_map()) -> cerl(). +map_val(#c_map{var = M}) -> + M. -update_c_map(Old, Es) -> - #c_map{es = Es, anno = get_ann(Old)}. +ann_c_map(As,M,Es) -> + #c_map{var=M,es = Es, anno = As }. + +update_c_map(Old,M,Es) -> + #c_map{var=M, es = Es, anno = get_ann(Old)}. map_pair_key(#c_map_pair{key=K}) -> K. map_pair_val(#c_map_pair{val=V}) -> V. diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl index 3837b57750..44293bb8ce 100644 --- a/lib/compiler/src/cerl_inline.erl +++ b/lib/compiler/src/cerl_inline.erl @@ -64,7 +64,7 @@ seq_body/1, set_ann/2, try_arg/1, try_body/1, try_vars/1, try_evars/1, try_handler/1, tuple_es/1, tuple_arity/1, type/1, values_es/1, var_name/1, - map_es/1, update_c_map/2, + map_val/1, map_es/1, update_c_map/3, update_c_map_pair/4, map_pair_op/1, map_pair_key/1, map_pair_val/1 ]). @@ -1334,12 +1334,12 @@ i_bitstr(E, Ren, Env, S) -> i_map(E, Ctx, Ren, Env, S) -> %% Visit the segments for value. - {Es, S1} = mapfoldl(fun (E, S) -> - i_map_pair(E, Ctx, Ren, Env, S) - end, - S, map_es(E)), - S2 = count_size(weight(map), S1), - {update_c_map(E, Es), S2}. + {M1, S1} = i(map_val(E), value, Ren, Env, S), + {Es, S2} = mapfoldl(fun (E, S) -> + i_map_pair(E, Ctx, Ren, Env, S) + end, S1, map_es(E)), + S3 = count_size(weight(map), S2), + {update_c_map(E, M1,Es), S3}. i_map_pair(E, Ctx, Ren, Env, S) -> %% It is not necessary to visit the Op and Key fields, @@ -1411,13 +1411,15 @@ i_pattern(E, Ren, Env, Ren0, Env0, S) -> S2 = count_size(weight(binary), S1), {update_c_binary(E, Es), S2}; map -> + %% map patterns should not have vals + M = map_val(E), + {Es, S1} = mapfoldl(fun (E, S) -> - i_map_pair_pattern(E, Ren, Env, - Ren0, Env0, S) - end, - S, map_es(E)), + i_map_pair_pattern(E, Ren, Env, Ren0, Env0, S) + end, + S, map_es(E)), S2 = count_size(weight(map), S1), - {update_c_map(E, Es), S2}; + {update_c_map(E, M, Es), S2}; _ -> case is_literal(E) of true -> diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl index 2542841eef..2ebeab243f 100644 --- a/lib/compiler/src/cerl_trees.erl +++ b/lib/compiler/src/cerl_trees.erl @@ -57,9 +57,9 @@ update_c_try/6, update_c_tuple/2, update_c_tuple_skel/2, update_c_values/2, values_es/1, var_name/1, - map_es/1, - ann_c_map/2, - update_c_map/2, + map_val/1, map_es/1, + ann_c_map/3, + update_c_map/3, map_pair_key/1,map_pair_val/1,map_pair_op/1, ann_c_map_pair/4, update_c_map_pair/4 @@ -138,7 +138,7 @@ map_1(F, T) -> tuple -> update_c_tuple_skel(T, map_list(F, tuple_es(T))); map -> - update_c_map(T, map_list(F, map_es(T))); + update_c_map(T, map(F,map_val(T)), map_list(F, map_es(T))); map_pair -> update_c_map_pair(T, map(F, map_pair_op(T)), map(F, map_pair_key(T)), @@ -372,8 +372,9 @@ mapfold(F, S0, T) -> {Ts, S1} = mapfold_list(F, S0, tuple_es(T)), F(update_c_tuple_skel(T, Ts), S1); map -> - {Ts, S1} = mapfold_list(F, S0, map_es(T)), - F(update_c_map(T, Ts), S1); + {M , S1} = mapfold(F, S0, map_val(T)), + {Ts, S2} = mapfold_list(F, S1, map_es(T)), + F(update_c_map(T, M, Ts), S2); map_pair -> {Op, S1} = mapfold(F, S0, map_pair_op(T)), {Key, S2} = mapfold(F, S1, map_pair_key(T)), @@ -723,9 +724,10 @@ label(T, N, Env) -> {As, N2} = label_ann(T, N1), {ann_c_tuple_skel(As, Ts), N2}; map -> - {Ts, N1} = label_list(map_es(T), N, Env), - {As, N2} = label_ann(T, N1), - {ann_c_map(As, Ts), N2}; + {M, N1} = label(map_val(T), N, Env), + {Ts, N2} = label_list(map_es(T), N1, Env), + {As, N3} = label_ann(T, N2), + {ann_c_map(As, M, Ts), N3}; map_pair -> {Op, N1} = label(map_pair_op(T), N, Env), {Val, N2} = label(map_pair_key(T), N1, Env), diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index e79fe41f9b..9030dd998b 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -246,7 +246,7 @@ format_error_reason({Reason, Stack}) when is_list(Stack) -> end, FormatFun = fun (Term, _) -> io_lib:format("~tp", [Term]) end, [io_lib:format("~tp", [Reason]),"\n\n", - lib:format_stacktrace(1, erlang:get_stacktrace(), StackFun, FormatFun)]; + lib:format_stacktrace(1, Stack, StackFun, FormatFun)]; format_error_reason(Reason) -> io_lib:format("~tp", [Reason]). @@ -430,10 +430,9 @@ pass(from_core) -> pass(from_asm) -> {".S",[?pass(beam_consult_asm)|asm_passes()]}; pass(asm) -> - %% TODO: remove 'asm' in R18 - io:format("compile:file/2 option 'asm' has been deprecated and will be " - "removed in R18.~n" - "Use 'from_asm' instead.~n"), + %% TODO: remove 'asm' in 18.0 + io:format("compile:file/2 option 'asm' has been deprecated and will be~n" + "removed in the 18.0 release. Use 'from_asm' instead.~n"), pass(from_asm); pass(from_beam) -> {".beam",[?pass(read_beam_file)|binary_passes()]}; diff --git a/lib/compiler/src/compiler.appup.src b/lib/compiler/src/compiler.appup.src index 54a63833e6..fe273b269c 100644 --- a/lib/compiler/src/compiler.appup.src +++ b/lib/compiler/src/compiler.appup.src @@ -1 +1,21 @@ -{"%VSN%",[],[]}. +%% -*- erlang -*- +%% %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% +{"%VSN%", + [{<<".*">>,[{restart_application, compiler}]}], + [{<<".*">>,[{restart_application, compiler}]}] +}. diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl index 31a1f8b0b7..555a331bd7 100644 --- a/lib/compiler/src/rec_env.erl +++ b/lib/compiler/src/rec_env.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-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 @@ -72,6 +72,7 @@ test_1({custom, F} = Type, N, Env) when is_integer(N), N > 0 -> test_1(_,0, Env) -> Env. -endif. +%%@clear %% Representation: @@ -95,7 +96,7 @@ test_1(_,0, Env) -> %% ===================================================================== %% @type environment(). An abstract environment. --type mapping() :: {'map', dict()} | {'rec', dict(), dict()}. +-type mapping() :: {'map', dict:dict()} | {'rec', dict:dict(), dict:dict()}. -type environment() :: [mapping(),...]. %% ===================================================================== diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index eb9c302334..4ef345f563 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -2346,10 +2346,16 @@ is_safe_bool_expr(Core, Sub) -> is_safe_bool_expr_1(Core, Sub, gb_sets:empty()). is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang}, - name=#c_literal{val=is_record}, - args=[_,_]}, - _Sub, _BoolVars) -> + name=#c_literal{val=is_record}, + args=[A,#c_literal{val=Tag},#c_literal{val=Size}]}, + Sub, _BoolVars) when is_atom(Tag), is_integer(Size) -> + is_safe_simple(A, Sub); +is_safe_bool_expr_1(#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_record}}, + _Sub, _BoolVars) -> %% The is_record/2 BIF is NOT allowed in guards. + %% The is_record/3 BIF where its second argument is not an atom or its third + %% is not an integer is NOT allowed in guards. %% %% NOTE: Calls like is_record(Expr, LiteralTag), where LiteralTag %% is a literal atom referring to a defined record, have already diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index 39c9fea5d9..0b56a49cd6 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -69,6 +69,7 @@ INLINE= \ fun \ guard \ lc \ + map \ match \ misc \ num_bif \ diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 34c4b1e264..8cb7d1b55b 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -24,7 +24,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - app_test/1, + app_test/1,appup_test/1, file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1, binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, other_output/1, encrypted_abstr/1, @@ -42,7 +42,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), - [app_test, file_1, forms_2, module_mismatch, big_file, outdir, + [app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir, binary, makedep, cond_and_ifdef, listings, listings_big, other_output, encrypted_abstr, {group, bad_record_use}, strict_record, @@ -71,6 +71,10 @@ end_per_group(_GroupName, Config) -> app_test(Config) when is_list(Config) -> ?line ?t:app_test(compiler). +%% Test that the Application upgrade file has no `basic' errors."; +appup_test(Config) when is_list(Config) -> + ok = ?t:appup_test(compiler). + %% Tests that we can compile and run a simple Erlang program, %% using compile:file/1. diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index 7d35ffc8d5..b4baef461b 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -418,8 +418,12 @@ t_guard_fun(Config) when is_list(Config) -> {l,V} = F2(#{s=>l,v=>[V,V]}), %% error case - {'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} = (catch F1(#{s=>none,v=>none})), - ok. + case (catch F1(#{s=>none,v=>none})) of + {'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} -> ok; + {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; + Other -> + test_server:fail({no_match, Other}) + end. t_map_sort_literals(Config) when is_list(Config) -> @@ -500,8 +504,12 @@ t_build_and_match_empty_val(Config) when is_list(Config) -> ok = F(id(#{"hi"=>ok,{1,2}=>ok,1337=>ok})), %% error case - {'EXIT',{function_clause,_}} = (catch (F(id(#{"hi"=>ok})))), - ok. + case (catch (F(id(#{"hi"=>ok})))) of + {'EXIT',{function_clause,_}} -> ok; + {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; + Other -> + test_server:fail({no_match, Other}) + end. t_build_and_match_val(Config) when is_list(Config) -> F = fun @@ -514,8 +522,12 @@ t_build_and_match_val(Config) when is_list(Config) -> {2,"second"} = F(id(#{"hi"=>second,v=>"second"})), %% error case - {'EXIT',{function_clause,_}} = (catch (F(id(#{"hi"=>ok})))), - ok. + case (catch (F(id(#{"hi"=>ok})))) of + {'EXIT',{function_clause,_}} -> ok; + {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; + Other -> + test_server:fail({no_match, Other}) + end. %% Use this function to avoid compile-time evaluation of an expression. diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl index c9f5a2053e..f736e14bf6 100644 --- a/lib/compiler/test/record_SUITE.erl +++ b/lib/compiler/test/record_SUITE.erl @@ -369,6 +369,14 @@ record_test_3(Config) when is_list(Config) -> ?line false = is_record(id(#barf{}), id(barf), id(42)), ?line false = is_record(id(#barf{}), id(foo), id(6)), + Rec = id(#barf{}), + Good = id(barf), + Bad = id(foo), + Size = id(6), + + true = is_record(Rec, Good, Size) orelse error, + error = is_record(Rec, Bad, Size) orelse error, + ok. record_access_in_guards(Config) when is_list(Config) -> |