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