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