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