aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_dict.erl20
-rw-r--r--lib/compiler/src/beam_disasm.erl11
-rw-r--r--lib/compiler/src/beam_validator.erl20
-rw-r--r--lib/compiler/src/cerl.erl17
-rw-r--r--lib/compiler/src/cerl_inline.erl26
-rw-r--r--lib/compiler/src/cerl_trees.erl20
-rw-r--r--lib/compiler/src/compile.erl9
-rw-r--r--lib/compiler/src/compiler.appup.src22
-rw-r--r--lib/compiler/src/rec_env.erl5
-rw-r--r--lib/compiler/src/sys_core_fold.erl12
-rw-r--r--lib/compiler/test/Makefile1
-rw-r--r--lib/compiler/test/compile_SUITE.erl8
-rw-r--r--lib/compiler/test/map_SUITE.erl24
-rw-r--r--lib/compiler/test/record_SUITE.erl8
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) ->