1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(beam_literals_SUITE).
22-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
23	 init_per_group/2,end_per_group/2]).
24-export([putting/1, matching_smalls/1, matching_smalls_jt/1,
25	 matching_bigs/1, matching_more_bigs/1,
26	 matching_bigs_and_smalls/1, badmatch/1, case_clause/1,
27	 receiving/1, literal_type_tests/1,
28	 put_list/1, fconv/1, literal_case_expression/1,
29	 increment/1]).
30
31-include_lib("common_test/include/ct.hrl").
32
33suite() -> [{ct_hooks,[ts_install_cth]}].
34
35all() ->
36    [putting, matching_smalls, matching_smalls_jt,
37     matching_bigs, matching_more_bigs,
38     matching_bigs_and_smalls, badmatch, case_clause,
39     receiving, literal_type_tests, put_list, fconv,
40     literal_case_expression, increment].
41
42groups() ->
43    [].
44
45init_per_suite(Config) ->
46    Config.
47
48end_per_suite(_Config) ->
49    ok.
50
51init_per_group(_GroupName, Config) ->
52    Config.
53
54end_per_group(_GroupName, Config) ->
55    Config.
56
57
58%% Test creating lists and tuples containing big number literals.
59putting(Config) when is_list(Config) ->
60    -773973888575883407313908 = chksum(putting1(id(8987697898797))).
61
62putting1(X) ->
63    {8797987987987987872256443, [1324483773773], {3.1415, 2.71, [2.5, 35.125|9.31]},
64     [X|349873987387373],
65     [329878349873|-387394729872], -773973937933873929749873}.
66
67%% Test matching of a few big number literals (in Beam select_val/3 will NOT be used).
68matching_bigs(Config) when is_list(Config) ->
69    a = matching1(3972907842873739),
70    b = matching1(-389789298378939783333333333333333333784),
71    other = matching1(3141699999999999999999999999999999999),
72    other = matching1(42).
73
74%% Test matching small numbers (both positive and negative).
75matching_smalls(Config) when is_list(Config) ->
76    a = m_small(-42),
77    b = m_small(0),
78    c = m_small(105),
79    d = m_small(-13),
80    e = m_small(337848),
81    other = m_small(324),
82    other = m_small(-7),
83    ok.
84
85m_small(-42) -> a;
86m_small(0) -> b;
87m_small(105) -> c;
88m_small(-13) -> d;
89m_small(337848) -> e;
90m_small(_) -> other.
91
92%% Test matching small numbers (both positive and negative).
93%% Make sure that a jump table is used.
94matching_smalls_jt(Config) when is_list(Config) ->
95    a = m_small_jt(-2),
96    b = m_small_jt(-1),
97    c = m_small_jt(0),
98    d = m_small_jt(2),
99    e = m_small_jt(3),
100    other = m_small(324),
101    other = m_small(-7),
102    ok.
103
104m_small_jt(-2) -> a;
105m_small_jt(-1) -> b;
106m_small_jt(0) -> c;
107m_small_jt(2) -> d;
108m_small_jt(3) -> e;
109m_small_jt(_) -> other.
110
111%% Big numbers, no select_val.
112
113matching1(3972907842873739) -> a;
114matching1(-389789298378939783333333333333333333784) -> b;
115matching1(_) -> other.
116
117
118%% Test matching of a big number literals (in Beam, a select_val/3 instruction will be used)
119matching_more_bigs(Config) when is_list(Config) ->
120    a = matching2(-999766349740978337),
121    b = matching2(9734097866575478),
122    c = matching2(-966394677364879734),
123    d = matching2(13987294872948990),
124    e = matching2(777723896192459245),
125    other = matching2(7),
126    other = matching2(39789827988888888888888888888347474444444444444444444).
127
128%% Big numbers with select_val.
129
130matching2(-999766349740978337) -> a;
131matching2(9734097866575478) -> b;
132matching2(-966394677364879734) -> c;
133matching2(13987294872948990) -> d;
134matching2(777723896192459245) -> e;
135matching2(_) -> other.
136
137%% Test matching of a mix of big numbers and literals.
138matching_bigs_and_smalls(Config) when is_list(Config) ->
139    a = matching3(38472928723987239873873),
140    b = matching3(0),
141    c = matching3(-3873973932710954671207461057614287561348756348743634876436784367873),
142    d = matching3(3978429867297393873),
143    e = matching3(42),
144    f = matching3(-4533),
145    other = matching3(77),
146    other = matching3(39274120984379249874219748),
147
148    a = matching4(1),
149    b = matching4(5),
150    c = matching4(10),
151    d = matching4(15),
152    e = matching4(20),
153    f = matching4(25),
154    big = matching4(79379377983497837983789333),
155    g = matching4(30),
156    h = matching4(35),
157    i = matching4(40),
158    j = matching4(45),
159    k = matching4(50),
160    other = matching4(a),
161    other = matching4(383793474329747922),
162
163    x = matching5(1),
164    y = matching5(2),
165    z = matching5(3),
166    xx = matching5(4),
167    yy = matching5(5),
168    zz = matching5(6),
169    xxx = matching5(7),
170    yyy = matching5(8),
171    zzz = matching5(9),
172    big = matching5(1 bsl 128),
173    other = matching5(0),
174    other = matching5(10),
175    other = matching5(-1111111111111111111111111111111111111),
176
177    ok.
178
179%% Mixed small and big.
180
181matching3(38472928723987239873873) -> a;
182matching3(0) -> b;
183matching3(-3873973932710954671207461057614287561348756348743634876436784367873) -> c;
184matching3(3978429867297393873) -> d;
185matching3(42) -> e;
186matching3(-4533) -> f;
187matching3(_) -> other.
188
189matching4(1) -> a;
190matching4(5) -> b;
191matching4(10) -> c;
192matching4(15) -> d;
193matching4(20) -> e;
194matching4(25) -> f;
195matching4(79379377983497837983789333) -> big;
196matching4(30) -> g;
197matching4(35) -> h;
198matching4(40) -> i;
199matching4(45) -> j;
200matching4(50) -> k;
201matching4(_) -> other.
202
203matching5(1) -> x;
204matching5(2) -> y;
205matching5(3) -> z;
206matching5(4) -> xx;
207matching5(5) -> yy;
208matching5(6) -> zz;
209matching5(7) -> xxx;
210matching5(8) -> yyy;
211matching5(9) -> zzz;
212matching5(1 bsl 128) -> big;
213matching5(_) -> other.
214
215%% Test literal badmatches with big number and floats.
216badmatch(Config) when is_list(Config) ->
217    %% We are satisfied if we can load this module and run it.
218    Big = id(32984798729847892498297824872982972978239874),
219    Float = id(3.1415927),
220    catch a = Big,
221    catch b = Float,
222    {'EXIT',{{badmatch,3879373498378993387},_}} =
223	   (catch c = 3879373498378993387),
224    {'EXIT',{{badmatch,7.0},_}} = (catch d = 7.0),
225    case Big of
226        Big -> ok
227    end,
228    case Float of
229        Float -> ok
230    end,
231    ok.
232
233case_clause(Config) when is_list(Config) ->
234    {'EXIT',{{case_clause,337.0},_}} = (catch case_clause_float()),
235    {'EXIT',{{try_clause,42.0},_}} = (catch try_case_clause_float()),
236    {'EXIT',{{case_clause,37932749837839747383847398743789348734987},_}} =
237	(catch case_clause_big()),
238    {'EXIT',{{try_clause,977387349872349870423364354398566348},_}} =
239	(catch try_case_clause_big()),
240    ok.
241
242case_clause_float() ->
243    case 337.0 of
244	blurf -> ok
245    end.
246
247try_case_clause_float() ->
248    try 42.0 of
249	blurf -> ok
250    catch _:_ ->
251	    error
252    end.
253
254case_clause_big() ->
255    case 37932749837839747383847398743789348734987 of
256	blurf -> ok
257    end.
258
259try_case_clause_big() ->
260    try 977387349872349870423364354398566348 of
261	blurf -> ok
262    catch _:_ ->
263	    error
264    end.
265
266%% Test receive with a big number literal (more than 27 bits, less than 32 bits).
267receiving(Config) when is_list(Config) ->
268    Self = self(),
269    spawn(fun() -> Self ! here_is_a_message end),
270    ok = receive
271	     here_is_a_message ->
272		 ok
273	 after 16#f1234567 ->
274		 timeout
275	 end.
276
277%% Test type tests on literal values.
278literal_type_tests(Config) when is_list(Config) ->
279    %% Generate an Erlang module with all different type of type tests.
280    Tests = make_test([{T, L} || T <- type_tests(), L <- literals()]),
281    Mod = literal_test,
282    Anno = erl_anno:new(0),
283    Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]},
284    Form = [{attribute,Anno,module,Mod},
285            {attribute,Anno,compile,export_all},
286            Func, {eof,Anno}],
287
288    %% Print generated code for inspection.
289    lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
290
291    %% Test compile:form/1.  This implies full optimization (default).
292    {ok,Mod,Code1} = compile:forms(Form),
293    {module,Mod} = code:load_binary(Mod, Mod, Code1),
294    Mod:test(),
295    true = code:delete(Mod),
296    code:purge(Mod),
297
298    %% Test compile:form/2.  Turn off all optimizations.
299    NoOpt = [no_copt,no_bool_opt,no_share_opt,no_bsm_opt,no_fun_opt,
300             no_ssa_opt,no_recv_opt,no_postopt],
301    {ok,Mod,Code2} = compile:forms(Form, [binary,report,time|NoOpt]),
302    {module,Mod} = code:load_binary(Mod, Mod, Code2),
303    Mod:test(),
304    true = code:delete(Mod),
305    code:purge(Mod),
306
307    %% The new SSA-based compiler in OTP 22 and later will evaluate
308    %% calls to guard BIFs and tests even if all optimizations are
309    %% turned off. To ensure that BEAM can load and execute type tests
310    %% with literal operands, we will need to assemble a pre-generated
311    %% .S file. The comments in the .S file itself explains how it
312    %% was generated.
313
314    DataDir = proplists:get_value(data_dir, Config),
315    UnoptTestsFile = filename:join(DataDir, "unoptimized_literal_tests"),
316    {ok,UnoptMod,Code3} = compile:file(UnoptTestsFile, [from_asm,binary,report,time]),
317    {module,UnoptMod} = code:load_binary(UnoptMod, UnoptMod, Code3),
318    UnoptMod:test(),
319    true = code:delete(UnoptMod),
320    code:purge(UnoptMod),
321
322    ok.
323
324make_test([{is_function=T,L}|Ts]) ->
325    [guard_test(T, L),guard_test(T, 0, L),body_test(T, L),body_test(T, 0, L)|make_test(Ts)];
326make_test([{T,L}|Ts]) ->
327    [guard_test(T, L),body_test(T, L)|make_test(Ts)];
328make_test([]) -> [].
329
330guard_test(_, L) when is_function(L) ->
331    %% Skip guard tests with exports - they are not literals
332    {atom,erl_anno:new(0),true};
333guard_test(T, L) ->
334    S = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T, L, T, L]),
335    {Val,Expr} = eval_string(S),
336    Anno = erl_anno:new(0),
337    {match,Anno,{atom,Anno,Val},Expr}.
338
339guard_test(_, _, L) when is_function(L) ->
340    %% Skip guard tests with exports - they are not literals
341    {atom,erl_anno:new(0),true};
342guard_test(T, A, L) ->
343    S = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ", [T,L,A,T,L,A]),
344    {Val,Expr} = eval_string(S),
345    Anno = erl_anno:new(0),
346    {match,Anno,{atom,Anno,Val},Expr}.
347
348body_test(T, L) ->
349    S = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p}]), ~w(~w) end. ", [T,L,T,L]),
350    {Val,Expr} = eval_string(S),
351    Anno = erl_anno:new(0),
352    {match,Anno,{atom,Anno,Val},Expr}.
353
354body_test(T, A, L) ->
355    S = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p,~p}]), ~w(~w,~w) end. ", [T,L,A,T,L,A]),
356    {Val,Expr} = eval_string(S),
357    Anno = erl_anno:new(0),
358    {match,Anno,{atom,Anno,Val},Expr}.
359
360eval_string(S) ->
361    {ok,Toks,_Line} = erl_scan:string(lists:flatten(S)),
362    {ok,E} = erl_parse:parse_exprs(Toks),
363    {value,Val,_Bs} = erl_eval:exprs(E, []),
364    {Val,hd(E)}.
365
366literals() ->
367    [42,
368     3.14,
369     -3,
370     32982724987789283473473838474,
371     [],
372     "abc",
373     <<"abc">>,
374     {},
375     xxxx,
376     fun erlang:erase/0].
377
378type_tests() ->
379    [is_boolean,
380     is_integer,
381     is_float,
382     is_number,
383     is_atom,
384     is_list,
385     is_tuple,
386     is_pid,
387     is_reference,
388     is_port,
389     is_binary,
390     is_function].
391
392put_list(Config) when is_list(Config) ->
393    %% put_list x0 Literal Reg
394    [Config|8739757395764] = put_list_rqr(Config),
395    {[Config|7779757395764],Config} = put_list_rqx(Config),
396    [Config|98765432100000] = put_list_rqy(Config),
397
398    %% put_list x Literal Reg
399    [Config|16#FFFFF77777137483769] = put_list_xqr(ignore, Config),
400    {[Config|16#AAAAAFFFFF77777],{a,b},Config} =  put_list_xqx({a,b}, Config),
401    [Config|12777765432979879] = put_list_xqy(ignore, Config),
402
403    %% put_list y Literal Reg
404    [Config|17424134793676869867] = put_list_yqr(Config),
405    {[Config|77424134793676869867],Config} = put_list_yqx(Config),
406    {Config,[Config|16#BCDEFF4241676869867]} = put_list_yqy(Config),
407
408    %% put_list Literal x0 Reg
409    [42.0|Config] = put_list_qrr(Config),
410    [Config,42.0|Config] = put_list_qrx(Config),
411    [100.0|Config] = put_list_qry(Config),
412
413    %% put_list Literal x1 Reg
414    [127.0|Config] = put_list_qxr({ignore,me}, Config),
415    [Config,130.0|Config] = put_list_qxx(ignore, Config),
416    [99.0|Config] = put_list_qxy(Config),
417
418    %% put_list Literal y0 Reg
419    [200.0|Config] = put_list_qyr(Config),
420    [Config,210.0|Config] = put_list_qyx(Config),
421    [[300.0|Config]|Config] = put_list_qyy(Config),
422
423    ok.
424
425%% put_list x0 Literal x0
426put_list_rqr(Config) -> [Config|8739757395764].
427
428%% put_list x0 Literal x1
429put_list_rqx(Config) -> {[Config|7779757395764],Config}.
430
431%% put_list x0 Literal y0
432put_list_rqy(Config) ->
433    Res = [Config|98765432100000],
434    id(42),
435    Res.
436
437%% put_list x1 Literal x0
438put_list_xqr(_, Config) -> [Config|16#FFFFF77777137483769].
439
440%% put_list x1 Literal x2
441put_list_xqx(A, Config) -> {[Config|16#AAAAAFFFFF77777],A,Config}.
442
443%% put_list x1 Literal y0
444put_list_xqy(_, Config) ->
445    Res = [Config|12777765432979879],
446    id(42),
447    Res.
448
449%% put_list y0 Literal x0
450put_list_yqr(Config) ->
451    id(Config),
452    [Config|17424134793676869867].
453
454%% put_list y0 Literal x1
455put_list_yqx(Config) ->
456    id(Config),
457    {[Config|77424134793676869867],Config}.
458
459%% put_list y1 Literal y0
460put_list_yqy(Config) ->
461    id(Config),
462    Res = [Config|16#BCDEFF4241676869867],
463    id(Config),
464    {Config,Res}.
465
466%% put_list Literal x0 x0
467put_list_qrr(Config) ->
468    [42.0|Config].
469
470%% put_list Literal x0 x1
471put_list_qrx(Config) ->
472    [Config,42.0|Config].
473
474%% put_list Literal x0 y0
475put_list_qry(Config) ->
476    Res = [100.0|Config],
477    id(0),
478    Res.
479
480%% put_list Literal x1 x0
481put_list_qxr(_, Config) ->
482    [127.0|Config].
483
484%% put_list Literal x1 x2
485put_list_qxx(_, Config) ->
486    [Config,130.0|Config].
487
488%% put_list Literal x1 y0
489put_list_qxy(Config) ->
490    Res = [99.0|Config],
491    id(0),
492    Res.
493
494%% put_list Literal y0 x0
495put_list_qyr(Config) ->
496    id(Config),
497    [200.0|Config].
498
499%% put_list Literal y0 x1
500put_list_qyx(Config) ->
501    id(Config),
502    [Config,210.0|Config].
503
504%% put_list Literal y1 y0
505put_list_qyy(Config) ->
506    id(Config),
507    Res = [300.0|Config],
508    id(Config),
509    [Res|Config].
510
511fconv(Config) when is_list(Config) ->
512    5.0 = fconv_1(-34444444450.0),
513    13.0 = fconv_2(7.0),
514    ok.
515
516fconv_1(F) when is_float(F) ->
517    34444444455 + F.
518
519fconv_2(F) when is_float(F) ->
520    6.0 + F.
521
522literal_case_expression(Config) when is_list(Config) ->
523    DataDir = proplists:get_value(data_dir, Config),
524    Src = filename:join(DataDir, "literal_case_expression"),
525    Opts = [from_asm,binary,no_postopt],
526    {ok,literal_case_expression=Mod,Code} = compile:file(Src, Opts),
527    {module,Mod} = code:load_binary(Mod, Src, Code),
528    ok = Mod:x(),
529    ok = Mod:y(),
530    ok = Mod:zi1(),
531    ok = Mod:zi2(),
532    ok = Mod:za1(),
533    ok = Mod:za2(),
534    true = code:delete(Mod),
535    code:purge(Mod),
536    ok.
537
538%% Test the i_increment instruction.
539increment(Config) when is_list(Config) ->
540    %% In the 32-bit emulator, Neg32 can be represented as a small,
541    %% but -Neg32 cannot. Therefore the i_increment instruction must
542    %% not be used in the subtraction that follows (since i_increment
543    %% cannot handle a bignum literal).
544    Neg32 = -(1 bsl 27),
545    Big32 = id(1 bsl 32),
546    Result32 = (1 bsl 32) + (1 bsl 27),
547    Result32 = Big32 + (1 bsl 27),
548    Result32 = Big32 - Neg32,
549
550    %% Same thing, but for the 64-bit emulator.
551    Neg64 = -(1 bsl 59),
552    Big64 = id(1 bsl 64),
553    Result64 = (1 bsl 64) + (1 bsl 59),
554    Result64 = Big64 + (1 bsl 59),
555    Result64 = Big64 - Neg64,
556
557    %% Test error handling for the i_increment instruction.
558    Bad = id(bad),
559    {'EXIT',{badarith,_}} = (catch Bad + 42),
560
561    %% Small operands, but a big result.
562    Res32 = 1 bsl 27,
563    Small32 = id(Res32-1),
564    Res32 = Small32 + 1,
565    Res64 = 1 bsl 59,
566    Small64 = id(Res64-1),
567    Res64 = Small64 + 1,
568    ok.
569
570%% Help functions.
571
572chksum(Term) ->
573    chksum(Term, 0).
574
575chksum([List|T], Sum) when is_list(List) ->
576    chksum(T, chksum(List, Sum));
577chksum([H|T], Sum) ->
578    chksum(T, chksum(H, Sum));
579chksum([], Sum) -> Sum;
580chksum(Tuple, Sum) when is_tuple(Tuple) ->
581    chksum(tuple_to_list(Tuple), Sum);
582chksum(Int, Sum) when is_integer(Int) ->
583    Sum * 5 + Int;
584chksum(Other, Sum) ->
585    erlang:phash2([Other|Sum], 39729747).
586
587id(I) -> I.
588