1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-2020. 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(bs_match_SUITE). 22-compile(nowarn_shadow_vars). 23 24-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 25 init_per_group/2,end_per_group/2, 26 init_per_testcase/2,end_per_testcase/2, 27 verify_highest_opcode/1, expand_and_squeeze/1, 28 size_shadow/1,int_float/1,otp_5269/1,null_fields/1,wiger/1, 29 bin_tail/1,save_restore/1, 30 partitioned_bs_match/1,function_clause/1, 31 unit/1,shared_sub_bins/1,bin_and_float/1, 32 dec_subidentifiers/1,skip_optional_tag/1,decode_integer/1, 33 wfbm/1,degenerated_match/1,bs_sum/1,coverage/1, 34 multiple_uses/1,zero_label/1,followed_by_catch/1, 35 matching_meets_construction/1,simon/1,matching_and_andalso/1, 36 otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1, 37 match_string/1,zero_width/1,bad_size/1,haystack/1, 38 cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1, 39 no_partition/1,calling_a_binary/1,binary_in_map/1, 40 match_string_opt/1,select_on_integer/1, 41 map_and_binary/1,unsafe_branch_caching/1, 42 bad_literals/1,good_literals/1,constant_propagation/1, 43 parse_xml/1,get_payload/1,escape/1,num_slots_different/1, 44 beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1, 45 expression_before_match/1,erl_689/1,restore_on_call/1, 46 restore_after_catch/1,matches_on_parameter/1,big_positions/1, 47 matching_meets_apply/1,bs_start_match2_defs/1, 48 exceptions_after_match_failure/1, 49 bad_phi_paths/1,many_clauses/1, 50 combine_empty_segments/1,hangs_forever/1, 51 bs_saved_position_units/1,empty_matches/1]). 52 53-export([coverage_id/1,coverage_external_ignore/2]). 54 55-include_lib("common_test/include/ct.hrl"). 56-include_lib("syntax_tools/include/merl.hrl"). 57 58 59suite() -> 60 [{ct_hooks,[ts_install_cth]}, 61 {timetrap,{minutes,1}}]. 62 63all() -> 64 [{group,p}]. 65 66groups() -> 67 [{p,test_lib:parallel(), 68 [verify_highest_opcode, 69 size_shadow,int_float,otp_5269,null_fields,wiger, 70 bin_tail,save_restore,expand_and_squeeze, 71 partitioned_bs_match,function_clause,unit, 72 shared_sub_bins,bin_and_float,dec_subidentifiers, 73 skip_optional_tag,decode_integer,wfbm,degenerated_match,bs_sum, 74 coverage,multiple_uses,zero_label,followed_by_catch, 75 matching_meets_construction,simon, 76 matching_and_andalso,otp_7188,otp_7233,otp_7240, 77 otp_7498,match_string,zero_width,bad_size,haystack, 78 cover_beam_bool,matched_out_size,follow_fail_branch, 79 no_partition,calling_a_binary,binary_in_map, 80 match_string_opt,select_on_integer, 81 map_and_binary,unsafe_branch_caching, 82 bad_literals,good_literals,constant_propagation,parse_xml, 83 get_payload,escape,num_slots_different, 84 beam_bsm,guard,is_ascii,non_opt_eq, 85 expression_before_match,erl_689,restore_on_call, 86 matches_on_parameter,big_positions, 87 matching_meets_apply,bs_start_match2_defs, 88 exceptions_after_match_failure,bad_phi_paths, 89 many_clauses,combine_empty_segments,hangs_forever, 90 bs_saved_position_units,empty_matches]}]. 91 92init_per_suite(Config) -> 93 test_lib:recompile(?MODULE), 94 Config. 95 96end_per_suite(_Config) -> 97 ok. 98 99init_per_group(_GroupName, Config) -> 100 Config. 101 102end_per_group(_GroupName, Config) -> 103 Config. 104 105 106init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 107 Config. 108 109end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 110 ok. 111 112verify_highest_opcode(_Config) -> 113 case ?MODULE of 114 bs_match_r21_SUITE -> 115 {ok,Beam} = file:read_file(code:which(?MODULE)), 116 case test_lib:highest_opcode(Beam) of 117 Highest when Highest =< 163 -> 118 ok; 119 TooHigh -> 120 ct:fail({too_high_opcode_for_21,TooHigh}) 121 end; 122 _ -> 123 ok 124 end. 125 126size_shadow(Config) when is_list(Config) -> 127 %% Originally OTP-5270. 128 7 = size_shadow_1(), 129 7 = size_shadow_2(8), 130 7 = size_shadow_3(), 131 no = size_shadow_4(8), 132 Any = {any,term,goes}, 133 {2577,Any,-175,whatever} = 134 (size_shadow_5(Any, 12))(<<2577:12>>, -175, whatever), 135 {7777,Any,42,whatever} = 136 (size_shadow_6(Any, 13))(42, <<7777:13>>, whatever), 137 {<<45>>,<<>>} = size_shadow_7({int,1}, <<1:16,45>>), 138 {'EXIT',{function_clause,_}} = 139 (catch size_shadow_7({int,42}, <<1:16,45>>)), 140 ok. 141 142size_shadow_1() -> 143 L = 8, 144 Fs = [fun(<<L:L,B:L>>) -> B end, 145 fun(A) -> 146 (fun([<<L:L,B:L>>]) -> B end)([A]) 147 end, 148 fun(A) -> 149 (fun([<<L:L,B:L>>,<<L:L,B:L>>]) -> B end)([A,A]) 150 end, 151 fun(A) -> 152 <<Size:L,_/bits>> = A, 153 Inner = fun([L], {#{key1 := <<L:L,B:L>>, 154 key2 := <<L:L,B:L>>}, L}) -> B end, 155 Inner([Size], {#{key1 => A,key2 => A},Size}) 156 end], 157 size_shadow_apply(Fs, <<16:8, 7:16>>). 158 159size_shadow_2(L) -> 160 Fs = [fun(<<L:L,B:L>>) -> B end, 161 fun(A) -> 162 (fun([<<L:L,B:L>>]) -> B end)([A]) 163 end, 164 fun(A) -> 165 (fun({<<L:L,B:L>>,<<L:L,B:L>>}) -> B end)({A,A}) 166 end], 167 size_shadow_apply(Fs, <<16:8, 7:16>>). 168 169size_shadow_3() -> 170 L = 8, 171 Fs = [fun(<<L:L,B:L,L:L>>) -> B end, 172 fun(A) -> 173 (fun({tag,[<<L:L,B:L,L:L>>]}) -> B end)({tag,[A]}) 174 end, 175 fun(A) -> 176 (fun({tag,<<L:L,B:L,L:L>>,<<L:L,B:L,L:L>>}) -> B end)({tag,A,A}) 177 end], 178 size_shadow_apply(Fs, <<16:8, 7:16,16:16>>). 179 180size_shadow_4(L) -> 181 Fs = [fun(<<L:L,B:L,L:L>>) -> B; 182 (_) -> no 183 end, 184 fun(A) -> 185 Inner = fun([<<L:L,B:L,L:L>>]) -> B; 186 (_) -> no 187 end, 188 Inner([A]) 189 end, 190 fun(A) -> 191 Inner = fun({<<L:L,B:L,L:L>>,<<L:L,B:L,L:L>>}) -> B; 192 (_) -> no 193 end, 194 Inner({A,A}) 195 end], 196 size_shadow_apply(Fs, <<16:8, 7:16,15:16>>). 197 198size_shadow_5(X, Y) -> 199 fun (<< A:Y >>, Y, B) -> fum(A, X, Y, B) end. 200 201size_shadow_6(X, Y) -> 202 fun (Y, << A:Y >>, B) -> fum(A, X, Y, B) end. 203 204fum(A, B, C, D) -> 205 {A,B,C,D}. 206 207size_shadow_7({int,N}, <<N:16,B:N/binary,T/binary>>) -> 208 {B,T}. 209 210size_shadow_apply([F|Fs], Arg) when is_function(F, 1) -> 211 size_shadow_apply(Fs, Arg, F(Arg)). 212 213size_shadow_apply([F|Fs], Arg, Res) when is_function(F, 1) -> 214 Res = F(Arg), 215 size_shadow_apply(Fs, Arg, Res); 216size_shadow_apply([], _, Res) -> 217 Res. 218 219int_float(Config) when is_list(Config) -> 220 %% OTP-5323 221 <<103133.0:64/float>> = <<103133:64/float>>, 222 <<103133:64/float>> = <<103133:64/float>>, 223 224 %% Coverage of error cases in sys_pre_expand:coerce_to_float/2. 225 case id(default) of 226 <<(1 bsl 1024):64/float>> -> 227 ct:fail(should_not_match); 228 default -> 229 ok 230 end. 231 232%% Stolen from erl_eval_SUITE and modified. 233%% OTP-5269. Bugs in the bit syntax. 234otp_5269(Config) when is_list(Config) -> 235 check(fun() -> L = 8, 236 F = fun(<<A:L,B:A>>) -> B end, 237 F(<<16:8, 7:16>>) 238 end, 239 7), 240 check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, 241 7), 242 check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, 243 32), 244 check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, 245 [32]), 246 check(fun() -> [X || <<A:8, 247 B:A>> <- [<<16:8,19:16>>], 248 <<X:8>> <- [<<B:8>>]] end, 249 [19]), 250 check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end, 251 28), 252 check(fun() -> 253 <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, 254 {Size,B,Rest} 255 end, 256 {2,<<"AB">>,<<"CD">>}), 257 check(fun() -> X = 32, 258 [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, 259 %% "binsize variable" ^ 260 [1,2]), 261 check(fun() -> 262 (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) -> 263 case A of 264 B -> wrong; 265 _ -> ok 266 end 267 end)(<<1,2,3,4>>) end, 268 ok), 269 ok. 270 271null_fields(Config) when is_list(Config) -> 272 check(fun() -> 273 W = id(0), 274 F = fun(<<_:W>>) -> tail; 275 (<<>>) -> empty 276 end, 277 F(<<>>) 278 end, tail), 279 check(fun() -> 280 F = fun(<<_/binary>>) -> tail; 281 (<<>>) -> empty 282 end, 283 F(<<>>) 284 end, tail), 285 ok. 286 287wiger(Config) when is_list(Config) -> 288 ok1 = wcheck(<<3>>), 289 ok2 = wcheck(<<1,2,3>>), 290 ok3 = wcheck(<<4>>), 291 {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), 292 {error,<<>>} = wcheck(<<>>), 293 ok. 294 295wcheck(<<A>>) when A==3-> 296 ok1; 297wcheck(<<_,_:2/binary>>) -> 298 ok2; 299wcheck(<<_>>) -> 300 ok3; 301wcheck(Other) -> 302 {error,Other}. 303 304bin_tail(Config) when is_list(Config) -> 305 S = <<"abcde">>, 306 $a = bin_tail_c(S, 0), 307 $c = bin_tail_c(S, 2), 308 $e = bin_tail_c(S, 4), 309 {'EXIT',_} = (catch bin_tail_c(S, 5)), 310 {'EXIT',_} = (catch bin_tail_c_var(S, 5)), 311 312 $a = bin_tail_d(S, 0), 313 $b = bin_tail_d(S, 8), 314 $d = bin_tail_d(S, 3*8), 315 {'EXIT',_} = (catch bin_tail_d_dead(S, 1)), 316 {'EXIT',_} = (catch bin_tail_d_dead(S, 9)), 317 {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)), 318 {'EXIT',_} = (catch bin_tail_d_var(S, 1)), 319 320 ok = bin_tail_e(<<2:2,0:1,1:5>>), 321 ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>), 322 error = bin_tail_e(<<3:2,1:1,1:5,42:64>>), 323 error = bin_tail_e(<<>>), 324 325 MD5 = erlang:md5(<<42>>), 326 <<"abc">> = bin_tail_f(<<MD5/binary,"abc">>, MD5, 3), 327 error = bin_tail_f(<<MD5/binary,"abc">>, MD5, 999), 328 {'EXIT',{_,_}} = (catch bin_tail_f(<<0:16/unit:8>>, MD5, 0)), 329 330 ok. 331 332bin_tail_c(Bin, Offset) -> 333 Res = bin_tail_c_dead(Bin, Offset), 334 <<_:Offset/binary,_,Tail/binary>> = Bin, 335 {Res,Tail} = bin_tail_c_var(Bin, Offset), 336 Res. 337 338bin_tail_c_dead(Bin, Offset) -> 339 <<_:Offset/binary,C,_/binary>> = Bin, 340 C. 341 342bin_tail_c_var(Bin, Offset) -> 343 <<_:Offset/binary,C,Tail/binary>> = Bin, 344 {C,Tail}. 345 346 347bin_tail_d(Bin, BitOffset) -> 348 Res = bin_tail_d_dead(Bin, BitOffset), 349 <<_:BitOffset,_:8,Tail/binary>> = Bin, 350 {Res,Tail} = bin_tail_d_var(Bin, BitOffset), 351 Res. 352 353bin_tail_d_dead(Bin, BitOffset) -> 354 <<_:BitOffset,C,_/binary>> = Bin, 355 C. 356 357bin_tail_d_var(Bin, BitOffset) -> 358 <<_:BitOffset,C,Tail/binary>> = Bin, 359 {C,Tail}. 360 361bin_tail_e(Bin) -> 362 case bin_tail_e_dead(Bin) of 363 ok -> 364 <<_,Tail/binary>> = Bin, 365 Tail = bin_tail_e_var(Bin), 366 ok; 367 error -> 368 bin_tail_e_var(Bin) 369 end. 370 371bin_tail_e_dead(Bin) -> 372 case Bin of 373 %% The binary is aligned at the end; neither the bs_skip_bits2 nor 374 %% bs_test_tail2 instructions are needed. 375 <<2:2,_:1,1:5,_/binary>> -> ok; 376 _ -> error 377 end. 378 379bin_tail_e_var(Bin) -> 380 case Bin of 381 %% The binary is aligned at the end; neither the bs_skip_bits2 nor 382 %% bs_test_tail2 instructions are needed. 383 <<2:2,_:1,1:5,Tail/binary>> -> Tail; 384 _ -> error 385 end. 386 387bin_tail_f(Bin, MD5, Size) -> 388 case Bin of 389 <<MD5:16/binary, Tail:Size/binary>> -> 390 Tail; 391 <<MD5:16/binary, _/binary>> -> 392 error 393 end. 394 395save_restore(Config) when is_list(Config) -> 396 0 = save_restore_1(<<0:2,42:6>>), 397 {1,3456} = save_restore_1(<<1:2,3456:14>>), 398 {2,7981234} = save_restore_1(<<2:2,7981234:30>>), 399 {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>), 400 401 A = <<" x">>, 402 B = <<".x">>, 403 C = <<"-x">>, 404 405 {" ",<<"x">>} = lll(A), 406 {" ",<<"x">>} = mmm(A), 407 {" ",<<"x">>} = nnn(A), 408 {" ",<<"x">>} = ooo(A), 409 410 {".",<<"x">>} = lll(B), 411 {".",<<"x">>} = mmm(B), 412 {".",<<"x">>} = nnn(B), 413 {".",<<"x">>} = ooo(B), 414 415 {"-",<<"x">>} = lll(C), 416 {"-",<<"x">>} = mmm(C), 417 {"-",<<"x">>} = nnn(C), 418 {"-",<<"x">>} = ooo(C), 419 420 a = multiple_matches(<<777:16>>, <<777:16>>), 421 b = multiple_matches(<<777:16>>, <<999:16>>), 422 c = multiple_matches(<<777:16>>, <<57:8>>), 423 d = multiple_matches(<<17:8>>, <<1111:16>>), 424 425 Bin = <<-1:64>>, 426 case bad_float_unpack_match(Bin) of 427 -1 -> ok; 428 _Other -> ct:fail(bad_return_value_probably_NaN) 429 end. 430 431save_restore_1(Bin) -> 432 case Bin of 433 <<0:2,_:6>> -> 0; 434 <<1:2,A:14>> -> {1,A}; 435 <<2:2,A:30>> -> {2,A}; 436 <<A:64>> -> {3,A} 437 end. 438 439lll(<<Char, Tail/binary>>) -> {[Char],Tail}. 440 441mmm(<<$.,$.,$., Tail/binary>>) -> Tail; 442mmm(<<$\s,$-,$\s, Tail/binary>>) -> Tail; 443mmm(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail! 444 445nnn(<<"...", Tail/binary>>) -> Tail; 446nnn(<<" - ", Tail/binary>>) -> Tail; 447nnn(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail! 448 449ooo(<<" - ", Tail/binary>>) -> Tail; 450ooo(<<Char, Tail/binary>>) -> {[Char],Tail}. 451 452multiple_matches(<<Y:16>>, <<Y:16>>) -> a; 453multiple_matches(<<_:16>>, <<_:16>>) -> b; 454multiple_matches(<<_:16>>, <<_:8>>) -> c; 455multiple_matches(<<_:8>>, <<_:16>>) -> d. 456 457bad_float_unpack_match(<<F:64/float>>) -> F; 458bad_float_unpack_match(<<I:64/integer-signed>>) -> I. 459 460 461partitioned_bs_match(Config) when is_list(Config) -> 462 <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>), 463 error = partitioned_bs_match(10, <<7,8,15,13>>), 464 error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}), 465 ok = partitioned_bs_match(0, <<>>), 466 fc(partitioned_bs_match, [-1,blurf], 467 catch partitioned_bs_match(-1, blurf)), 468 fc(partitioned_bs_match, [-1,<<1,2,3>>], 469 catch partitioned_bs_match(-1, <<1,2,3>>)), 470 {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>), 471 {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>), 472 473 fc(partitioned_bs_match_2, [4,<<0:17>>], 474 catch partitioned_bs_match_2(4, <<0:17>>)), 475 476 anything = partitioned_bs_match_3(anything, <<42>>), 477 ok = partitioned_bs_match_3(1, 2), 478 479 ok. 480 481partitioned_bs_match(_, <<42:8,T/binary>>) -> 482 T; 483partitioned_bs_match(N, _) when N > 0 -> 484 error; 485partitioned_bs_match(_, <<>>) -> 486 ok. 487 488partitioned_bs_match_2(1, <<B:8,T/binary>>) -> 489 {B,T}; 490partitioned_bs_match_2(Len, <<_:8,T/binary>>) -> 491 {Len,T}. 492 493partitioned_bs_match_3(Var, <<_>>) -> Var; 494partitioned_bs_match_3(1, 2) -> ok. 495 496function_clause(Config) when is_list(Config) -> 497 ok = function_clause_1(<<0,7,0,7,42>>), 498 fc(function_clause_1, [<<0,1,2,3>>], 499 catch function_clause_1(<<0,1,2,3>>)), 500 fc(function_clause_1, [<<0,1,2,3>>], 501 catch function_clause_1(<<0,7,0,1,2,3>>)), 502 503 ok = function_clause_2(<<0,7,0,7,42>>), 504 ok = function_clause_2(<<255>>), 505 ok = function_clause_2(<<13:4>>), 506 fc(function_clause_2, [<<0,1,2,3>>], 507 catch function_clause_2(<<0,1,2,3>>)), 508 fc(function_clause_2, [<<0,1,2,3>>], 509 catch function_clause_2(<<0,7,0,1,2,3>>)), 510 511 ok. 512 513function_clause_1(<<0:8,7:8,T/binary>>) -> 514 function_clause_1(T); 515function_clause_1(<<_:8>>) -> 516 ok. 517 518function_clause_2(<<0:8,7:8,T/binary>>) -> 519 function_clause_2(T); 520function_clause_2(<<_:8>>) -> 521 ok; 522function_clause_2(<<_:4>>) -> 523 ok. 524 525unit(Config) when is_list(Config) -> 526 42 = peek1(<<42>>), 527 43 = peek1(<<43,1,2>>), 528 43 = peek1(<<43,1,2,(-1):1>>), 529 43 = peek1(<<43,1,2,(-1):2>>), 530 43 = peek1(<<43,1,2,(-1):7>>), 531 532 99 = peek8(<<99>>), 533 100 = peek8(<<100,101>>), 534 fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)), 535 536 37484 = peek16(<<37484:16>>), 537 37489 = peek16(<<37489:16,5566:16>>), 538 fc(peek16, [<<8>>], catch peek16(<<8>>)), 539 fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)), 540 fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)), 541 542 127 = peek7(<<127:7>>), 543 100 = peek7(<<100:7,19:7>>), 544 fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)), 545 546 1 = unit_opt(1, -1), 547 8 = unit_opt(8, -1), 548 549 <<1:32,"abc">> = unit_opt_2(<<1:32,"abc">>), 550 <<"def">> = unit_opt_2(<<2:32,"def">>), 551 {'EXIT',_} = (catch unit_opt_2(<<1:32,33:7>>)), 552 {'EXIT',_} = (catch unit_opt_2(<<2:32,55:7>>)), 553 554 <<0:64>> = unit_opt_3(<<1:128>>), 555 <<1:64>> = unit_opt_3(<<1:64>>), 556 557 ok. 558 559peek1(<<B:8,_/bitstring>>) -> B. 560 561peek7(<<B:7,_/binary-unit:7>>) -> B. 562 563peek8(<<B:8,_/binary>>) -> B. 564 565peek16(<<B:16,_/binary-unit:16>>) -> B. 566 567unit_opt(U, X) -> 568 %% Cover type analysis in beam_ssa_type. 569 Bin = case U of 570 1 -> <<X:7>>; 571 8 -> <<X>> 572 end, 573 %% The type of Bin will be set to {binary,gcd(1, 8)}. 574 case Bin of 575 <<_/binary-unit:8>> -> 8; 576 <<_/binary-unit:1>> -> 1 577 end. 578 579unit_opt_2(<<St:32,KO/binary>> = Bin0) -> 580 Bin = if 581 St =:= 1 -> 582 Bin0; 583 St =:= 2 -> 584 <<KO/binary>> 585 end, 586 id(Bin). 587 588unit_opt_3(A) when is_binary(A) -> 589 %% There should be no test_unit instruction after the first segment, since 590 %% we already know A is a binary and its tail will still be a binary after 591 %% matching 8 bytes from it. 592 <<Bin:8/binary, _/binary>> = A, 593 Bin. 594 595shared_sub_bins(Config) when is_list(Config) -> 596 {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0), 597 ok. 598 599sum(<<B,T/binary>>, Acc, Sum) -> 600 sum(T, [T|Acc], Sum+B); 601sum(<<>>, Last, Sum) -> {Sum,Last}. 602 603 604bin_and_float(Config) when is_list(Config) -> 605 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0), 606 607 Sz = id(1), 608 <<>> = << <<0>> || <<1:Sz/float-unit:63>> <= <<2:30>> >>, 609 610 ok. 611 612bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X), 613 is_float(Y), 614 is_float(Z) -> 615 bin_and_float(T, Sum+X*X+Y*Y+Z*Z); 616bin_and_float(<<>>, Sum) -> Sum. 617 618dec_subidentifiers(Config) when is_list(Config) -> 619 {[],<<1,2,3>>} = 620 do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2), 621 {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2), 622 {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0), 623 ok. 624 625do_dec_subidentifiers(Buffer, Av, Al, Len) -> 626 Res = dec_subidentifiers(Buffer, Av, Al, Len), 627 Res = dec_subidentifiers2(Buffer, Av, Al, Len), 628 Res = dec_subidentifiers4(Buffer, Av, Al, Len), 629 Res = dec_subidentifiers3(Buffer, Av, Al, Len). 630 631dec_subidentifiers(Buffer, _Av, Al, 0) -> 632 {lists:reverse(Al),Buffer}; 633dec_subidentifiers(<<1:1,H:7,T/binary>>, Av, Al, Len) -> 634 dec_subidentifiers(T, (Av bsl 7) bor H, Al, Len-1); 635dec_subidentifiers(<<H,T/binary>>, Av, Al, Len) -> 636 dec_subidentifiers(T, 0, [((Av bsl 7) bor H)|Al], Len-1). 637 638dec_subidentifiers2(<<Buffer/binary>>, _Av, Al, 0) -> 639 {lists:reverse(Al),Buffer}; 640dec_subidentifiers2(<<1:1,H:7,T/binary>>, Av, Al, Len) -> 641 dec_subidentifiers2(T, (Av bsl 7) bor H, Al, Len-1); 642dec_subidentifiers2(<<H,T/binary>>, Av, Al, Len) -> 643 dec_subidentifiers2(T, 0, [((Av bsl 7) bor H)|Al], Len-1). 644 645dec_subidentifiers3(Buffer, _Av, Al, 0) when is_binary(Buffer) -> 646 {lists:reverse(Al),Buffer}; 647dec_subidentifiers3(<<1:1,H:7,T/binary>>, Av, Al, Len) -> 648 dec_subidentifiers3(T, (Av bsl 7) bor H, Al, Len-1); 649dec_subidentifiers3(<<H,T/binary>>, Av, Al, Len) -> 650 dec_subidentifiers3(T, 0, [((Av bsl 7) bor H)|Al], Len-1). 651 652dec_subidentifiers4(<<1:1,H:7,T/binary>>, Av, Al, Len) when Len =/= 0 -> 653 dec_subidentifiers4(T, (Av bsl 7) bor H, Al, Len-1); 654dec_subidentifiers4(<<H,T/binary>>, Av, Al, Len) when Len =/= 0 -> 655 dec_subidentifiers4(T, 0, [((Av bsl 7) bor H)|Al], Len-1); 656dec_subidentifiers4(Buffer, _Av, Al, 0) -> 657 {lists:reverse(Al),Buffer}. 658 659 660skip_optional_tag(Config) when is_list(Config) -> 661 {ok,<<>>} = skip_optional_tag(<<42>>, <<42>>), 662 {ok,<<>>} = skip_optional_tag(<<42,1>>, <<42,1>>), 663 {ok,<<1,2,3>>} = skip_optional_tag(<<42>>, <<42,1,2,3>>), 664 missing = skip_optional_tag(<<2:3>>, blurf), 665 ok. 666 667skip_optional_tag(<<>>, Binary) -> 668 {ok,Binary}; 669skip_optional_tag(<<Tag,RestTag/binary>>, <<Tag,Rest/binary>>) -> 670 skip_optional_tag(RestTag, Rest); 671skip_optional_tag(_, _) -> missing. 672 673decode_integer(_Config) -> 674 {10795,<<43>>,whatever} = decode_integer(1, <<42,43>>, whatever), 675 {-28909,<<19>>,whatever} = decode_integer(1, <<143,19>>, whatever), 676 ok. 677 678decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) when B1 == 0 -> 679 Bin = <<_Skip:Len/unit:8, Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>, 680 Size = byte_size(Bin), 681 <<Int:Size/unit:8>> = Bin, 682 {Int,Buffer2,RemovedBytes}; 683decode_integer(Len, <<B1:1,B2:7,Bs/binary>>, RemovedBytes) -> 684 Bin = <<_Skip:Len/unit:8,Buffer2/binary>> = <<B1:1,B2:7,Bs/binary>>, 685 Size = byte_size(Bin), 686 <<N:Size/unit:8>> = <<B2,Bs/binary>>, 687 Int = N - (1 bsl (8 * size(Bin) -1)), 688 {Int,Buffer2,RemovedBytes}. 689 690-define(DATELEN, 16). 691 692wfbm(Config) when is_list(Config) -> 693 %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski, 694 %% with modifications. 695 {nomatch,0} = check_for_dot_or_space(<<" ">>), 696 {nomatch,0} = check_for_dot_or_space(<<" abc">>), 697 {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>), 698 {nomatch,0} = check_for_dot_or_space(<<".gurka">>), 699 {nomatch,1} = check_for_dot_or_space(<<"g.urka">>), 700 701 nomatch = get_tail(<<>>), 702 {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>), 703 {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>), 704 nomatch = get_tail(<<"200y.2007.10.23.blurf ">>), 705 {'EXIT',_} = (catch get_tail({no,binary,at,all})), 706 {'EXIT',_} = (catch get_tail(no_binary)), 707 ok. 708 709check_for_dot_or_space(Bin) -> 710 check_for_dot_or_space(Bin, 0). 711 712check_for_dot_or_space(<<$\s, _/binary>>, 0) -> 713 {nomatch,0}; 714check_for_dot_or_space(Bin, Len) -> 715 case Bin of 716 <<Front:Len/binary, $\s, _/binary>> -> 717 {ok,Front}; 718 <<_:Len/binary, $., _/binary>> -> 719 {nomatch,Len}; 720 _ -> 721 check_for_dot_or_space(Bin, Len+1) 722 end. 723 724get_tail(<<>>) -> 725 nomatch; 726get_tail(Bin) -> 727 <<Front:?DATELEN/binary, Tail/binary>> = Bin, 728 case Front of 729 <<_:3/binary,"x/",Y:4/binary,$/,M:2/binary,$/,D:2/binary,$/>> -> 730 case check_for_dot_or_space(Tail) of 731 {ok,Match} -> 732 {ok,<<Y/binary,$/,M/binary,$/,D/binary,$/, Match/binary>>}; 733 {nomatch,Skip} -> {skip,?DATELEN + Skip} 734 end; 735 _ -> nomatch 736 end. 737 738degenerated_match(Config) when is_list(Config) -> 739 error = degenerated_match_1(<<>>), 740 1 = degenerated_match_1(<<1:1>>), 741 2 = degenerated_match_1(<<42,43>>), 742 743 error = degenerated_match_2(<<>>), 744 no_split = degenerated_match_2(<<1,2>>), 745 {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>), 746 747 ok. 748 749degenerated_match_1(<<>>) -> error; 750degenerated_match_1(Bin) -> byte_size(Bin). 751 752degenerated_match_2(<<>>) -> error; 753degenerated_match_2(Bin) -> 754 case byte_size(Bin) > 4 of 755 true -> 756 split_binary(Bin, 4); 757 false -> 758 no_split 759 end. 760 761bs_sum(Config) when is_list(Config) -> 762 0 = bs_sum_1([]), 763 0 = bs_sum_1(<<>>), 764 42 = bs_sum_1([42]), 765 1 = bs_sum_1(<<1>>), 766 10 = bs_sum_1([1,2,3,4]), 767 15 = bs_sum_1(<<1,2,3,4,5>>), 768 21 = bs_sum_1([1,2,3|<<4,5,6>>]), 769 15 = bs_sum_1([1,2,3|{4,5}]), 770 6 = bs_sum_1([1,2,3|zero]), 771 6 = bs_sum_1([1,2,3|0]), 772 7 = bs_sum_1([1,2,3|one]), 773 774 fc(catch bs_sum_1({too,big,tuple})), 775 fc(catch bs_sum_1([1,2,3|{too,big,tuple}])), 776 777 [] = sneaky_alias(<<>>), 778 [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)), 779 fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))), 780 fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))), 781 ok. 782 783bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T); 784bs_sum_1([H|T]) -> H+bs_sum_1(T); 785bs_sum_1({A,B}=_Tuple=_AliasForNoGoodReason) -> A+B; 786bs_sum_1(0) -> 0; 787bs_sum_1(zero=_Zero) -> 0; 788bs_sum_1(one) -> 1; 789bs_sum_1([]) -> 0; 790bs_sum_1(<<>>) -> 0. 791 792sneaky_alias(<<>>=L) -> binary_to_list(L); 793sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)]. 794 795coverage(Config) when is_list(Config) -> 796 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>), 797 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>), 798 fc(catch coverage_fold(fun(B, A) -> 799 A+B 800 end, 0, [a,b,c])), 801 802 {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float), 803 {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple), 804 {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} = 805 coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}), 806 807 [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []), 808 809 {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}), 810 811 [42] = coverage_apply(<<42>>, [coverage_id]), 812 42 = coverage_external(<<42>>), 813 814 do_coverage_bin_to_term_list([]), 815 do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]), 816 fc(coverage_bin_to_term_list, [<<0,0,0,7>>], 817 catch do_coverage_bin_to_term_list_1(<<7:32>>)), 818 819 <<>> = coverage_per_key(<<4:32>>), 820 <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>), 821 822 binary = coverage_bitstring(<<>>), 823 binary = coverage_bitstring(<<7>>), 824 bitstring = coverage_bitstring(<<7:4>>), 825 other = coverage_bitstring([a]), 826 827 %% Cover code in beam_trim. 828 829 {done,<<17,53>>,[253,155,200]} = 830 coverage_trim(<<253,155,200,17,53>>, e0, e1, e2, e3, []), 831 832 <<"(right|linux)">> = coverage_trim_1(<<"">>, <<"right">>, <<"linux">>), 833 <<"/(right|linux)">> = coverage_trim_1(<<"/">>, <<"right">>, <<"linux">>), 834 <<"(left|linux)/(right|linux)">> = 835 coverage_trim_1(<<"left">>, <<"right">>, <<"linux">>), 836 837 {10,<<"-">>,""} = coverage_trim_2(<<"-">>, 10, []), 838 {8,<<"-">>,"aa"} = coverage_trim_2(<<"aa-">>, 10, []), 839 840 {<<"abc">>,<<"tag">>} = coverage_trim_3([<<"abc","tag">>], 3), 841 842 %% Cover code in beam_ssa_codegen. 843 ok = coverage_beam_ssa_codegen(<<2>>), 844 845 ok. 846 847coverage_fold(Fun, Acc, <<H,T/binary>>) -> 848 IdFun = fun id/1, 849 coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T); 850coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc. 851 852coverage_build(Acc0, <<H,T/binary>>, float) -> 853 Float = id(<<H:64/float>>), 854 Acc = <<Acc0/binary,Float/binary>>, 855 coverage_build(Acc, T, float); 856coverage_build(Acc0, <<H,T/binary>>, Tuple0) -> 857 Str = id(<<H:(id(4)),(H-1):4,"abc">>), 858 Acc = id(<<Acc0/bitstring,Str/bitstring>>), 859 Tuple = setelement(2, setelement(3, Tuple0, 43), 42), 860 if 861 byte_size(Acc) > 0 -> 862 coverage_build(Acc, T, Tuple) 863 end; 864coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}. 865 866coverage_bc(<<H,T/binary>>, Acc) -> 867 B = << <<C:8>> || C <- [H] >>, 868 coverage_bc(T, [B|Acc]); 869coverage_bc(<<>>, Acc) -> Acc. 870 871coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x -> 872 setelement(H, Tuple, T1). 873 874coverage_apply(<<H,T/binary>>, [F|Fs]) -> 875 [?MODULE:F(H)|coverage_apply(T, Fs)]; 876coverage_apply(<<>>, []) -> []. 877 878coverage_external(<<H,T/binary>>) -> 879 ?MODULE:coverage_external_ignore(T, T), 880 H. 881 882coverage_external_ignore(_, _) -> 883 ok. 884 885coverage_id(I) -> id(I). 886 887do_coverage_bin_to_term_list(L) -> 888 Bin = << <<(begin BinTerm = term_to_binary(Term), 889 <<(byte_size(BinTerm)):32,BinTerm/binary>> end)/binary>> || 890 Term <- L >>, 891 L = do_coverage_bin_to_term_list_1(Bin), 892 L = do_coverage_bin_to_term_list_1(<<Bin/binary,7:32,"garbage">>), 893 L = do_coverage_bin_to_term_list_1(<<7:32,"garbage",Bin/binary>>). 894 895do_coverage_bin_to_term_list_1(Bin) -> 896 Res = coverage_bin_to_term_list(Bin), 897 Res = coverage_bin_to_term_list(Bin, []), 898 Res = coverage_bin_to_term_list_catch(Bin), 899 Res = coverage_bin_to_term_list_catch(Bin, []). 900 901coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>) -> 902 try binary_to_term(BinTerm) of 903 Term -> [Term|coverage_bin_to_term_list(T)] 904 catch 905 error:badarg -> coverage_bin_to_term_list(T) 906 end; 907coverage_bin_to_term_list(<<>>) -> []. 908 909coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) -> 910 try binary_to_term(BinTerm) of 911 Term -> coverage_bin_to_term_list(T, [Term|Acc]) 912 catch 913 error:badarg -> coverage_bin_to_term_list(T, Acc) 914 end; 915coverage_bin_to_term_list(<<>>, Acc) -> lists:reverse(Acc). 916 917coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>) -> 918 case catch binary_to_term(BinTerm) of 919 {'EXIT',_} -> coverage_bin_to_term_list_catch(T); 920 Term -> [Term|coverage_bin_to_term_list_catch(T)] 921 end; 922coverage_bin_to_term_list_catch(<<>>) -> []. 923 924coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) -> 925 case catch binary_to_term(BinTerm) of 926 {'EXIT',_} -> coverage_bin_to_term_list_catch(T, Acc); 927 Term -> coverage_bin_to_term_list_catch(T, [Term|Acc]) 928 end; 929coverage_bin_to_term_list_catch(<<>>, Acc) -> lists:reverse(Acc). 930 931coverage_per_key(<<BinSize:32,Bin/binary>> = B) -> 932 true = (byte_size(B) =:= BinSize), 933 Bin. 934 935coverage_bitstring(Bin) when is_binary(Bin) -> binary; 936coverage_bitstring(<<_/bitstring>>) -> bitstring; 937coverage_bitstring(_) -> other. 938 939coverage_trim(<<C:8,T/binary>> = Bin, E0, E1, E2, E3, Acc) -> 940 case id(C > 128) of 941 true -> 942 coverage_trim(T, E0, E1, E2, E3, [C|Acc]); 943 false -> 944 {done,Bin,lists:reverse(Acc)} 945 end. 946 947coverage_trim_1(<<>>, Right, OsType) -> 948 do_coverage_trim_1(Right, OsType); 949coverage_trim_1(<<"/">>, Right, OsType) -> 950 <<"/",(do_coverage_trim_1(Right, OsType))/binary>>; 951coverage_trim_1(Left, Right, OsType) -> 952 <<(do_coverage_trim_1(Left, OsType))/binary, 953 "/", 954 (do_coverage_trim_1(Right, OsType))/binary>>. 955 956do_coverage_trim_1(A, OsType) -> 957 <<"(",A/binary,"|",OsType/binary,")">>. 958 959coverage_trim_2(<<C/utf8,R/binary>> = Bin, I, L) -> 960 case printable_char(C) of 961 true -> 962 coverage_trim_2(R, I - 1, [C | L]); 963 false -> 964 {I,Bin,lists:reverse(L)} 965 end. 966 967coverage_trim_3(CipherTextFragment, TagLen) -> 968 CipherLen = iolist_size(CipherTextFragment) - TagLen, 969 <<CipherText:CipherLen/bytes, CipherTag:TagLen/bytes>> = 970 iolist_to_binary(CipherTextFragment), 971 {CipherText, CipherTag}. 972 973printable_char($a) -> true; 974printable_char(_) -> false. 975 976coverage_beam_ssa_codegen(Bin) -> 977 %% With +r21 there will be a copy instruction that copies 978 %% a map literal to an x register, thus covering a line 979 %% beam_ssa_codegen:opt_allocate_defs/2. 980 case #{1 => 42} of 981 #{1 := 42} -> 982 << <<0>> || <<2>> <= Bin >> 983 end, 984 ok. 985 986multiple_uses(Config) when is_list(Config) -> 987 {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>), 988 true = multiple_uses_2(<<0,0,197,18>>), 989 <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1), 990 991 ok = first_after(<<>>, 42), 992 <<1>> = first_after(<<1,2,3>>, 0), 993 <<2>> = first_after(<<1,2,3>>, 1), 994 995 ok. 996 997multiple_uses_1(<<X:16,Tail/binary>>) -> 998 %% NOT OPTIMIZED: sub binary is matched or used in more than one place 999 {Y,Z} = multiple_uses_match(Tail), 1000 {X,Y,Z,Tail}. 1001 1002multiple_uses_2(<<_:16,Tail/binary>>) -> 1003 %% NOT OPTIMIZED: sub binary is matched or used in more than one place 1004 multiple_uses_cmp(Tail, Tail). 1005 1006multiple_uses_3(<<_:16,Tail/binary>>, Fun) -> 1007 %% NOT OPTIMIZED: sub binary is used or returned 1008 Fun(Tail). 1009 1010multiple_uses_match(<<Y:16,Z:16>>) -> 1011 {Y,Z}. 1012 1013multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true; 1014multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false. 1015 1016first_after(Data, Offset) -> 1017 case byte_size(Data) > Offset of 1018 false -> 1019 {_First, _Rest} = {ok, ok}, 1020 ok; 1021 true -> 1022 <<_:Offset/binary, Rest/binary>> = Data, 1023 %% 'Rest' saved in y(0) before the call. 1024 {First, _} = match_first(Data, Rest), 1025 %% When beam_bsm sees the code, the following line 1026 %% which uses y(0) has been optimized away. 1027 {First, Rest} = {First, Rest}, 1028 First 1029 end. 1030 1031match_first(_, <<First:1/binary, Rest/binary>>) -> 1032 {First, Rest}. 1033 1034zero_label(Config) when is_list(Config) -> 1035 <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>), 1036 <<"CE">> = read_pols(<<"noFACE">>), 1037 ok. 1038 1039read_pols(Data) -> 1040 <<PolygonType:4/binary,Rest/binary>> = Data, 1041 %% Intentional warning. 1042 (PolygonType == <<"FACE">>) or (PolygonType == <<"PTCH">>), 1043 Rest. 1044 1045followed_by_catch(Config) when is_list(Config) -> 1046 ok = handle(<<0,1,2,3,4,5>>). 1047 1048-record(rec,{field}). 1049handle(<<>>) -> ok; 1050handle(Msg) -> 1051 <<_DataLen:16, Rest/binary>> = Msg, 1052 case catch fooX:func() of 1053 [X] -> 1054 X#rec.field; 1055 _ -> 1056 ok 1057 end, 1058 handle(Rest). 1059 1060matching_meets_construction(Config) when is_list(Config) -> 1061 Bin = id(<<"abc">>), 1062 Len = id(2), 1063 Tail0 = id(<<1,2,3,4,5>>), 1064 <<_:Len/binary,Tail/binary>> = Tail0, 1065 Res = <<Tail/binary,Bin/binary>>, 1066 <<3,4,5,"abc">> = Res, 1067 {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)), 1068 {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)), 1069 <<"Bbc">> = matching_meets_construction_3(<<"Abc">>), 1070 1071 <<1,2>> = encode_octet_string(<<1,2,3>>, 2), 1072 ok. 1073 1074matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>. 1075 1076matching_meets_construction_2(<<"A",H/binary>>) -> <<"B",H/float>>. 1077 1078matching_meets_construction_3(<<"A",H/binary>>) -> <<"B",H/binary>>. 1079 1080encode_octet_string(<<OctetString/binary>>, Len) -> 1081 <<OctetString:Len/binary-unit:8>>. 1082 1083simon(Config) when is_list(Config) -> 1084 one = simon(blurf, <<>>), 1085 two = simon(0, <<42>>), 1086 fc(simon, [17,<<1>>], catch simon(17, <<1>>)), 1087 fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)), 1088 1089 one = simon2(blurf, <<9>>), 1090 two = simon2(0, <<9,1>>), 1091 fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)), 1092 ok. 1093 1094simon(_, <<>>) -> one; 1095simon(0, <<_>>) -> two. 1096 1097simon2(_, <<9>>) -> one; 1098simon2(0, <<_:16>>) -> two. 1099 1100 1101%% OTP-7113: Crash in v3_codegen. 1102matching_and_andalso(Config) when is_list(Config) -> 1103 ok = matching_and_andalso_1(<<1,2,3>>, 3), 1104 {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)), 1105 {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)), 1106 {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)), 1107 1108 {"abc",<<"xyz">>} = matching_and_andalso_23("abc", <<"-xyz">>), 1109 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($a-1)>>), 1110 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($z+1)>>), 1111 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($A-1)>>), 1112 {"abc",<<"">>} = matching_and_andalso_23("abc", <<($Z+1)>>), 1113 error = matching_and_andalso_23([], <<>>), 1114 error = matching_and_andalso_23([], <<$A>>), 1115 error = matching_and_andalso_23([], <<$Z>>), 1116 error = matching_and_andalso_23([], <<$a>>), 1117 error = matching_and_andalso_23([], <<$z>>), 1118 ok. 1119 1120matching_and_andalso_1(<<Bitmap/binary>>, K) 1121 when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K -> 1122 ok. 1123 1124matching_and_andalso_23(Datetime, Bin) -> 1125 Res = matching_and_andalso_2(Datetime, Bin), 1126 Res = matching_and_andalso_3(Datetime, Bin), 1127 Res. 1128 1129matching_and_andalso_2(Datetime, <<H,T/binary>>) 1130 when not ((H >= $a) andalso (H =< $z)) andalso 1131 not ((H >= $A) andalso (H =< $Z)) -> 1132 {Datetime,T}; 1133matching_and_andalso_2(_, _) -> error. 1134 1135%% Contrived example to ensure we cover the handling of 'call' instructions 1136%% in v3_codegen:bsm_rename_ctx/4. 1137matching_and_andalso_3(Datetime, <<H,T/binary>>) 1138 when not ((abs(H) >= $a) andalso (abs(H) =< $z)) andalso 1139 not ((abs(H) >= $A) andalso (abs(H) =< $Z)) -> 1140 {Datetime,T}; 1141matching_and_andalso_3(_, _) -> error. 1142 1143%% Thanks to Tomas Stejskal. 1144otp_7188(Config) when is_list(Config) -> 1145 MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0, 1146 0,0,0,0,0,0,0,0,0,0,0,0,0,68,97,110,105,101,108,32,76, 1147 97,110,100,97,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66, 1148 101,115,116,32,79,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1149 0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115, 1150 116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 1151 32,32,12>>, 1152 {ok,{"ID3v1", 1153 [{title,<<68,117,154,105,232,107,121>>}, 1154 {artist,<<"Daniel Landa">>}, 1155 {album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3). 1156 1157parse_v1_or_v11_tag(<<"TAG", Title:30/binary, 1158 Artist:30/binary, Album:30/binary, 1159 _Year:4/binary, _Comment:28/binary, 1160 0:8, Track:8, _Genre:8>>) -> 1161 {ok, 1162 {"ID3v1.1", 1163 [{track, Track}, {title, trim(Title)}, 1164 {artist, trim(Artist)}, {album, trim(Album)}]}}; 1165parse_v1_or_v11_tag(<<"TAG", Title:30/binary, 1166 Artist:30/binary, Album:30/binary, 1167 _Year:4/binary, _Comment:30/binary, 1168 _Genre:8>>) -> 1169 {ok, 1170 {"ID3v1", 1171 [{title, trim(Title)}, 1172 {artist, trim(Artist)}, 1173 {album, trim(Album)}]}}; 1174parse_v1_or_v11_tag(_) -> 1175 error. 1176 1177trim(Bin) -> 1178 list_to_binary(trim_blanks(binary_to_list(Bin))). 1179 1180trim_blanks(L) -> 1181 lists:reverse(skip_blanks_and_zero(lists:reverse(L))). 1182 1183skip_blanks_and_zero([$\s|T]) -> 1184 skip_blanks_and_zero(T); 1185skip_blanks_and_zero([0|T]) -> 1186 skip_blanks_and_zero(T); 1187skip_blanks_and_zero(L) -> 1188 L. 1189 1190%% OTP-7233. Record and binary matching optimizations clashed. 1191%% Thanks to Vladimir Klebansky. 1192 1193-record(rec_otp_7233, {key, val}). 1194 1195otp_7233(Config) when is_list(Config) -> 1196 otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}), 1197 [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format), 1198 erase(io_format), 1199 otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}), 1200 undefined = get(io_format), 1201 ok. 1202 1203otp_7233_1(Rec) -> 1204 <<K:2/binary,_Rest:5/binary>> = Rec#rec_otp_7233.key, 1205 case K of 1206 <<"XX">> -> 1207 Value = Rec#rec_otp_7233.val, 1208 case lists:keyfind("xxxxxxxx", 1, Value) of 1209 false -> 1210 ok; 1211 T -> 1212 put(io_format, [Rec#rec_otp_7233.key,T]) 1213 end; 1214 _ -> ok 1215 end. 1216 1217 1218otp_7240(Config) when is_list(Config) -> 1219 a = otp_7240_a(0, <<>>), 1220 b = otp_7240_a(1, 2), 1221 1222 a = otp_7240_b(anything, <<>>), 1223 b = otp_7240_b(1, {x,y}), 1224 1225 a = otp_7240_c(anything, <<>>), 1226 b = otp_7240_c(1, <<2>>), 1227 1228 a = otp_7240_d(anything, <<>>), 1229 b = otp_7240_d(again, <<2>>), 1230 1231 a = otp_7240_e(anything, <<>>), 1232 b = otp_7240_e(1, 41), 1233 1234 a = otp_7240_f(anything, <<>>), 1235 b = otp_7240_f(1, {}), 1236 1237 ok. 1238 1239otp_7240_a(_, <<>>) -> a; 1240otp_7240_a(1, 2) -> b. 1241 1242otp_7240_b(_, <<>>) -> a; 1243otp_7240_b(1, {_,_}) -> b. 1244 1245otp_7240_c(_, <<>>) -> a; 1246otp_7240_c(1, <<2>>) -> b. 1247 1248otp_7240_d(_, <<>>) -> a; 1249otp_7240_d(_, <<2>>) -> b. 1250 1251otp_7240_e(_, <<>>) -> a; 1252otp_7240_e(1, B) when B < 42 -> b. 1253 1254otp_7240_f(_, <<>>) -> a; 1255otp_7240_f(1, B) when is_tuple(B) -> b. 1256 1257otp_7498(Config) when is_list(Config) -> 1258 <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0), 1259 <<2,3>> = otp_7498_foo(<<1,2,3>>, 1), 1260 <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2), 1261 1262 <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0), 1263 <<2,3>> = otp_7498_bar(<<1,2,3>>, 1), 1264 <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2), 1265 <<>> = otp_7498_bar(<<>>, 2), 1266 <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3), 1267 1268 ok. 1269 1270otp_7498_foo(Bin, 0) -> 1271 otp_7498_foo(Bin, 42); 1272otp_7498_foo(<<_A, Rest/bitstring>>, 1) -> 1273 otp_7498_foo(Rest, 43); 1274otp_7498_foo(Bin, _I) -> 1275 Bin. 1276 1277otp_7498_bar(Bin, 0) -> 1278 otp_7498_bar(Bin, 42); 1279otp_7498_bar(<<_A, Rest/bitstring>>, 1) -> 1280 otp_7498_bar(Rest, 43); 1281otp_7498_bar(<<>>, 2) -> 1282 otp_7498_bar(<<>>, 44); 1283otp_7498_bar(Bin, _I) -> 1284 Bin. 1285 1286 1287match_string(Config) when is_list(Config) -> 1288 %% To make sure that native endian really is handled correctly 1289 %% (i.e. that the compiler does not attempt to use bs_match_string/4 1290 %% instructions for native segments), running this test is not enough. 1291 %% Either examine the generated for do_match_string_native/1 or 1292 %% check the coverage for the v3_kernel module. 1293 case erlang:system_info(endian) of 1294 little -> 1295 do_match_string_native(<<$a,0,$b,0>>); 1296 big -> 1297 do_match_string_native(<<0,$a,0,$b>>) 1298 end, 1299 1300 do_match_string_big(<<0,$a,0,$b>>), 1301 do_match_string_little(<<$a,0,$b,0>>), 1302 1303 do_match_string_big_signed(<<255,255>>), 1304 do_match_string_little_signed(<<255,255>>), 1305 1306 plain = no_match_string_opt(<<"abc">>), 1307 strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>), 1308 1309 ok. 1310 1311do_match_string_native(<<$a:16/native,$b:16/native>>) -> ok. 1312 1313do_match_string_big(<<$a:16/big,$b:16/big>>) -> ok. 1314 1315do_match_string_little(<<$a:16/little,$b:16/little>>) -> ok. 1316 1317do_match_string_big_signed(<<(-1):16/signed>>) -> ok. 1318 1319do_match_string_little_signed(<<(-1):16/little-signed>>) -> ok. 1320 1321no_match_string_opt(<<"abc">>) -> plain; 1322no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange. 1323 1324 1325%% OTP-7591: A zero-width segment in matching would crash the compiler. 1326 1327zero_width(Config) when is_list(Config) -> 1328 <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>, 1329 2 = Len, 1330 Str = <<"hi">>, 1331 1332 %% Match sure that values that cannot fit in a segment will not match. 1333 case id(<<0:8>>) of 1334 <<256:8>> -> ct:fail(should_not_match); 1335 _ -> ok 1336 end, 1337 1338 %% Would crash in the segment squeezing functions in v3_kernel. 1339 F = fun (<<42>>) -> star; 1340 (<<V:0>>) -> V; 1341 (_) -> no_match 1342 end, 1343 star = F(<<42>>), 1344 0 = F(<<>>), 1345 no_match = F(<<1>>), 1346 no_match = F(whatever), 1347 1348 ok. 1349 1350 1351%% OTP_7650: A invalid size for binary segments could crash the compiler. 1352bad_size(Config) when is_list(Config) -> 1353 Tuple = {a,b,c}, 1354 Binary = <<1,2,3>>, 1355 Atom = an_atom, 1356 NaN = <<(-1):32>>, 1357 1358 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)), 1359 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)), 1360 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Atom>> = id(<<>>)), 1361 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:3.14>> = id(<<>>)), 1362 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:"ZJV">> = id(<<>>)), 1363 {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:(-1)>> = id(<<>>)), 1364 1365 {'EXIT',{{badmatch,<<>>},_}} = (catch <<42.0:Tuple/float>> = id(<<>>)), 1366 {'EXIT',{{badmatch,<<>>},_}} = (catch <<42.0:Binary/float>> = id(<<>>)), 1367 {'EXIT',{{badmatch,<<>>},_}} = (catch <<42.0:Atom/float>> = id(<<>>)), 1368 {'EXIT',{{badmatch,<<>>},_}} = (catch <<42.0:2.5/float>> = id(<<>>)), 1369 {'EXIT',{{badmatch,<<>>},_}} = (catch <<42.0:1/float>> = id(<<>>)), 1370 {'EXIT',{{badmatch,NaN},_}} = (catch <<42.0:32/float>> = id(NaN)), 1371 1372 %% Matched out value is ignored. 1373 {'EXIT',{{badmatch,<<>>},_}} = (catch <<_:Binary>> = id(<<>>)), 1374 {'EXIT',{{badmatch,<<>>},_}} = (catch <<_:Tuple>> = id(<<>>)), 1375 {'EXIT',{{badmatch,<<>>},_}} = (catch <<_:Atom>> = id(<<>>)), 1376 {'EXIT',{{badmatch,<<>>},_}} = (catch <<_:2.5>> = id(<<>>)), 1377 {'EXIT',{{badmatch,<<1:1>>},_}} = (catch <<_:1/float>> = id(<<1:1>>)), 1378 {'EXIT',{{badmatch,NaN},_}} = (catch <<_:32/float>> = id(NaN)), 1379 1380 no_match = bad_all_size(<<>>), 1381 no_match = bad_all_size(<<1,2,3>>), 1382 1383 true = bad_size_1(<<0>>), 1384 error = bad_size_1(<<0,1>>), 1385 1386 ok. 1387 1388bad_all_size(Bin) -> 1389 Res = bad_all_size_1(Bin), 1390 Res = bad_all_size_2(Bin), 1391 Res = bad_all_size_3(Bin), 1392 Res = bad_all_size_4(Bin), 1393 Res = bad_all_size_5(Bin), 1394 Res = bad_all_size_6(Bin), 1395 Res. 1396 1397bad_all_size_1(Bin) -> 1398 case Bin of 1399 <<B:all/binary>> -> B; 1400 _ -> no_match 1401 end. 1402 1403bad_all_size_2(Bin) -> 1404 case Bin of 1405 <<_:all/binary>> -> ok; 1406 _ -> no_match 1407 end. 1408 1409bad_all_size_3(Bin) -> 1410 All = all, 1411 case Bin of 1412 <<B:All/binary>> -> B; 1413 _ -> no_match 1414 end. 1415 1416bad_all_size_4(Bin) -> 1417 All = all, 1418 case Bin of 1419 <<_:All/binary>> -> ok; 1420 _ -> no_match 1421 end. 1422 1423bad_all_size_5(Bin) -> 1424 All = case 0 of 1425 0 -> all 1426 end, 1427 case Bin of 1428 <<B:All/binary>> -> B; 1429 _ -> no_match 1430 end. 1431 1432bad_all_size_6(Bin) -> 1433 All = case 0 of 1434 0 -> all 1435 end, 1436 case Bin of 1437 <<_:All/binary>> -> ok; 1438 _ -> no_match 1439 end. 1440 1441bad_size_1(<<0>>) -> true; 1442bad_size_1(<<0:[]>>) -> false; 1443bad_size_1(_) -> error. 1444 1445haystack(Config) when is_list(Config) -> 1446 <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>), 1447 [<<0:10/unit:8>>, 1448 <<0:20/unit:8>>] = haystack_2(<<1:8192>>), 1449 ok. 1450 1451%% Used to crash the compiler. 1452haystack_1(Haystack) -> 1453 Subs = [10], 1454 [begin 1455 <<B:Y/binary>> = Haystack, 1456 B 1457 end || Y <- Subs], 1458 Haystack. 1459 1460%% There would be an incorrect badmatch exception. 1461haystack_2(Haystack) -> 1462 Subs = [{687,10},{369,20}], 1463 [begin 1464 <<_:X/binary,B:Y/binary,_/binary>> = Haystack, 1465 B 1466 end || {X,Y} <- Subs ]. 1467 1468fc({'EXIT',{function_clause,_}}) -> ok; 1469fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= bs_match_inline_SUITE -> ok. 1470 1471fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok; 1472fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}}) 1473 when ?MODULE =:= bs_match_inline_SUITE -> 1474 Args = tuple_to_list(ActualArgs). 1475 1476%% Cover the clause handling bs_context to binary in 1477%% beam_block:initialized_regs/2. 1478cover_beam_bool(Config) when is_list(Config) -> 1479 ok = do_cover_beam_bool(<<>>, 3), 1480 <<19>> = do_cover_beam_bool(<<19>>, 2), 1481 <<42>> = do_cover_beam_bool(<<42>>, 1), 1482 <<17>> = do_cover_beam_bool(<<13,17>>, 0), 1483 ok. 1484 1485do_cover_beam_bool(Bin, X) when X > 0 -> 1486 if 1487 X =:= 1; X =:= 2 -> 1488 Bin; 1489 true -> 1490 ok 1491 end; 1492do_cover_beam_bool(<<_,Bin/binary>>, X) -> 1493 do_cover_beam_bool(Bin, X+1). 1494 1495matched_out_size(Config) when is_list(Config) -> 1496 {253,16#DEADBEEF} = mos_int(<<8,253,16#DEADBEEF:32>>), 1497 {6,16#BEEFDEAD} = mos_int(<<3,6:3,16#BEEFDEAD:32>>), 1498 {53,16#CAFEDEADBEEFCAFE} = mos_int(<<16,53:16,16#CAFEDEADBEEFCAFE:64>>), 1499 {23,16#CAFEDEADBEEFCAFE} = mos_int(<<5,23:5,16#CAFEDEADBEEFCAFE:64>>), 1500 1501 {<<1,2,3>>,4} = mos_bin(<<3,1,2,3,4,3>>), 1502 {<<1,2,3,7>>,19,42} = mos_bin(<<4,1,2,3,7,19,4,42>>), 1503 <<1,2,3,7>> = mos_bin(<<4,1,2,3,7,"abcdefghij">>), 1504 1505 false = mos_verify_sig(not_a_binary), 1506 false = mos_verify_sig(<<>>), 1507 false = mos_verify_sig(<<42:32>>), 1508 <<"123456789">> = mos_verify_sig(<<77:32,0:77/unit:8,9:32,"123456789">>), 1509 1510 ok. 1511 1512mos_int(B) -> 1513 Res = mos_int_plain(B), 1514 Res = mos_int_list([B]), 1515 Res = mos_int_tuple({a,[B],z}), 1516 1517 Res = mos_int_mixed([B]), 1518 Res = mos_int_mixed({a,[B],z}), 1519 42 = mos_int_mixed({30,12}), 1520 no_match = mos_int_mixed([B,B,B]), 1521 1522 Res = mos_int_pats1({tag,[B]}, {0,1,2,3,4,5,6,7,8,9}), 1523 Res = mos_int_pats2({tag,[B]}, {a,a,a,a,a,a,a,a,a,a}, [z]), 1524 {I,X} = Res, 1525 Res = mos_int_pats3({tag,[B]}, [I,{X,B,X},I]), 1526 Res = mos_int_map(#{key => [B]}), 1527 Key = {my,key}, 1528 Res = mos_int_map(Key, #{Key => [B]}), 1529 {I,X,B} = mos_int_alias([[B]]), 1530 Res = {I,X}, 1531 Res = mos_int_try([B]), 1532 Res = mos_int_receive(B), 1533 Res = mos_int_fun([B]), 1534 Res = mos_int_exported(B), 1535 Res = mos_int_utf(B), 1536 Res. 1537 1538mos_int_plain(<<L,I:L,X:32>>) -> 1539 {I,X}; 1540mos_int_plain(<<L,I:L,X:64>>) -> 1541 {I,X}. 1542 1543mos_int_list([<<L,I:L,X:32>>]) -> 1544 {I,X}; 1545mos_int_list([<<L,I:L,X:64>>]) -> 1546 {I,X}. 1547 1548mos_int_tuple({a,[<<L,I:L,X:32>>],z}) -> 1549 {I,X}; 1550mos_int_tuple({a,[<<L,I:L,X:64>>],z}) -> 1551 {I,X}. 1552 1553mos_int_mixed({a,[<<L,I:L,X:32>>],z}) -> 1554 {I,X}; 1555mos_int_mixed({a,[<<L,I:L,X:64>>],z}) -> 1556 {I,X}; 1557mos_int_mixed([<<L,I:L,X:32>>]) -> 1558 {I,X}; 1559mos_int_mixed([<<L,I:L,X:64>>]) -> 1560 {I,X}; 1561mos_int_mixed({A,B}) when is_integer(A), is_integer(B) -> 1562 A + B; 1563mos_int_mixed(_) -> 1564 no_match. 1565 1566mos_int_pats1({tag,[<<L,I:L,X:32>>]}, {_,_,_,_,_,_,_,_,_,_}) -> 1567 {I,X}; 1568mos_int_pats1({tag,[<<L,I:L,X:64>>]}, {_,_,_,_,_,_,_,_,_,_}) -> 1569 {I,X}. 1570 1571mos_int_pats2({tag,[<<L,I:L,X:32>>]}, {S,S,S,S,S,S,S,S,S,S}, [_|_]) -> 1572 {I,X}; 1573mos_int_pats2({tag,[<<L,I:L,X:64>>]}, {S,S,S,S,S,S,S,S,S,S}, [_|_]) -> 1574 {I,X}. 1575 1576mos_int_pats3({tag,[<<L,I:L,X:32>>]}, [I,{X,<<L,I:L,X:32>>,X},I]) -> 1577 {I,X}; 1578mos_int_pats3({tag,[<<L,I:L,X:64>>]}, [I,{X,<<L,I:L,X:64>>,X},I]) -> 1579 {I,X}. 1580 1581mos_int_map(#{key := [<<L,I:L,X:32>>]}) -> 1582 {I,X}; 1583mos_int_map(#{key := [<<L,I:L,X:64>>]}) -> 1584 {I,X}. 1585 1586mos_int_map(Key, Map) -> 1587 case Map of 1588 #{Key := [<<L,I:L,X:32>>]} -> {I,X}; 1589 #{Key := [<<L,I:L,X:64>>]} -> {I,X} 1590 end. 1591 1592mos_int_alias([[<<L,I:L,X:32>> = B]]) -> 1593 {I,X,B}; 1594mos_int_alias([[<<L,I:L,X:64>> = B]]) -> 1595 {I,X,B}. 1596 1597mos_int_try(B) -> 1598 try id(B) of 1599 [<<L,I:L,X:32>>] -> {I,X}; 1600 [<<L,I:L,X:64>>] -> {I,X} 1601 after 1602 ok 1603 end. 1604 1605mos_int_receive(Msg) -> 1606 Res = (fun() -> 1607 self() ! Msg, 1608 receive 1609 <<L,I:L,X:32>> -> {I,X}; 1610 <<L,I:L,X:64>> -> {I,X} 1611 end 1612 end)(), 1613 self() ! Msg, 1614 Res = receive 1615 <<L,I:L,X:32>> -> {I,X}; 1616 <<L,I:L,X:64>> -> {I,X} 1617 end, 1618 self() ! {tag,[Msg]}, 1619 Res = receive 1620 {tag,[<<L,I:L,X:32>>]} -> {I,X}; 1621 {tag,[<<L,I:L,X:64>>]} -> {I,X} 1622 end, 1623 Res. 1624 1625mos_int_fun(B) -> 1626 L = ignore_me, 1627 F = fun ([<<L,I:L,X:32>>]) -> {I,X}; 1628 ([<<L,I:L,X:64>>]) -> {I,X} 1629 end, 1630 F(B). 1631 1632mos_int_exported(B) -> 1633 case B of 1634 <<L,I:L,X:32>> -> ok; 1635 <<L,I:L,X:64>> -> ok 1636 end, 1637 {I,X}. 1638 1639mos_int_utf(B0) -> 1640 B = id(<<B0/bits,777/utf8,7777/utf16,9999/utf32>>), 1641 case B of 1642 <<L,I:L,X:32,777/utf8,7777/utf16,9999/utf32>> -> {I,X}; 1643 <<L,I:L,X:64,777/utf8,7777/utf16,9999/utf32>> -> {I,X} 1644 end. 1645 1646mos_bin(B) -> 1647 Res = mos_bin_plain(B), 1648 Res = mos_bin_tuple({outer,{inner,B}}), 1649 Res. 1650 1651mos_bin_plain(<<L,Bin:L/binary,X:8,L>>) -> 1652 L = byte_size(Bin), 1653 {Bin,X}; 1654mos_bin_plain(<<L,Bin:L/binary,X:8,L,Y:8>>) -> 1655 L = byte_size(Bin), 1656 {Bin,X,Y}; 1657mos_bin_plain(<<L,Bin:L/binary,"abcdefghij">>) -> 1658 L = byte_size(Bin), 1659 Bin. 1660 1661mos_bin_tuple({outer,{inner,<<L,Bin:L/binary,X:8,L>>}}) -> 1662 L = byte_size(Bin), 1663 {Bin,X}; 1664mos_bin_tuple({outer,{inner,<<L,Bin:L/binary,X:8,L,Y:8>>}}) -> 1665 L = byte_size(Bin), 1666 {Bin,X,Y}; 1667mos_bin_tuple({outer,{inner,<<L,Bin:L/binary,"abcdefghij">>}}) -> 1668 L = byte_size(Bin), 1669 Bin. 1670 1671mos_verify_sig(AlgSig) -> 1672 try 1673 <<AlgLen:32, _Alg:AlgLen/binary, 1674 SigLen:32, Sig:SigLen/binary>> = AlgSig, 1675 Sig 1676 catch 1677 _:_ -> 1678 false 1679 end. 1680 1681follow_fail_branch(_) -> 1682 42 = ffb_1(<<0,1>>, <<0>>), 1683 8 = ffb_1(<<0,1>>, [a]), 1684 42 = ffb_2(<<0,1>>, <<0>>, 17), 1685 8 = ffb_2(<<0,1>>, [a], 0), 1686 ok. 1687 1688ffb_1(<<_,T/bitstring>>, List) -> 1689 case List of 1690 <<_>> -> 1691 42; 1692 [_|_] -> 1693 %% The fail branch of the bs_start_match2 instruction 1694 %% pointing to here would be ignored, making the compiler 1695 %% incorrectly assume that the delayed sub-binary 1696 %% optimization was safe. 1697 bit_size(T) 1698 end. 1699 1700ffb_2(<<_,T/bitstring>>, List, A) -> 1701 case List of 1702 <<_>> when A =:= 17 -> 42; 1703 [_|_] -> bit_size(T) 1704 end. 1705 1706no_partition(_) -> 1707 one = no_partition_1(<<"string">>, a1), 1708 {two,<<"string">>} = no_partition_1(<<"string">>, a2), 1709 {two,<<>>} = no_partition_1(<<>>, a2), 1710 {two,a} = no_partition_1(a, a2), 1711 three = no_partition_1(undefined, a3), 1712 {four,a,[]} = no_partition_1([a], a4), 1713 {five,a,b} = no_partition_1({a,b}, a5), 1714 1715 one = no_partition_2(<<"string">>, a1), 1716 two = no_partition_2(<<"string">>, a2), 1717 two = no_partition_2(<<>>, a2), 1718 two = no_partition_2(a, a2), 1719 three = no_partition_2(undefined, a3), 1720 four = no_partition_2(42, a4), 1721 five = no_partition_2([], a5), 1722 six = no_partition_2(42.0, a6), 1723 ok. 1724 1725no_partition_1(<<"string">>, a1) -> 1726 one; 1727no_partition_1(V, a2) -> 1728 {two,V}; 1729no_partition_1(undefined, a3) -> 1730 three; 1731no_partition_1([H|T], a4) -> 1732 {four,H,T}; 1733no_partition_1({A,B}, a5) -> 1734 {five,A,B}. 1735 1736no_partition_2(<<"string">>, a1) -> 1737 one; 1738no_partition_2(_, a2) -> 1739 two; 1740no_partition_2(undefined, a3) -> 1741 three; 1742no_partition_2(42, a4) -> 1743 four; 1744no_partition_2([], a5) -> 1745 five; 1746no_partition_2(42.0, a6) -> 1747 six. 1748 1749calling_a_binary(Config) when is_list(Config) -> 1750 [] = call_binary(<<>>, []), 1751 {'EXIT',{badarg,_}} = (catch call_binary(<<1>>, [])), 1752 {'EXIT',{badarg,_}} = (catch call_binary(<<1,2,3>>, [])), 1753 ok. 1754 1755call_binary(<<>>, Acc) -> 1756 Acc; 1757call_binary(<<H,T/bits>>, Acc) -> 1758 T(<<Acc/binary,H>>). 1759 1760binary_in_map(Config) when is_list(Config) -> 1761 ok = match_binary_in_map(#{key => <<42:8>>}), 1762 {'EXIT',{{badmatch,#{key := 1}},_}} = 1763 (catch match_binary_in_map(#{key => 1})), 1764 {'EXIT',{{badmatch,#{key := <<1023:16>>}},_}} = 1765 (catch match_binary_in_map(#{key => <<1023:16>>})), 1766 {'EXIT',{{badmatch,#{key := <<1:8>>}},_}} = 1767 (catch match_binary_in_map(#{key => <<1:8>>})), 1768 {'EXIT',{{badmatch,not_a_map},_}} = 1769 (catch match_binary_in_map(not_a_map)), 1770 ok. 1771 1772match_binary_in_map(Map) -> 1773 case 8 of 1774 N -> 1775 #{key := <<42:N>>} = Map, 1776 ok 1777 end. 1778 1779match_string_opt(Config) when is_list(Config) -> 1780 {x,<<1,2,3>>,{<<1>>,{v,<<1,2,3>>}}} = 1781 do_match_string_opt({<<1>>,{v,<<1,2,3>>}}), 1782 ok. 1783 1784do_match_string_opt({<<1>>,{v,V}}=T) -> 1785 {x,V,T}. 1786 1787select_on_integer(Config) when is_list(Config) -> 1788 42 = do_select_on_integer(<<42>>), 1789 <<"abc">> = do_select_on_integer(<<128,"abc">>), 1790 1791 {'EXIT',_} = (catch do_select_on_integer(<<0:1>>)), 1792 {'EXIT',_} = (catch do_select_on_integer(<<1:1>>)), 1793 {'EXIT',_} = (catch do_select_on_integer(<<0:1,0:15>>)), 1794 ok. 1795 1796%% The ASN.1 compiler frequently generates code like this. 1797do_select_on_integer(<<0:1,I:7>>) -> 1798 I; 1799do_select_on_integer(<<1:1,_:7,Bin/binary>>) -> 1800 Bin. 1801 1802%% If 'bin_opt_info' was given the warning would lack filename 1803%% and line number. 1804 1805map_and_binary(_Config) -> 1806 {<<"10">>,<<"37">>,<<"am">>} = do_map_and_binary(<<"10:37am">>), 1807 Map1 = #{time => "noon"}, 1808 {ok,Map1} = do_map_and_binary(Map1), 1809 Map2 = #{hour => 8, min => 42}, 1810 {8,42,Map2} = do_map_and_binary(Map2), 1811 ok. 1812 1813do_map_and_binary(<<Hour:2/bytes, $:, Min:2/bytes, Rest/binary>>) -> 1814 {Hour, Min, Rest}; 1815do_map_and_binary(#{time := _} = T) -> 1816 {ok, T}; 1817do_map_and_binary(#{hour := Hour, min := Min} = T) -> 1818 {Hour, Min, T}. 1819 1820%% Unsafe caching of branch outcomes in beam_bsm would cause the 1821%% delayed creation of sub-binaries optimization to be applied even 1822%% when it was unsafe. 1823 1824unsafe_branch_caching(_Config) -> 1825 <<>> = do_unsafe_branch_caching(<<42,1>>), 1826 <<>> = do_unsafe_branch_caching(<<42,2>>), 1827 <<>> = do_unsafe_branch_caching(<<42,3>>), 1828 <<17,18>> = do_unsafe_branch_caching(<<42,3,17,18>>), 1829 <<>> = do_unsafe_branch_caching(<<1,3,42,2>>), 1830 1831 ok. 1832 1833do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) -> 1834 <<C1/integer, B1/binary>> = Bin, 1835 case C1 of 1836 X when X =:= 1 orelse X =:= 2 -> 1837 Bin2 = <<>>; 1838 _ -> 1839 Bin2 = B1 1840 end, 1841 case Code of 1842 1 -> do_unsafe_branch_caching(Bin2); 1843 _ -> Bin2 1844 end. 1845 1846bad_literals(_Config) -> 1847 Mod = list_to_atom(?MODULE_STRING ++ "_" ++ 1848 atom_to_list(?FUNCTION_NAME)), 1849 S = [signed_lit_match(V, Sz) || V <- lists:seq(-8, 8), 1850 Sz <- [0,1,2,3]] ++ 1851 [unsigned_lit_match(V, Sz) || V <- lists:seq(-2, 8), 1852 Sz <- [0,1,2]] ++ 1853 [unicode_match(V) || 1854 V <- [-100,-1,0,1,2|lists:seq(16#10FFFC, 16#110004)]], 1855 Code = ?Q(["-module('@Mod@').\n" 1856 "-export([f/0]).\n" 1857 "f() ->\n" 1858 "_@S,\n" 1859 "ok.\n"]), 1860 merl:print(Code), 1861 Opts = test_lib:opt_opts(?MODULE), 1862 {ok,_} = merl:compile_and_load(Code, Opts), 1863 Mod:f(), 1864 1865 {'EXIT',<<42>>} = (catch bad_literals_1()), 1866 no_match = bad_literals_2(<<"abc">>), 1867 1868 Sz = id(8), 1869 {'EXIT',{{badmatch,_},_}} = (catch <<-1:Sz>> = <<-1>>), 1870 ok. 1871 1872bad_literals_1() -> 1873 BadSz = bad, 1874 case case <<42>> of 1875 <<42:BadSz>> -> ok; 1876 Val -> exit(Val) 1877 end of 1878 ok -> ok; 1879 error -> error 1880 end. 1881 1882bad_literals_2(<<atom:16>>) -> 1883 fail; 1884bad_literals_2(<<2.5:16>>) -> 1885 fail; 1886bad_literals_2(_) -> 1887 no_match. 1888 1889signed_lit_match(V, Sz) -> 1890 case <<V:Sz>> of 1891 <<V:Sz/signed>> -> 1892 ?Q("<<_@V@:_@Sz@/signed>> = <<_@V@:_@Sz@>>"); 1893 _ -> 1894 ?Q(["case <<_@V@:_@Sz@>> of\n", 1895 " <<_@V@:_@Sz@/signed>> ->\n", 1896 " ct:fail(should_not_match);\n", 1897 " _ ->\n", 1898 " ok\n", 1899 "end\n"]) 1900 end. 1901 1902unsigned_lit_match(V, Sz) -> 1903 case <<V:Sz>> of 1904 <<V:Sz/unsigned>> -> 1905 ?Q("<<_@V@:_@Sz@>> = <<_@V@:_@Sz@>>"); 1906 _ -> 1907 ?Q(["case <<_@V@:_@Sz@>> of\n", 1908 " <<_@V@:_@Sz@/unsigned>> ->\n", 1909 " ct:fail(should_not_match);\n", 1910 " _ ->\n", 1911 " ok\n", 1912 "end\n"]) 1913 end. 1914 1915unicode_match(V) -> 1916 try <<V/utf8>> of 1917 <<V/utf8>> -> 1918 ?Q(["<<_@V@/utf8>> = <<_@V@/utf8>>,\n", 1919 "<<_@V@/utf16>> = <<_@V@/utf16>>,\n", 1920 "<<_@V@/utf32>> = <<_@V@/utf32>>\n"]) 1921 catch 1922 error:badarg -> 1923 ?Q(["case <<_@V@:32>> of\n", 1924 " <<_@V@/utf32>> ->\n", 1925 " ct:fail(should_not_match);\n", 1926 " _ ->\n", 1927 " ok\n", 1928 "end\n"]) 1929 end. 1930 1931%% Test a few legal but rare cases. 1932 1933good_literals(_Config) -> 1934 Sz = id(64), 1935 1936 %% Variable size. 1937 <<42:Sz>> = id(<<42:Sz>>), 1938 <<42.0:Sz/float>> = id(<<42:Sz/float>>), 1939 1940 %% unit > 1 1941 <<16#cafebeef:4/unit:8>> = id(<<16#cafebeef:32>>), 1942 ok. 1943 1944constant_propagation(_Config) -> 1945 <<5>> = constant_propagation_a(a, <<5>>), 1946 {'EXIT',{{case_clause,b},_}} = (catch constant_propagation_a(b, <<5>>)), 1947 258 = constant_propagation_b(<<1,2>>), 1948 F = constant_propagation_c(), 1949 259 = F(<<1,3>>), 1950 ok. 1951 1952constant_propagation_a(X, Y) -> 1953 case X of 1954 a -> Y2 = 8 1955 end, 1956 <<5:Y2>> = Y. 1957 1958constant_propagation_b(B) -> 1959 Sz = 16, 1960 <<X:Sz/integer>> = B, 1961 X. 1962 1963constant_propagation_c() -> 1964 Size = 16, 1965 fun(Bin) -> 1966 <<X:Size/integer>> = Bin, 1967 X 1968 end. 1969 1970parse_xml(_Config) -> 1971 <<"<?xmlX">> = do_parse_xml(<<"<?xmlX">>), 1972 <<" ">> = do_parse_xml(<<"<?xml ">>), 1973 ok. 1974 1975do_parse_xml(<<"<?xml"/utf8,Rest/binary>> = Bytes) -> 1976 %% Delayed sub-binary creation is not safe. A buggy (development) 1977 %% version of check_liveness_everywhere() in beam_utils would turn 1978 %% on the optimization. 1979 Rest1 = case is_next_char_whitespace(Rest) of 1980 false -> 1981 Bytes; 1982 true -> 1983 id(Rest) 1984 end, 1985 id(Rest1). 1986 1987is_next_char_whitespace(<<C/utf8,_/binary>>) -> 1988 C =:= $\s. 1989 1990-record(ext_header, 1991 {this_hdr = 17, 1992 ext_hdr_opts}). 1993 1994get_payload(_Config) -> 1995 <<3445:48>> = do_get_payload(#ext_header{ext_hdr_opts = <<3445:48>>}), 1996 {'EXIT',_} = (catch do_get_payload(#ext_header{})), 1997 ok. 1998 1999do_get_payload(ExtHdr) -> 2000 _ = ExtHdr#ext_header.this_hdr, 2001 ExtHdrOptions = ExtHdr#ext_header.ext_hdr_opts, 2002 <<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts, 2003 ExtHdrOptions. 2004 2005escape(_Config) -> 2006 0 = escape(<<>>, 0), 2007 1 = escape(<<128>>, 0), 2008 2 = escape(<<128,255>>, 0), 2009 42 = escape(<<42>>, 0), 2010 50 = escape(<<42,8>>, 0), 2011 ok. 2012 2013escape(<<Byte, Rest/bits>>, Pos) when Byte >= 127 -> 2014 escape(Rest, Pos + 1); 2015escape(<<Byte, Rest/bits>>, Pos) -> 2016 escape(Rest, Pos + Byte); 2017escape(<<_Rest/bits>>, Pos) -> 2018 Pos. 2019 2020%% ERL-490 2021num_slots_different(_Config) -> 2022 Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>}, 2023 {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>}, 2024 {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>}, 2025 {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>}, 2026 {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>}, 2027 {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>}, 2028 {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}], 2029 _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts], 2030 2031 {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)), 2032 {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)), 2033 {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)), 2034 {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)), 2035 ok. 2036 2037 2038lgettext(<<"de">>, <<"default">>, <<"Remove">>) -> 2039 {ok, <<"a">>}; 2040lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) -> 2041 {ok, <<"a">>}; 2042lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) -> 2043 {ok, <<"a">>}; 2044lgettext(<<"de">>, <<"default">>, <<"Results">>) -> 2045 {ok, <<"Ergebnisse">>}; 2046lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) -> 2047 {ok, <<"a">>}; 2048lgettext(<<"de">>, <<"navigation">>, <<"Results">>) -> 2049 {ok, <<"Ergebnisse">>}; 2050lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) -> 2051 {ok, <<"Ressourcen">>}. 2052 2053%% Test more code in beam_bsm. 2054beam_bsm(_Config) -> 2055 true = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [1,0,1,1]), 2056 false = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [0]), 2057 2058 true = bsm_validate_scheme(<<>>), 2059 true = bsm_validate_scheme(<<5,10>>), 2060 false = bsm_validate_scheme(<<5,10,11,12>>), 2061 true = bsm_validate_scheme([]), 2062 true = bsm_validate_scheme([5,10]), 2063 false = bsm_validate_scheme([5,6,7]), 2064 2065 <<1,2,3>> = bsm_must_save_and_not_save(<<1,2,3>>, []), 2066 D = fun(N) -> 2*N end, 2067 [2,4|<<3>>] = bsm_must_save_and_not_save(<<1,2,3>>, [D,D]), 2068 2069 ok. 2070 2071check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) -> 2072 check_bitstring_list(T1, T2); 2073check_bitstring_list(<<>>, []) -> 2074 true; 2075check_bitstring_list(_, _) -> 2076 false. 2077 2078bsm_validate_scheme([]) -> true; 2079bsm_validate_scheme([H|T]) -> 2080 case bsm_is_scheme(H) of 2081 true -> bsm_validate_scheme(T); 2082 false -> false 2083 end; 2084bsm_validate_scheme(<<>>) -> true; 2085bsm_validate_scheme(<<H, Rest/binary>>) -> 2086 case bsm_is_scheme(H) of 2087 true -> bsm_validate_scheme(Rest); 2088 false -> false 2089 end. 2090 2091bsm_is_scheme(Int) -> 2092 Int rem 5 =:= 0. 2093 2094%% NOT OPTIMIZED: different control paths use different positions in the binary 2095bsm_must_save_and_not_save(Bin, []) -> 2096 Bin; 2097bsm_must_save_and_not_save(<<H,T/binary>>, [F|Fs]) -> 2098 [F(H)|bsm_must_save_and_not_save(T, Fs)]; 2099bsm_must_save_and_not_save(<<>>, []) -> 2100 []. 2101 2102guard(_Config) -> 2103 _Tuple = id({a,b}), 2104 ok = guard_1(<<1,2,3>>, {1,2,3}), 2105 ok = guard_2(<<42>>, #{}), 2106 ok. 2107 2108%% Cover handling of #k_put{} in v3_codegen:bsm_rename_ctx/4. 2109guard_1(<<A,B,C>>, Tuple) when Tuple =:= {A,B,C} -> 2110 ok. 2111 2112%% Cover handling of #k_call{} in v3_codegen:bsm_rename_ctx/4. 2113guard_2(<<_>>, Healing) when Healing#{[] => Healing} =:= #{[] => #{}} -> 2114 ok. 2115 2116is_ascii(_Config) -> 2117 true = do_is_ascii(<<>>), 2118 true = do_is_ascii(<<"string">>), 2119 false = do_is_ascii(<<1024/utf8>>), 2120 {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<$A,0:3>>)), 2121 {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<16#80,0:3>>)), 2122 ok. 2123 2124do_is_ascii(<<>>) -> 2125 true; 2126do_is_ascii(<<C,_/binary>>) when C >= 16#80 -> 2127 %% This clause must fail to match if the size of the argument in 2128 %% bits is not divisible by 8. Beware of unsafe optimizations. 2129 false; 2130do_is_ascii(<<_, T/binary>>) -> 2131 do_is_ascii(T). 2132 2133non_opt_eq(_Config) -> 2134 true = non_opt_eq([], <<>>), 2135 true = non_opt_eq([$a], <<$a>>), 2136 false = non_opt_eq([$a], <<$b>>), 2137 ok. 2138 2139%% An example from the Efficiency Guide. It used to be not optimized, 2140%% but now it can be optimized. 2141 2142non_opt_eq([H|T1], <<H,T2/binary>>) -> 2143 non_opt_eq(T1, T2); 2144non_opt_eq([_|_], <<_,_/binary>>) -> 2145 false; 2146non_opt_eq([], <<>>) -> 2147 true. 2148 2149%% ERL-689 2150 2151erl_689(_Config) -> 2152 {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE), 2153 {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE), 2154 {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>), 2155 {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>), 2156 ok. 2157 2158do_erl_689_1(Arg1, Arg2) -> 2159 Res = do_erl_689_1a(Arg1, Arg2), 2160 Res = do_erl_689_1b(Arg1, Arg2). 2161 2162do_erl_689_2(Arg1, Arg2) -> 2163 Res = do_erl_689_2a(Arg1, Arg2), 2164 Res = do_erl_689_2b(Arg1, Arg2). 2165 2166do_erl_689_1a(<<Length, Data/binary>>, _) -> 2167 case {Data, Length} of 2168 {_, 0} -> 2169 %% bs_context_to_binary would incorrectly set Data to the original 2170 %% binary (before matching in the function head). 2171 {{0, 0, 0}, Data}; 2172 {<<Y:16/little, M, D, Rest/binary>>, 4} -> 2173 {{Y, M, D}, Rest} 2174 end. 2175 2176do_erl_689_1b(<<Length, Data/binary>>, _) -> 2177 case {Data, Length} of 2178 {_, 0} -> 2179 %% bs_context_to_binary would incorrectly set Data to the original 2180 %% binary (before matching in the function head). 2181 id(0), 2182 {{0, 0, 0}, Data}; 2183 {<<Y:16/little, M, D, Rest/binary>>, 4} -> 2184 id(1), 2185 {{Y, M, D}, Rest} 2186 end. 2187 2188do_erl_689_2a(_, <<Length, Data/binary>>) -> 2189 case {Length, Data} of 2190 {0, _} -> 2191 %% bs_context_to_binary would incorrectly set Data to the original 2192 %% binary (before matching in the function head). 2193 {{0, 0, 0}, Data}; 2194 {4, <<Y:16/little, M, D, Rest/binary>>} -> 2195 {{Y, M, D}, Rest} 2196 end. 2197 2198do_erl_689_2b(_, <<Length, Data/binary>>) -> 2199 case {Length, Data} of 2200 {0, _} -> 2201 %% bs_context_to_binary would incorrectly set Data to the original 2202 %% binary (before matching in the function head). 2203 id(0), 2204 {{0, 0, 0}, Data}; 2205 {4, <<Y:16/little, M, D, Rest/binary>>} -> 2206 id(1), 2207 {{Y, M, D}, Rest} 2208 end. 2209 2210%% ERL-753 2211 2212bs_start_match2_defs(_Config) -> 2213 {<<"http://127.0.0.1:1234/vsaas/hello">>} = api_url(<<"hello">>), 2214 {"https://127.0.0.1:4321/vsaas/hello"} = api_url({https, "hello"}). 2215 2216api_url(URL) -> 2217 case URL of 2218 <<_/binary>> -> {<<"http://127.0.0.1:1234/vsaas/",URL/binary>>}; 2219 {https, [_|_] = URL1} -> {"https://127.0.0.1:4321/vsaas/"++URL1} 2220 end. 2221 2222check(F, R) -> 2223 R = F(). 2224 2225%% Make sure that an expression that comes between function start and a match 2226%% expression passes validation. 2227expression_before_match(Config) when is_list(Config) -> 2228 <<_,R/binary>> = id(<<0,1,2,3>>), 2229 {1, <<2,3>>} = expression_before_match_1(R), 2230 ok. 2231 2232expression_before_match_1(R) -> 2233 A = id(1), 2234 case R of 2235 <<1,Bar/binary>> -> {A, Bar}; 2236 <<>> -> {A, baz} 2237 end. 2238 2239%% Make sure that context positions are updated on calls. 2240restore_on_call(Config) when is_list(Config) -> 2241 ok = restore_on_call_plain(<<0, 1, 2>>), 2242 <<"x">> = restore_on_call_match(<<0, "x">>), 2243 ok. 2244 2245restore_on_call_plain(<<0, Rest/binary>>) -> 2246 <<2>> = restore_on_call_plain_1(Rest), 2247 %% {badmatch, <<>>} on missing restore. 2248 <<2>> = restore_on_call_plain_1(Rest), 2249 ok. 2250 2251restore_on_call_plain_1(<<1, Rest/binary>>) -> Rest; 2252restore_on_call_plain_1(Other) -> Other. 2253 2254%% Calls a function that moves the match context passed to it, and then matches 2255%% on its result to confuse the reposition algorithm's success/fail logic. 2256restore_on_call_match(<<0, Bin/binary>>) -> 2257 case skip_until_zero(Bin) of 2258 {skipped, Rest} -> 2259 Rest; 2260 not_found -> 2261 %% The match context did not get repositioned before the 2262 %% bs_get_tail instruction here. 2263 Bin 2264 end. 2265 2266skip_until_zero(<<0,Rest/binary>>) -> 2267 {skipped, Rest}; 2268skip_until_zero(<<_C,Rest/binary>>) -> 2269 skip_until_zero(Rest); 2270skip_until_zero(_) -> 2271 not_found. 2272 2273%% 'catch' must invalidate positions. 2274restore_after_catch(Config) when is_list(Config) -> 2275 <<0, 1>> = restore_after_catch_1(<<0, 1>>), 2276 ok. 2277 2278restore_after_catch_1(<<A/binary>>) -> 2279 try throw_after_byte(A) of 2280 _ -> impossible 2281 catch 2282 throw:_Any -> 2283 %% Will equal <<1>> if the bug is present. 2284 A 2285 end. 2286 2287throw_after_byte(<<_,_/binary>>) -> 2288 throw(away). 2289 2290matches_on_parameter(Config) when is_list(Config) -> 2291 %% This improves coverage for matching on "naked" parameters. 2292 {<<"urka">>, <<"a">>} = matches_on_parameter_1(<<"gurka">>), 2293 ok = (catch matches_on_parameter_2(<<"10001110101">>, 0)). 2294 2295matches_on_parameter_1(Bin) -> 2296 <<"g", A/binary>> = Bin, 2297 <<_,_,"rk", B/binary>> = Bin, 2298 {A, B}. 2299 2300matches_on_parameter_2(Bin, Offset) -> 2301 <<_:Offset, Bit:1, Rest/bits>> = Bin, 2302 case bit_size(Rest) of 2303 0 -> throw(ok); 2304 _ -> [Bit | matches_on_parameter_2(Bin, Offset + 1)] 2305 end. 2306 2307big_positions(Config) when is_list(Config) -> 2308 %% This provides coverage for when match context positions no longer fit 2309 %% into an immediate on 32-bit platforms. 2310 2311 A = <<0:((1 bsl 27) - 8), $A, 1:1, "gurka", $A>>, 2312 B = <<0:((1 bsl 27) - 8), $B, "hello", $B>>, 2313 2314 {a,$A} = bp_start_match(A), 2315 {b,$B} = bp_start_match(B), 2316 {a,$A} = bp_getpos(A), 2317 {b,$B} = bp_getpos(B), 2318 2319 ok. 2320 2321%% After the first iteration the context's position will no longer fit into an 2322%% immediate. To improve performance the bs_start_match3 instruction will 2323%% return a new context with an updated base position so that we won't have to 2324%% resort to using bigints. 2325bp_start_match(<<_:(1 bsl 27),T/bits>>) -> bp_start_match(T); 2326bp_start_match(<<1:1,"gurka",A>>) -> {a,A}; 2327bp_start_match(<<"hello",B>>) -> {b,B}. 2328 2329%% This is a corner case where the above didn't work perfectly; if the position 2330%% was _just_ small enough to fit into an immediate when bs_start_match3 was 2331%% hit, but too large at bs_get_position, then it must be saved as a bigint. 2332bp_getpos(<<_:((1 bsl 27) - 8),T/bits>>) -> bp_getpos(T); 2333bp_getpos(<<A,1:1,"gurka",A>>) -> {a,A}; 2334bp_getpos(<<B,"hello",B>>) -> {b,B}. 2335 2336matching_meets_apply(_Config) -> 2337 <<"abc">> = do_matching_meets_apply(<<"/abc">>, []), 2338 42 = do_matching_meets_apply(<<"">>, {erlang,-42}), 2339 100 = do_matching_meets_apply(no_binary, {erlang,-100}), 2340 ok. 2341 2342do_matching_meets_apply(<<$/, Rest/binary>>, _Handler) -> 2343 id(Rest); 2344do_matching_meets_apply(<<_/binary>>=Name, never_matches_a) -> 2345 %% Used to crash the compiler because variables in a remote 2346 %% were not handled properly by beam_ssa_bsm. 2347 Name:foo(gurka); 2348do_matching_meets_apply(<<_/binary>>=Name, never_matches_b) -> 2349 %% Another case of the above. 2350 foo:Name(gurka); 2351do_matching_meets_apply(_Bin, {Handler, State}) -> 2352 %% Another case of the above. 2353 Handler:abs(State). 2354 2355%% Exception handling was broken on the failure path of bs_start_match as 2356%% beam_ssa_bsm accidentally cloned and renamed the ?BADARG_BLOCK. 2357exceptions_after_match_failure(_Config) -> 2358 {'EXIT', {badarith, _}} = (catch do_exceptions_after_match_failure(atom)), 2359 ok = do_exceptions_after_match_failure(<<0, 1, "gurka">>), 2360 ok = do_exceptions_after_match_failure(2.0). 2361 2362do_exceptions_after_match_failure(<<_A, _B, "gurka">>) -> 2363 ok; 2364do_exceptions_after_match_failure(Other) -> 2365 Other / 2.0, 2366 ok. 2367 2368%% ERL-1050: After copying successors, phi nodes on the *original* path could 2369%% refer to blocks that were only reachable from the copied path. 2370bad_phi_paths(_Config) -> 2371 <<"gurka">> = bad_phi_paths_1(id(<<"gurka">>)), 2372 ok. 2373 2374bad_phi_paths_1(Arg) -> 2375 B = case Arg of 2376 <<_/binary>> -> Arg; 2377 #{} -> id(Arg) 2378 end, 2379 id(B). 2380 2381combine_empty_segments(_Config) -> 2382 <<0,1,2,3>> = combine_empty_segments_1(<<0,1,2,3>>), 2383 ok. 2384 2385combine_empty_segments_1(A) -> 2386 <<B/bits>> = A, 2387 <<C/bits>> = B, 2388 <<D/bits>> = C, 2389 D. 2390 2391%% This never finishes compiling under +no_copt. 2392hangs_forever(Config) -> 2393 true = is_function(id(fun() -> hangs_forever_1(Config) end)), 2394 ok. 2395 2396hangs_forever_1(V0) -> 2397 case hangs_forever_1(V0) of 2398 <<A:1>> -> A 2399 end. 2400 2401 2402%% ERL-1340: the unit of previously saved match positions wasn't updated. 2403bs_saved_position_units(Config) when is_list(Config) -> 2404 [<<0,1,2,3,4>>, <<5,6,7,8,9>>] = bspu_1(id(<<0,1,2,3,4,5,6,7,8,9>>)), 2405 [] = bspu_1(id(<<>>)), 2406 2407 ok. 2408 2409bspu_1(<<Bin/binary>> = Bin) -> 2410 [Chunk || <<Chunk:5/binary>> <= Bin]. 2411 2412 2413empty_matches(Config) when is_list(Config) -> 2414 {<<>>, <<1,2,3,4:4>>} = em_1(<<1,2,3,4:4>>), 2415 {<<>>, <<1,2,3>>} = em_1(<<1,2,3>>), 2416 {<<>>, <<>>} = em_1(<<>>), 2417 2418 <<0,1,0,2,0,3>> = em_2(id(<<1,2,3>>)), 2419 <<>> = em_2(id(<<>>)), 2420 2421 <<1,2,3>> = em_3(id(<<1,2,3>>)), 2422 <<>> = em_3(id(<<>>)), 2423 2424 <<Zero:0/unit:1>> = id(<<>>), 2425 0 = id(Zero), 2426 2427 ok. 2428 2429em_1(Bytes) -> 2430 {Term, Bytes} = begin 2431 <<V2@V0:0/binary-unit:8,V2@Buf1/bitstring>> = Bytes, 2432 V2@Conv2 = binary:copy(V2@V0), 2433 {V2@Conv2, V2@Buf1} 2434 end, 2435 {Term, Bytes}. 2436 2437em_2(Bin) -> 2438 << 2439 <<K,N>> || <<K:0,N>> <= Bin 2440 >>. 2441 2442%% The validator didn't agree with the type optimization pass on what the unit 2443%% of empty binary segments should be. 2444em_3(<<V:0/binary,Rest/bits>>) -> 2445 em_3_1(V), 2446 Rest. 2447 2448em_3_1(I) -> I. 2449 2450id(I) -> I. 2451 2452expand_and_squeeze(Config) when is_list(Config) -> 2453 %% UTF8 literals are expanded and then squeezed into integer16 2454 [ 2455 {test,bs_get_integer2,_,_,[_,{integer,16}|_],_} 2456 | _ 2457 ] = binary_match_to_asm([ 2458 ?Q("<<$á/utf8,_/binary>>"), 2459 ?Q("<<$é/utf8,_/binary>>") 2460 ]), 2461 2462 %% Sized integers are expanded and then squeezed into integer16 2463 [ 2464 {test,bs_get_integer2,_,_,[_,{integer,16}|_],_} 2465 | _ 2466 ] = binary_match_to_asm([ 2467 ?Q("<<0:32,_/binary>>"), 2468 ?Q("<<\"bbbb\",_/binary>>") 2469 ]), 2470 2471 %% Groups of 8 bits are squeezed into integer16 2472 [ 2473 {test,bs_get_integer2,_,_,[_,{integer,16}|_],_} 2474 | _ 2475 ] = binary_match_to_asm([ 2476 ?Q("<<\"aaaa\",_/binary>>"), 2477 ?Q("<<\"bbbb\",_/binary>>") 2478 ]), 2479 2480 %% Groups of 8 bits with empty binary are also squeezed 2481 [ 2482 {test,bs_get_integer2,_,_,[_,{integer,16}|_],_} 2483 | _ 2484 ] = binary_match_to_asm([ 2485 ?Q("<<\"aaaa\",_/binary>>"), 2486 ?Q("<<\"bbbb\",_/binary>>"), 2487 ?Q("<<>>") 2488 ]), 2489 2490 %% Groups of 8 bits with float lookup are not squeezed 2491 [ 2492 {test,bs_get_integer2,_,_,[_,{integer,8}|_],_} 2493 | _ 2494 ] = binary_match_to_asm([ 2495 ?Q("<<\"aaaa\",_/binary>>"), 2496 ?Q("<<\"bbbb\",_/binary>>"), 2497 ?Q("<<_/float>>") 2498 ]), 2499 2500 %% Groups of diverse bits go with minimum possible 2501 [ 2502 {test,bs_get_integer2,_,_,[_,{integer,8}|_],_} 2503 | _ 2504 ] = binary_match_to_asm([ 2505 ?Q("<<\"aa\",_/binary>>"), 2506 ?Q("<<\"bb\",_/binary>>"), 2507 ?Q("<<\"c\",_/binary>>") 2508 ]), 2509 2510 %% Groups of diverse bits go with minimum possible but are recursive... 2511 [ 2512 {test,bs_get_integer2,_,_,[_,{integer,8}|_],_} 2513 | RestDiverse 2514 ] = binary_match_to_asm([ 2515 ?Q("<<\"aaa\",_/binary>>"), 2516 ?Q("<<\"abb\",_/binary>>"), 2517 ?Q("<<\"c\",_/binary>>") 2518 ]), 2519 2520 %% so we still perform a 16 bits lookup for the remaining 2521 true = lists:any(fun({test,bs_get_integer2,_,_,[_,{integer,16}|_],_}) -> true; 2522 (_) -> false end, RestDiverse), 2523 2524 %% Large match is kept as is if there is a sized match later 2525 [ 2526 {test,bs_get_integer2,_,_,[_,{integer,64}|_],_} 2527 | _ 2528 ] = binary_match_to_asm([ 2529 ?Q("<<255,255,255,255,255,255,255,255>>"), 2530 ?Q("<<_:64>>") 2531 ]), 2532 2533 %% Large match is kept as is with large matches before and after 2534 [ 2535 {test,bs_get_integer2,_,_,[_,{integer,32}|_],_} 2536 | _ 2537 ] = binary_match_to_asm([ 2538 ?Q("<<A:32,_:A>>"), 2539 ?Q("<<0:32>>"), 2540 ?Q("<<_:32>>") 2541 ]), 2542 2543 %% Large match is kept as is with large matches before and after 2544 [ 2545 {test,bs_get_integer2,_,_,[_,{integer,32}|_],_} 2546 | _ 2547 ] = binary_match_to_asm([ 2548 ?Q("<<A:32,_:A>>"), 2549 ?Q("<<0,0,0,0>>"), 2550 ?Q("<<_:32>>") 2551 ]), 2552 2553 %% Large match is kept as is with smaller but still large matches before and after 2554 [ 2555 {test,bs_get_integer2,_,_,[_,{integer,32}|_],_} 2556 | _ 2557 ] = binary_match_to_asm([ 2558 ?Q("<<A:32, _:A>>"), 2559 ?Q("<<0:64>>"), 2560 ?Q("<<_:32>>") 2561 ]), 2562 2563 %% There is no squeezing for groups with more than 16 matches 2564 [ 2565 {test,bs_get_integer2,_,_,[_,{integer,8}|_],_} 2566 | _ 2567 ] = binary_match_to_asm([ 2568 ?Q("<<\"aa\", _/binary>>"), 2569 ?Q("<<\"bb\", _/binary>>"), 2570 ?Q("<<\"cc\", _/binary>>"), 2571 ?Q("<<\"dd\", _/binary>>"), 2572 ?Q("<<\"ee\", _/binary>>"), 2573 ?Q("<<\"ff\", _/binary>>"), 2574 ?Q("<<\"gg\", _/binary>>"), 2575 ?Q("<<\"hh\", _/binary>>"), 2576 ?Q("<<\"ii\", _/binary>>"), 2577 ?Q("<<\"jj\", _/binary>>"), 2578 ?Q("<<\"kk\", _/binary>>"), 2579 ?Q("<<\"ll\", _/binary>>"), 2580 ?Q("<<\"mm\", _/binary>>"), 2581 ?Q("<<\"nn\", _/binary>>"), 2582 ?Q("<<\"oo\", _/binary>>"), 2583 ?Q("<<\"pp\", _/binary>>") 2584 ]), 2585 2586 ok. 2587 2588binary_match_to_asm(Matches) -> 2589 Clauses = [ 2590 begin 2591 Ann = element(2, Match), 2592 {clause,Ann,[Match],[],[{integer,Ann,Return}]} 2593 end || {Match,Return} <- lists:zip(Matches, lists:seq(1, length(Matches))) 2594 ], 2595 2596 Module = [ 2597 {attribute,erl_anno:new(1),module,match_to_asm}, 2598 {attribute,erl_anno:new(2),export,[{example,1}]}, 2599 {function,erl_anno:new(3),example,1,Clauses} 2600 ], 2601 2602 {ok,match_to_asm,{match_to_asm,_Exports,_Attrs,Funs,_},_} = 2603 compile:forms(Module, [return, to_asm]), 2604 2605 [{function,example,1,2,AllInstructions}|_] = Funs, 2606 [{label,_},{line,_},{func_info,_,_,_},{label,_},{'%',_}, 2607 {test,bs_start_match3,_,_,_,_},{bs_get_position,_,_,_}|Instructions] = AllInstructions, 2608 Instructions. 2609 2610many_clauses(_Config) -> 2611 Mod = list_to_atom(?MODULE_STRING ++ "_" ++ 2612 atom_to_list(?FUNCTION_NAME)), 2613 Seq = lists:seq(1, 200), 2614 S = [one_clause(I) || I <- Seq], 2615 Code = ?Q(["-module('@Mod@').\n" 2616 "-export([f/1]).\n" 2617 "f(Bin) ->\n" 2618 "case Bin of\n" 2619 " dummy -> _@_@S\n" 2620 "end.\n"]), 2621 %% merl:print(Code), 2622 Opts = test_lib:opt_opts(?MODULE), 2623 {ok,_} = merl:compile_and_load(Code, Opts), 2624 _ = [begin 2625 H = erlang:phash2(I), 2626 Sz = 16, 2627 <<Res0:Sz>> = <<H:Sz>>, 2628 Res = I + Res0, 2629 Res = Mod:f({I,<<Sz:8,H:Sz>>}) 2630 end || I <- Seq], 2631 ok. 2632 2633one_clause(I) -> 2634 ?Q(<<"{_@I@,<<L:8,Val:L>>} -> _@I@ + Val">>). 2635