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