aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_dict.erl30
-rw-r--r--lib/compiler/src/compile.erl36
-rw-r--r--lib/compiler/test/compilation_SUITE.erl13
-rw-r--r--lib/compiler/test/compilation_SUITE_data/string_table.erl8
4 files changed, 56 insertions, 31 deletions
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index 4ffe8bc606..a1f994dfbd 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -33,7 +33,7 @@
exports = [] :: [{label(), arity(), label()}],
locals = [] :: [{label(), arity(), label()}],
imports = gb_trees:empty() :: gb_tree(), %{{M,F,A},Index}
- strings = [] :: [string()], %String pool
+ strings = <<>> :: binary(), %String pool
lambdas = [], %[{...}]
literals = dict:new() :: dict(), %Format: {Literal,Number}
next_atom = 1 :: pos_integer(),
@@ -119,10 +119,11 @@ import(Mod0, Name0, Arity, #asm{imports=Imp0,next_import=NextIndex}=D0)
string(Str, Dict) when is_list(Str) ->
#asm{strings=Strings,string_offset=NextOffset} = Dict,
- case old_string(Str, Strings) of
+ StrBin = list_to_binary(Str),
+ case old_string(StrBin, Strings) of
none ->
- NewDict = Dict#asm{strings=Strings++Str,
- string_offset=NextOffset+length(Str)},
+ NewDict = Dict#asm{strings = <<Strings/binary,StrBin/binary>>,
+ string_offset=NextOffset+byte_size(StrBin)},
{NextOffset,NewDict};
Offset when is_integer(Offset) ->
{NextOffset-Offset,Dict}
@@ -187,7 +188,7 @@ import_table(#asm{imports=Imp,next_import=NumImports}) ->
ImpTab = [MFA || {MFA,_} <- Sorted],
{NumImports,ImpTab}.
--spec string_table(bdict()) -> {non_neg_integer(), [string()]}.
+-spec string_table(bdict()) -> {non_neg_integer(), binary()}.
string_table(#asm{strings=Strings,string_offset=Size}) ->
{Size,Strings}.
@@ -217,15 +218,12 @@ literal_table(#asm{literals=Tab,next_literal=NumLiterals}) ->
my_term_to_binary(Term) ->
term_to_binary(Term, [{minor_version,1}]).
-%% Search for string Str in the string pool Pool.
+%% Search for binary string Str in the binary string pool Pool.
%% old_string(Str, Pool) -> none | Index
--spec old_string(string(), [string()]) -> 'none' | pos_integer().
-
-old_string([C|Str]=Str0, [C|Pool]) ->
- case lists:prefix(Str, Pool) of
- true -> length(Pool)+1;
- false -> old_string(Str0, Pool)
- end;
-old_string([_|_]=Str, [_|Pool]) ->
- old_string(Str, Pool);
-old_string([_|_], []) -> none.
+-spec old_string(binary(), binary()) -> 'none' | pos_integer().
+
+old_string(Str, Pool) ->
+ case binary:match(Pool, Str) of
+ nomatch -> none;
+ {Start,_Length} -> byte_size(Pool) - Start
+ end.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 4642fb68b3..26da3ecad2 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -41,8 +41,7 @@
-type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
--type line() :: integer().
--type err_info() :: {line(), module(), term()}. %% ErrorDescriptor
+-type err_info() :: {erl_scan:line(), module(), term()}. %% ErrorDescriptor
-type errors() :: [{file:filename(), [err_info()]}].
-type warnings() :: [{file:filename(), [err_info()]}].
-type mod_ret() :: {'ok', module()}
@@ -70,7 +69,7 @@
file(File) -> file(File, ?DEFAULT_OPTIONS).
--spec file(module() | file:filename(), [option()]) -> comp_ret().
+-spec file(module() | file:filename(), [option()] | option()) -> comp_ret().
file(File, Opts) when is_list(Opts) ->
do_compile({file,File}, Opts++env_default_opts());
@@ -88,6 +87,8 @@ forms(Forms, Opt) when is_atom(Opt) ->
%% would have generated a Beam file, false otherwise (if only a binary or a
%% listing file would have been generated).
+-spec output_generated([option()]) -> boolean().
+
output_generated(Opts) ->
noenv_output_generated(Opts++env_default_opts()).
@@ -96,6 +97,8 @@ output_generated(Opts) ->
%% for default options.
%%
+-spec noenv_file(module() | file:filename(), [option()] | option()) -> comp_ret().
+
noenv_file(File, Opts) when is_list(Opts) ->
do_compile({file,File}, Opts);
noenv_file(File, Opt) ->
@@ -106,6 +109,8 @@ noenv_forms(Forms, Opts) when is_list(Opts) ->
noenv_forms(Forms, Opt) when is_atom(Opt) ->
noenv_forms(Forms, [Opt|?DEFAULT_OPTIONS]).
+-spec noenv_output_generated([option()]) -> boolean().
+
noenv_output_generated(Opts) ->
any(fun ({save_binary,_F}) -> true;
(_Other) -> false
@@ -216,16 +221,16 @@ format_error({module_name,Mod,Filename}) ->
[Mod,Filename]).
%% The compile state record.
--record(compile, {filename="",
- dir="",
- base="",
- ifile="",
- ofile="",
+-record(compile, {filename="" :: file:filename(),
+ dir="" :: file:filename(),
+ base="" :: file:filename(),
+ ifile="" :: file:filename(),
+ ofile="" :: file:filename(),
module=[],
code=[],
core_code=[],
abstract_code=[], %Abstract code for debugger.
- options=[],
+ options=[] :: [option()],
errors=[],
warnings=[]}).
@@ -362,7 +367,7 @@ mpf(Ms) ->
[{File,[M || {F,M} <- Ms, F =:= File]} ||
File <- lists:usort([F || {F,_} <- Ms])].
-%% passes(form|file, [Option]) -> [{Name,PassFun}]
+%% passes(forms|file, [Option]) -> [{Name,PassFun}]
%% Figure out which passes that need to be run.
passes(forms, Opts) ->
@@ -819,6 +824,10 @@ foldl_transform(St, [T|Ts]) ->
{'EXIT',R} ->
Es = [{St#compile.ifile,[{none,compile,{parse_transform,T,R}}]}],
{error,St#compile{errors=St#compile.errors ++ Es}};
+ {warning, Forms, Ws} ->
+ foldl_transform(
+ St#compile{code=Forms,
+ warnings=St#compile.warnings ++ Ws}, Ts);
Forms ->
foldl_transform(St#compile{code=Forms}, Ts)
end;
@@ -828,7 +837,6 @@ get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts].
core_transforms(St) ->
%% The options field holds the complete list of options at this
-
Ts = get_core_transforms(St#compile.options),
foldl_core_transforms(St, Ts).
@@ -1172,12 +1180,12 @@ write_binary(Name, Bin, St) ->
%% report_errors(State) -> ok
%% report_warnings(State) -> ok
-report_errors(St) ->
- case member(report_errors, St#compile.options) of
+report_errors(#compile{options=Opts,errors=Errors}) ->
+ case member(report_errors, Opts) of
true ->
foreach(fun ({{F,_L},Eds}) -> list_errors(F, Eds);
({F,Eds}) -> list_errors(F, Eds) end,
- St#compile.errors);
+ Errors);
false -> ok
end.
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index d4843c9eba..9c06740816 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -46,7 +46,7 @@ all(suite) ->
trycatch_4, opt_crash,
otp_5404,otp_5436,otp_5481,otp_5553,otp_5632,
otp_5714,otp_5872,otp_6121,otp_6121a,otp_6121b,
- otp_7202,otp_7345,on_load
+ otp_7202,otp_7345,on_load,string_table
].
-define(comp(N),
@@ -596,4 +596,15 @@ otp_7345(ObjRef, _RdEnv, Args) ->
10},
id(LlUnitdataReq).
+%% Check the generation of the string table.
+
+string_table(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line File = filename:join(DataDir, "string_table.erl"),
+ ?line {ok,string_table,Beam,[]} = compile:file(File, [return, binary]),
+ ?line {ok,{string_table,[StringTableChunk]}} = beam_lib:chunks(Beam, ["StrT"]),
+ ?line {"StrT", <<"stringabletringtable">>} = StringTableChunk,
+ ok.
+
+
id(I) -> I.
diff --git a/lib/compiler/test/compilation_SUITE_data/string_table.erl b/lib/compiler/test/compilation_SUITE_data/string_table.erl
new file mode 100644
index 0000000000..1da1d015dd
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/string_table.erl
@@ -0,0 +1,8 @@
+-module(string_table).
+-export([f/1, g/1]).
+
+f(<<"string">>) -> string;
+f(<<"stringtable">>) -> stringtable.
+
+g(<<"stringtable">>) -> stringtable;
+g(<<"table">>) -> table.