1%% ``Licensed under the Apache License, Version 2.0 (the "License");
2%% you may not use this file except in compliance with the License.
3%% You may obtain a copy of the License at
4%%
5%%     http://www.apache.org/licenses/LICENSE-2.0
6%%
7%% Unless required by applicable law or agreed to in writing, software
8%% distributed under the License is distributed on an "AS IS" BASIS,
9%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10%% See the License for the specific language governing permissions and
11%% limitations under the License.
12%%
13%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
14%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
15%% AB. All Rights Reserved.''
16%%
17%%     $Id: v3_codegen.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
18%% Purpose : Code generator for Beam.
19
20%% The following assumptions have been made:
21%%
22%% 1. Matches, i.e. things with {match,M,Ret} wrappers, only return
23%% values; no variables are exported. If the match would have returned
24%% extra variables then these have been transformed to multiple return
25%% values.
26%%
27%% 2. All BIF's called in guards are gc-safe so there is no need to
28%% put thing on the stack in the guard.  While this would in principle
29%% work it would be difficult to keep track of the stack depth when
30%% trimming.
31%%
32%% The code generation uses variable lifetime information added by
33%% the v3_life module to save variables, allocate registers and
34%% move registers to the stack when necessary.
35%%
36%% We try to use a consistent variable name scheme throughout.  The
37%% StackReg record is always called Bef,Int<n>,Aft.
38
39-module(v3_codegen).
40
41%% The main interface.
42-export([module/2]).
43
44-import(lists, [member/2,keymember/3,keysort/2,keysearch/3,append/1,
45		map/2,flatmap/2,foldl/3,foldr/3,mapfoldl/3,
46		sort/1,reverse/1,reverse/2]).
47-import(v3_life, [vdb_find/2]).
48
49%%-compile([export_all]).
50
51-include("v3_life.hrl").
52
53%% Main codegen structure.
54-record(cg, {lcount=1,				%Label counter
55	     mod,				%Current module
56	     func,				%Current function
57	     finfo,				%Function info label
58	     fcode,				%Function code label
59	     btype,				%Type of bif used.
60	     bfail,				%Fail label of bif
61	     break,				%Break label
62	     recv,				%Receive label
63	     is_top_block,			%Boolean: top block or not
64	     functable = [],			%Table of local functions:
65						%[{{Name, Arity}, Label}...]
66	     in_catch=false,			%Inside a catch or not.
67	     need_frame,			%Need a stack frame.
68	     new_funs=true}).			%Generate new fun instructions.
69
70%% Stack/register state record.
71-record(sr, {reg=[],				%Register table
72	     stk=[],				%Stack table
73	     res=[]}).				%Reserved regs: [{reserved,I,V}]
74
75module({Mod,Exp,Attr,Forms}, Options) ->
76    NewFunsFlag = not member(no_new_funs, Options),
77    {Fs,St} = functions(Forms, #cg{mod=Mod,new_funs=NewFunsFlag}),
78    {ok,{Mod,Exp,Attr,Fs,St#cg.lcount}}.
79
80functions(Forms, St0) ->
81    mapfoldl(fun (F, St) -> function(F, St) end, St0#cg{lcount=1}, Forms).
82
83function({function,Name,Arity,As0,Vb,Vdb}, St0) ->
84    %%ok = io:fwrite("cg ~w:~p~n", [?LINE,{Name,Arity}]),
85    St1 = St0#cg{func={Name,Arity}},
86    {Fun,St2} = cg_fun(Vb, As0, Vdb, St1),
87    Func0 = {function,Name,Arity,St2#cg.fcode,Fun},
88    Func = bs_function(Func0),
89    {Func,St2}.
90
91%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
92
93cg_fun(Les, Hvs, Vdb, St0) ->
94    {Name,Arity} = St0#cg.func,
95    {Fi,St1} = new_label(St0),			%FuncInfo label
96    {Fl,St2} = local_func_label(Name, Arity, St1),
97    %% Create initial stack/register state, clear unused arguments.
98    Bef = clear_dead(#sr{reg=foldl(fun ({var,V}, Reg) ->
99					   put_reg(V, Reg)
100				   end, [], Hvs),
101			stk=[]}, 0, Vdb),
102    {B2,_Aft,St3} = cg_list(Les, 0, Vdb, Bef, St2#cg{btype=exit,
103						    bfail=Fi,
104						    finfo=Fi,
105						    fcode=Fl,
106						    is_top_block=true}),
107    A = [{label,Fi},{func_info,{atom,St3#cg.mod},{atom,Name},Arity},
108	 {label,Fl}|B2],
109    {A,St3}.
110
111%% cg(Lkexpr, Vdb, StackReg, State) -> {[Ainstr],StackReg,State}.
112%%  Generate code for a kexpr.
113%%  Split function into two steps for clarity, not efficiency.
114
115cg(Le, Vdb, Bef, St) ->
116    cg(Le#l.ke, Le, Vdb, Bef, St).
117
118cg({block,Es}, Le, Vdb, Bef, St) ->
119    block_cg(Es, Le, Vdb, Bef, St);
120cg({match,M,Rs}, Le, Vdb, Bef, St) ->
121    match_cg(M, Rs, Le, Vdb, Bef, St);
122cg({match_fail,F}, Le, Vdb, Bef, St) ->
123    match_fail_cg(F, Le, Vdb, Bef, St);
124cg({call,Func,As,Rs}, Le, Vdb, Bef, St) ->
125    call_cg(Func, As, Rs, Le, Vdb, Bef, St);
126cg({enter,Func,As}, Le, Vdb, Bef, St) ->
127    enter_cg(Func, As, Le, Vdb, Bef, St);
128cg({bif,Bif,As,Rs}, Le, Vdb, Bef, St) ->
129    bif_cg(Bif, As, Rs, Le, Vdb, Bef, St);
130cg({receive_loop,Te,Rvar,Rm,Tes,Rs}, Le, Vdb, Bef, St) ->
131    recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St);
132cg(receive_next, Le, Vdb, Bef, St) ->
133    recv_next_cg(Le, Vdb, Bef, St);
134cg(receive_accept, _Le, _Vdb, Bef, St) -> {[remove_message],Bef,St};
135cg({'try',Ta,Vs,Tb,Evs,Th,Rs}, Le, Vdb, Bef, St) ->
136    try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St);
137cg({'catch',Cb,R}, Le, Vdb, Bef, St) ->
138    catch_cg(Cb, R, Le, Vdb, Bef, St);
139cg({set,Var,Con}, Le, Vdb, Bef, St) -> set_cg(Var, Con, Le, Vdb, Bef, St);
140cg({return,Rs}, Le, Vdb, Bef, St) -> return_cg(Rs, Le, Vdb, Bef, St);
141cg({break,Bs}, Le, Vdb, Bef, St) -> break_cg(Bs, Le, Vdb, Bef, St);
142cg({need_heap,0}, _Le, _Vdb, Bef, St) ->
143    {[],Bef,St};
144cg({need_heap,H}, _Le, _Vdb, Bef, St) ->
145    {[{test_heap,H,max_reg(Bef#sr.reg)}],Bef,St}.
146
147%% cg_list([Kexpr], FirstI, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
148
149cg_list(Kes, I, Vdb, Bef, St0) ->
150    {Keis,{Aft,St1}} =
151	flatmapfoldl(fun (Ke, {Inta,Sta}) ->
152%			     ok = io:fwrite("    %% ~p\n", [Inta]),
153%			     ok = io:fwrite("cgl:~p\n", [Ke]),
154			     {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
155%			     ok = io:fwrite("    ~p\n", [Keis]),
156%			     ok = io:fwrite("    %% ~p\n", [Intb]),
157			     {comment(Inta) ++ Keis,{Intb,Stb}}
158		     end, {Bef,St0}, need_heap(Kes, I)),
159    {Keis,Aft,St1}.
160
161%% need_heap([Lkexpr], I, BifType) -> [Lkexpr].
162%%  Insert need_heap instructions in Kexpr list.  Try to be smart and
163%%  collect them together as much as possible.
164
165need_heap(Kes0, I) ->
166    {Kes1,{H,F}} = flatmapfoldr(fun (Ke, {H0,F0}) ->
167					{Ns,H1,F1} = need_heap_1(Ke, H0, F0),
168					{[Ke|Ns],{H1,F1}}
169				end, {0,false}, Kes0),
170    %% Prepend need_heap if necessary.
171    Kes2 = need_heap_need(I, H, F) ++ Kes1,
172%     ok = io:fwrite("need_heap: ~p~n",
173% 		   [{{H,F},
174% 		     map(fun (#l{ke={match,M,Rs}}) -> match;
175% 			     (Lke) -> Lke#l.ke end, Kes2)}]),
176    Kes2.
177
178need_heap_1(#l{ke={set,_,{binary,_}},i=I}, H, F) ->
179    {need_heap_need(I, H, F),0,false};
180need_heap_1(#l{ke={set,_,Val}}, H, F) ->
181    %% Just pass through adding to needed heap.
182    {[],H + case Val of
183		{cons,_} -> 2;
184		{tuple,Es} -> 1 + length(Es);
185		{string,S} -> 2 * length(S);
186		_Other -> 0
187	    end,F};
188need_heap_1(#l{ke={call,_Func,_As,_Rs},i=I}, H, F) ->
189    %% Calls generate a need if necessary and also force one.
190    {need_heap_need(I, H, F),0,true};
191need_heap_1(#l{ke={bif,dsetelement,_As,_Rs},i=I}, H, F) ->
192    {need_heap_need(I, H, F),0,true};
193need_heap_1(#l{ke={bif,{make_fun,_,_,_,_},_As,_Rs},i=I}, H, F) ->
194    {need_heap_need(I, H, F),0,true};
195need_heap_1(#l{ke={bif,_Bif,_As,_Rs}}, H, F) ->
196    {[],H,F};
197need_heap_1(#l{i=I}, H, F) ->
198    %% Others kexprs generate a need if necessary but don't force.
199    {need_heap_need(I, H, F),0,false}.
200
201need_heap_need(_I, 0, false) -> [];
202need_heap_need(I, H, _F) -> [#l{ke={need_heap,H},i=I}].
203
204
205%% match_cg(Match, [Ret], Le, Vdb, StackReg, State) ->
206%%	{[Ainstr],StackReg,State}.
207%%  Generate code for a match.  First save all variables on the stack
208%%  that are to survive after the match.  We leave saved variables in
209%%  their registers as they might actually be in the right place.
210%%  Should test this.
211
212match_cg(M, Rs, Le, Vdb, Bef, St0) ->
213    I = Le#l.i,
214    {Sis,Int0} = adjust_stack(Bef, I, I+1, Vdb),
215    {B,St1} = new_label(St0),
216    {Mis,Int1,St2} = match_cg(M, none, Int0, St1#cg{break=B}),
217    %% Put return values in registers.
218    Reg = load_vars(Rs, Int1#sr.reg),
219    {Sis ++ Mis ++ [{label,B}],
220     clear_dead(Int1#sr{reg=Reg}, I, Vdb),
221     St2#cg{break=St1#cg.break}}.
222
223%% match_cg(Match, Fail, StackReg, State) -> {[Ainstr],StackReg,State}.
224%%  Generate code for a match tree.  N.B. there is no need pass Vdb
225%%  down as each level which uses this takes its own internal Vdb not
226%%  the outer one.
227
228match_cg(Le, Fail, Bef, St) ->
229    match_cg(Le#l.ke, Le, Fail, Bef, St).
230
231match_cg({alt,F,S}, _Le, Fail, Bef, St0) ->
232    {Tf,St1} = new_label(St0),
233    {Fis,Faft,St2} = match_cg(F, Tf, Bef, St1),
234    {Sis,Saft,St3} = match_cg(S, Fail, Bef, St2),
235    Aft = sr_merge(Faft, Saft),
236    {Fis ++ [{label,Tf}] ++ Sis,Aft,St3};
237match_cg({select,V,Scs}, _Va, Fail, Bef, St) ->
238    match_fmf(fun (S, F, Sta) ->
239		      select_cg(S, V, F, Fail, Bef, Sta) end,
240	      Fail, St, Scs);
241match_cg({guard,Gcs}, _Le, Fail, Bef, St) ->
242    match_fmf(fun (G, F, Sta) -> guard_clause_cg(G, F, Bef, Sta) end,
243	      Fail, St, Gcs);
244match_cg({block,Es}, Le, _Fail, Bef, St) ->
245    %% Must clear registers and stack of dead variables.
246    Int = clear_dead(Bef, Le#l.i, Le#l.vdb),
247    block_cg(Es, Le, Int, St).
248
249%% match_fail_cg(FailReason, Le, Vdb, StackReg, State) ->
250%%	{[Ainstr],StackReg,State}.
251%%  Generate code for the match_fail "call".  N.B. there is no generic
252%%  case for when the fail value has been created elsewhere.
253
254match_fail_cg({function_clause,As}, Le, Vdb, Bef, St) ->
255    %% Must have the args in {x,0}, {x,1},...
256    {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
257    {Sis ++ [{jump,{f,St#cg.finfo}}],
258     Int#sr{reg=clear_regs(Int#sr.reg)},St};
259match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) ->
260    R = cg_reg_arg(Term, Bef),
261    Int0 = clear_dead(Bef, Le#l.i, Vdb),
262    {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
263    {Sis ++ [{badmatch,R}],
264     Int#sr{reg=clear_regs(Int0#sr.reg)},St};
265match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) ->
266    R = cg_reg_arg(Reason, Bef),
267    Int0 = clear_dead(Bef, Le#l.i, Vdb),
268    {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
269    {Sis++[{case_end,R}],
270     Int#sr{reg=clear_regs(Bef#sr.reg)},St};
271match_fail_cg(if_clause, Le, Vdb, Bef, St) ->
272    Int0 = clear_dead(Bef, Le#l.i, Vdb),
273    {Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
274    {Sis++[if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
275match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) ->
276    R = cg_reg_arg(Reason, Bef),
277    Int0 = clear_dead(Bef, Le#l.i, Vdb),
278    {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
279    {Sis ++ [{try_case_end,R}],
280     Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
281
282
283%% block_cg([Kexpr], Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
284%% block_cg([Kexpr], Le, StackReg, St) -> {[Ainstr],StackReg,St}.
285
286block_cg(Es, Le, _Vdb, Bef, St) ->
287    block_cg(Es, Le, Bef, St).
288
289block_cg(Es, Le, Bef, St0) ->
290    case St0#cg.is_top_block of
291	false ->
292	    cg_block(Es, Le#l.i, Le#l.vdb, Bef, St0);
293	true ->
294	    {Keis,Aft,St1} = cg_block(Es, Le#l.i, Le#l.vdb, Bef,
295				      St0#cg{is_top_block=false,
296					     need_frame=false}),
297	    top_level_block(Keis, Aft, max_reg(Bef#sr.reg), St1)
298    end.
299
300cg_block([], _I, _Vdb, Bef, St0) ->
301    {[],Bef,St0};
302cg_block(Kes0, I, Vdb, Bef, St0) ->
303    {Kes2,Int1,St1} =
304	case basic_block(Kes0) of
305	    {Kes1,LastI,Args,Rest} ->
306		Ke = hd(Kes1),
307		Fb = Ke#l.i,
308		cg_basic_block(Kes1, Fb, LastI, Args, Vdb, Bef, St0);
309	    {Kes1,Rest} ->
310		cg_list(Kes1, I, Vdb, Bef, St0)
311	end,
312    {Kes3,Int2,St2} = cg_block(Rest, I, Vdb, Int1, St1),
313    {Kes2 ++ Kes3,Int2,St2}.
314
315basic_block(Kes) -> basic_block(Kes, []).
316
317basic_block([], Acc) -> {reverse(Acc),[]};
318basic_block([Le|Les], Acc) ->
319    case collect_block(Le#l.ke) of
320	include -> basic_block(Les, [Le|Acc]);
321	{block_end,As} -> {reverse(Acc, [Le]),Le#l.i,As,Les};
322	no_block -> {reverse(Acc, [Le]),Les}
323    end.
324
325collect_block({set,_,{binary,_}})    -> no_block;
326collect_block({set,_,_})             -> include;
327collect_block({call,{var,_}=Var,As,_Rs}) -> {block_end,As++[Var]};
328collect_block({call,Func,As,_Rs})   -> {block_end,As++func_vars(Func)};
329collect_block({enter,{var,_}=Var,As})-> {block_end,As++[Var]};
330collect_block({enter,Func,As})       -> {block_end,As++func_vars(Func)};
331collect_block({return,Rs})           -> {block_end,Rs};
332collect_block({break,Bs})            -> {block_end,Bs};
333collect_block({bif,_Bif,_As,_Rs})    -> include;
334collect_block(_)                     -> no_block.
335
336func_vars({remote,M,F}) when element(1, M) == var;
337			     element(1, F) == var ->
338    [M,F];
339func_vars(_) -> [].
340
341%% cg_basic_block([Kexpr], FirstI, LastI, As, Vdb, StackReg, State) ->
342%%      {[Ainstr],StackReg,State}.
343
344cg_basic_block(Kes, Fb, Lf, As, Vdb, Bef, St0) ->
345    Res = make_reservation(As, 0),
346    Regs0 = reserve(Res, Bef#sr.reg, Bef#sr.stk),
347    Stk = extend_stack(Bef, Lf, Lf+1, Vdb),
348    Int0 = Bef#sr{reg=Regs0,stk=Stk,res=Res},
349    X0_v0 = x0_vars(As, Fb, Lf, Vdb),
350    {Keis,{Aft,_,St1}} =
351	flatmapfoldl(fun(Ke, St) -> cg_basic_block(Ke, St, Lf, Vdb) end,
352		     {Int0,X0_v0,St0}, need_heap(Kes, Fb)),
353    {Keis,Aft,St1}.
354
355cg_basic_block(Ke, {Inta,X0v,Sta}, _Lf, Vdb) when element(1, Ke#l.ke) =:= need_heap ->
356    {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
357    {comment(Inta) ++ Keis, {Intb,X0v,Stb}};
358cg_basic_block(Ke, {Inta,X0_v1,Sta}, Lf, Vdb) ->
359    {Sis,Intb} = save_carefully(Inta, Ke#l.i, Lf+1, Vdb),
360    {X0_v2,Intc} = allocate_x0(X0_v1, Ke#l.i, Intb),
361    Intd = reserve(Intc),
362    {Keis,Inte,Stb} = cg(Ke, Vdb, Intd, Sta),
363    {comment(Inta) ++ Sis ++ Keis, {Inte,X0_v2,Stb}}.
364
365make_reservation([], _) -> [];
366make_reservation([{var,V}|As], I) -> [{I,V}|make_reservation(As, I+1)];
367make_reservation([A|As], I) -> [{I,A}|make_reservation(As, I+1)].
368
369reserve(Sr) -> Sr#sr{reg=reserve(Sr#sr.res, Sr#sr.reg, Sr#sr.stk)}.
370
371reserve([{I,V}|Rs], [free|Regs], Stk) -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
372reserve([{I,V}|Rs], [{I,V}|Regs], Stk) -> [{I,V}|reserve(Rs, Regs, Stk)];
373reserve([{I,V}|Rs], [{I,Var}|Regs], Stk) ->
374    case on_stack(Var, Stk) of
375	true -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
376	false -> [{I,Var}|reserve(Rs, Regs, Stk)]
377    end;
378reserve([{I,V}|Rs], [{reserved,I,_}|Regs], Stk) ->
379    [{reserved,I,V}|reserve(Rs, Regs, Stk)];
380%reserve([{I,V}|Rs], [Other|Regs], Stk) -> [Other|reserve(Rs, Regs, Stk)];
381reserve([{I,V}|Rs], [], Stk) -> [{reserved,I,V}|reserve(Rs, [], Stk)];
382reserve([], Regs, _) -> Regs.
383
384extend_stack(Bef, Fb, Lf, Vdb) ->
385    Stk0 = clear_dead_stk(Bef#sr.stk, Fb, Vdb),
386    Saves = [V || {V,F,L} <- Vdb,
387		  F < Fb,
388		  L >= Lf,
389		  not on_stack(V, Stk0)],
390    Stk1 = foldl(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
391    Bef#sr.stk ++ lists:duplicate(length(Stk1) - length(Bef#sr.stk), free).
392
393save_carefully(Bef, Fb, Lf, Vdb) ->
394    Stk = Bef#sr.stk,
395    %% New variables that are in use but not on stack.
396    New = [ {V,F,L} || {V,F,L} <- Vdb,
397		       F < Fb,
398		   L >= Lf,
399		       not on_stack(V, Stk) ],
400    Saves = [ V || {V,_,_} <- keysort(2, New) ],
401    save_carefully(Saves, Bef, []).
402
403save_carefully([], Bef, Acc) -> {reverse(Acc),Bef};
404save_carefully([V|Vs], Bef, Acc) ->
405    case put_stack_carefully(V, Bef#sr.stk) of
406	error -> {reverse(Acc),Bef};
407	Stk1 ->
408	    SrcReg = fetch_reg(V, Bef#sr.reg),
409	    Move = {move,SrcReg,fetch_stack(V, Stk1)},
410	    {x,_} = SrcReg,			%Assertion - must be X register.
411	    save_carefully(Vs, Bef#sr{stk=Stk1}, [Move|Acc])
412    end.
413
414x0_vars([], _Fb, _Lf, _Vdb) -> [];
415x0_vars([{var,V}|_], Fb, _Lf, Vdb) ->
416    {V,F,_L} = VFL = vdb_find(V, Vdb),
417    x0_vars1([VFL], Fb, F, Vdb);
418x0_vars([X0|_], Fb, Lf, Vdb) ->
419    x0_vars1([{X0,Lf,Lf}], Fb, Lf, Vdb).
420
421x0_vars1(X0, Fb, Xf, Vdb) ->
422    Vs0 = [VFL || {_V,F,L}=VFL <- Vdb,
423		  F >= Fb,
424		  L < Xf],
425    Vs1 = keysort(3, Vs0),
426    keysort(2, X0++Vs1).
427
428allocate_x0([], _, Bef) -> {[],Bef#sr{res=[]}};
429allocate_x0([{_,_,L}|Vs], I, Bef) when L =< I ->
430    allocate_x0(Vs, I, Bef);
431allocate_x0([{V,_F,_L}=VFL|Vs], _, Bef) ->
432    {[VFL|Vs],Bef#sr{res=reserve_x0(V, Bef#sr.res)}}.
433
434reserve_x0(V, [_|Res]) -> [{0,V}|Res];
435reserve_x0(V, []) -> [{0,V}].
436
437top_level_block(Keis, Bef, _MaxRegs, St0) when St0#cg.need_frame =:= false,
438					      length(Bef#sr.stk) =:= 0 ->
439    %% This block need no stack frame.  However, we still need to turn the
440    %% stack frame upside down.
441    MaxY = length(Bef#sr.stk)-1,
442    Keis1 = flatmap(fun (Tuple) when tuple(Tuple) ->
443			    [turn_yregs(size(Tuple), Tuple, MaxY)];
444			(Other) ->
445			    [Other]
446		    end, Keis),
447    {Keis1, Bef, St0#cg{is_top_block=true}};
448top_level_block(Keis, Bef, MaxRegs, St0) ->
449    %% This top block needs an allocate instruction before it, and a
450    %% deallocate instruction before each return.
451    FrameSz = length(Bef#sr.stk),
452    MaxY = FrameSz-1,
453    Keis1 = flatmap(fun ({call_only,Arity,Func}) ->
454			    [{call_last,Arity,Func,FrameSz}];
455			({call_ext_only,Arity,Func}) ->
456			    [{call_ext_last,Arity,Func,FrameSz}];
457			({apply_only,Arity}) ->
458			    [{apply_last,Arity,FrameSz}];
459			(return) ->
460			    [{deallocate,FrameSz}, return];
461			(Tuple) when tuple(Tuple) ->
462			    [turn_yregs(size(Tuple), Tuple, MaxY)];
463			(Other) ->
464			    [Other]
465		    end, Keis),
466    {[{allocate_zero,FrameSz,MaxRegs}|Keis1], Bef, St0#cg{is_top_block=true}}.
467
468%% turn_yregs(Size, Tuple, MaxY) -> Tuple'
469%%   Renumber y register so that {y, 0} becomes {y, FrameSize-1},
470%%   {y, FrameSize-1} becomes {y, 0} and so on.  This is to make nested
471%%   catches work.  The code generation algorithm gives a lower register
472%%   number to the outer catch, which is wrong.
473
474turn_yregs(0, Tp, _) -> Tp;
475turn_yregs(El, Tp, MaxY) when element(1, element(El, Tp)) == yy ->
476    turn_yregs(El-1, setelement(El, Tp, {y,MaxY-element(2, element(El, Tp))}), MaxY);
477turn_yregs(El, Tp, MaxY) when list(element(El, Tp)) ->
478    New = map(fun ({yy,YY}) -> {y,MaxY-YY};
479		  (Other) -> Other end, element(El, Tp)),
480    turn_yregs(El-1, setelement(El, Tp, New), MaxY);
481turn_yregs(El, Tp, MaxY) ->
482    turn_yregs(El-1, Tp, MaxY).
483
484%% select_cg(Sclause, V, TypeFail, ValueFail, StackReg, State) ->
485%%      {Is,StackReg,State}.
486%%  Selecting type and value needs two failure labels, TypeFail is the
487%%  label to jump to of the next type test when this type fails, and
488%%  ValueFail is the label when this type is correct but the value is
489%%  wrong.  These are different as in the second case there is no need
490%%  to try the next type, it will always fail.
491
492select_cg(#l{ke={type_clause,cons,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
493    select_cons(S, V, Tf, Vf, Bef, St);
494select_cg(#l{ke={type_clause,nil,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
495    select_nil(S, V, Tf, Vf, Bef, St);
496select_cg(#l{ke={type_clause,binary,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
497    select_binary(S, V, Tf, Vf, Bef, St);
498select_cg(#l{ke={type_clause,bin_seg,S}}, {var,V}, Tf, Vf, Bef, St) ->
499    select_bin_segs(S, V, Tf, Vf, Bef, St);
500select_cg(#l{ke={type_clause,bin_end,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
501    select_bin_end(S, V, Tf, Vf, Bef, St);
502select_cg(#l{ke={type_clause,Type,Scs}}, {var,V}, Tf, Vf, Bef, St0) ->
503    {Vis,{Aft,St1}} =
504	mapfoldl(fun (S, {Int,Sta}) ->
505			 {Val,Is,Inta,Stb} = select_val(S, V, Vf, Bef, Sta),
506			 {{Is,[Val]},{sr_merge(Int, Inta),Stb}}
507		 end, {void,St0}, Scs),
508    OptVls = combine(lists:sort(combine(Vis))),
509    {Vls,Sis,St2} = select_labels(OptVls, St1, [], []),
510    {select_val_cg(Type, fetch_var(V, Bef), Vls, Tf, Vf, Sis), Aft, St2}.
511
512select_val_cg(tuple, R, [Arity,{f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
513    [{test,is_tuple,{f,Tf},[R]},{test,test_arity,{f,Vf},[R,Arity]}|Sis];
514select_val_cg(tuple, R, Vls, Tf, Vf, Sis) ->
515    [{test,is_tuple,{f,Tf},[R]},{select_tuple_arity,R,{f,Vf},{list,Vls}}|Sis];
516select_val_cg(Type, R, [Val, {f,Lbl}], Fail, Fail, [{label,Lbl}|Sis]) ->
517    [{test,is_eq_exact,{f,Fail},[R,{Type,Val}]}|Sis];
518select_val_cg(Type, R, [Val, {f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
519    [{test,select_type_test(Type),{f,Tf},[R]},
520     {test,is_eq_exact,{f,Vf},[R,{Type,Val}]}|Sis];
521select_val_cg(Type, R, Vls0, Tf, Vf, Sis) ->
522    Vls1 = map(fun ({f,Lbl}) -> {f,Lbl};
523		   (Value) -> {Type,Value}
524	       end, Vls0),
525    [{test,select_type_test(Type),{f,Tf},[R]}, {select_val,R,{f,Vf},{list,Vls1}}|Sis].
526
527select_type_test(tuple) -> is_tuple;
528select_type_test(integer) -> is_integer;
529select_type_test(atom) -> is_atom;
530select_type_test(float) -> is_float.
531
532combine([{Is,Vs1}, {Is,Vs2}|Vis]) -> combine([{Is,Vs1 ++ Vs2}|Vis]);
533combine([V|Vis]) -> [V|combine(Vis)];
534combine([]) -> [].
535
536select_labels([{Is,Vs}|Vis], St0, Vls, Sis) ->
537    {Lbl,St1} = new_label(St0),
538    select_labels(Vis, St1, add_vls(Vs, Lbl, Vls), [[{label,Lbl}|Is]|Sis]);
539select_labels([], St, Vls, Sis) ->
540    {Vls,append(Sis),St}.
541
542add_vls([V|Vs], Lbl, Acc) ->
543    add_vls(Vs, Lbl, [V, {f,Lbl}|Acc]);
544add_vls([], _, Acc) -> Acc.
545
546select_cons(#l{ke={val_clause,{cons,Es},B},i=I,vdb=Vdb}, V, Tf, Vf, Bef, St0) ->
547    {Eis,Int,St1} = select_extract_cons(V, Es, I, Vdb, Bef, St0),
548    {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
549    {[{test,is_nonempty_list,{f,Tf},[fetch_var(V, Bef)]}] ++ Eis ++ Bis,Aft,St2}.
550
551select_nil(#l{ke={val_clause,nil,B}}, V, Tf, Vf, Bef, St0) ->
552    {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
553    {[{test,is_nil,{f,Tf},[fetch_var(V, Bef)]}] ++ Bis,Aft,St1}.
554
555select_binary(#l{ke={val_clause,{old_binary,Var},B}}=L,
556	      V, Tf, Vf, Bef, St) ->
557    %% Currently handled in the same way as new binaries.
558    select_binary(L#l{ke={val_clause,{binary,Var},B}}, V, Tf, Vf, Bef, St);
559select_binary(#l{ke={val_clause,{binary,{var,Ivar}},B},i=I,vdb=Vdb},
560	      V, Tf, Vf, Bef, St0) ->
561    Int0 = clear_dead(Bef, I, Vdb),
562    {Bis,Aft,St1} = match_cg(B, Vf, Int0, St0),
563    {[{test,bs_start_match,{f,Tf},[fetch_var(V, Bef)]},{bs_save,Ivar}|Bis],
564     Aft,St1}.
565
566select_bin_segs(Scs, Ivar, Tf, _Vf, Bef, St) ->
567    match_fmf(fun(S, Fail, Sta) ->
568		      select_bin_seg(S, Ivar, Fail, Bef, Sta) end,
569	      Tf, St, Scs).
570
571select_bin_seg(#l{ke={val_clause,{bin_seg,Size,U,T,Fs,Es},B},i=I,vdb=Vdb},
572		   Ivar, Fail, Bef, St0) ->
573    {Mis,Int,St1} = select_extract_bin(Es, Size, U, T, Fs, Fail,
574				       I, Vdb, Bef, St0),
575    {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
576    {[{bs_restore,Ivar}|Mis] ++ Bis,Aft,St2}.
577
578select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf,
579		   I, Vdb, Bef, St) ->
580    SizeReg = get_bin_size_reg(Size0, Bef),
581    {Es,Aft} =
582	case vdb_find(Hd, Vdb) of
583	    {_,_,Lhd} when Lhd =< I ->
584		{[{test,bs_skip_bits,{f,Vf},[SizeReg,Unit,{field_flags,Flags}]},
585		  {bs_save,Tl}],Bef};
586	    {_,_,_} ->
587		Reg0 = put_reg(Hd, Bef#sr.reg),
588		Int1 = Bef#sr{reg=Reg0},
589		Rhd = fetch_reg(Hd, Reg0),
590		Name = get_bits_instr(Type),
591		{[{test,Name,{f,Vf},[SizeReg,Unit,{field_flags,Flags},Rhd]},
592		  {bs_save,Tl}],Int1}
593	end,
594    {Es,clear_dead(Aft, I, Vdb),St}.
595
596get_bin_size_reg({var,V}, Bef) ->
597    fetch_var(V, Bef);
598get_bin_size_reg(Literal, _Bef) ->
599    Literal.
600
601select_bin_end(#l{ke={val_clause,bin_end,B}},
602		   Ivar, Tf, Vf, Bef, St0) ->
603    {Bis,Aft,St2} = match_cg(B, Vf, Bef, St0),
604    {[{bs_restore,Ivar},{test,bs_test_tail,{f,Tf},[0]}|Bis],Aft,St2}.
605
606get_bits_instr(integer) -> bs_get_integer;
607get_bits_instr(float)   -> bs_get_float;
608get_bits_instr(binary)  -> bs_get_binary.
609
610select_val(#l{ke={val_clause,{tuple,Es},B},i=I,vdb=Vdb}, V, Vf, Bef, St0) ->
611    {Eis,Int,St1} = select_extract_tuple(V, Es, I, Vdb, Bef, St0),
612    {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
613    {length(Es),Eis ++ Bis,Aft,St2};
614select_val(#l{ke={val_clause,{_,Val},B}}, _V, Vf, Bef, St0) ->
615    {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
616    {Val,Bis,Aft,St1}.
617
618%% select_extract_tuple(Src, [V], I, Vdb, StackReg, State) ->
619%%      {[E],StackReg,State}.
620%%  Extract tuple elements, but only if they do not immediately die.
621
622select_extract_tuple(Src, Vs, I, Vdb, Bef, St) ->
623    F = fun ({var,V}, {Int0,Elem}) ->
624		case vdb_find(V, Vdb) of
625		    {V,_,L} when L =< I -> {[], {Int0,Elem+1}};
626		    _Other ->
627			Reg1 = put_reg(V, Int0#sr.reg),
628			Int1 = Int0#sr{reg=Reg1},
629			Rsrc = fetch_var(Src, Int1),
630			{[{get_tuple_element,Rsrc,Elem,fetch_reg(V, Reg1)}],
631			 {Int1,Elem+1}}
632		end
633	end,
634    {Es,{Aft,_}} = flatmapfoldl(F, {Bef,0}, Vs),
635    {Es,Aft,St}.
636
637select_extract_cons(Src, [{var,Hd}, {var,Tl}], I, Vdb, Bef, St) ->
638    {Es,Aft} = case {vdb_find(Hd, Vdb), vdb_find(Tl, Vdb)} of
639		   {{_,_,Lhd}, {_,_,Ltl}} when Lhd =< I, Ltl =< I ->
640		       %% Both head and tail are dead.  No need to generate
641		       %% any instruction.
642		       {[], Bef};
643		   _ ->
644		       %% At least one of head and tail will be used,
645		       %% but we must always fetch both.  We will call
646		       %% clear_dead/2 to allow reuse of the register
647		       %% in case only of them is used.
648
649		       Reg0 = put_reg(Tl, put_reg(Hd, Bef#sr.reg)),
650		       Int0 = Bef#sr{reg=Reg0},
651		       Rsrc = fetch_var(Src, Int0),
652		       Rhd = fetch_reg(Hd, Reg0),
653		       Rtl = fetch_reg(Tl, Reg0),
654		       Int1 = clear_dead(Int0, I, Vdb),
655		       {[{get_list,Rsrc,Rhd,Rtl}], Int1}
656	       end,
657    {Es,Aft,St}.
658
659
660guard_clause_cg(#l{ke={guard_clause,G,B},vdb=Vdb}, Fail, Bef, St0) ->
661    {Gis,Int,St1} = guard_cg(G, Fail, Vdb, Bef, St0),
662    {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
663    {Gis ++ Bis,Aft,St2}.
664
665%% guard_cg(Guard, Fail, Vdb, StackReg, State) ->
666%%      {[Ainstr],StackReg,State}.
667%%  A guard is a boolean expression of tests.  Tests return true or
668%%  false.  A fault in a test causes the test to return false.  Tests
669%%  never return the boolean, instead we generate jump code to go to
670%%  the correct exit point.  Primops and tests all go to the next
671%%  instruction on success or jump to a failure label.
672
673guard_cg(#l{ke={protected,Ts,Rs},i=I,vdb=Pdb}, Fail, _Vdb, Bef, St) ->
674    protected_cg(Ts, Rs, Fail, I, Pdb, Bef, St);
675guard_cg(#l{ke={block,Ts},i=I,vdb=Bdb}, Fail, _Vdb, Bef, St) ->
676    guard_cg_list(Ts, Fail, I, Bdb, Bef, St);
677guard_cg(#l{ke={test,Test,As},i=I,vdb=_Tdb}, Fail, Vdb, Bef, St) ->
678    test_cg(Test, As, Fail, I, Vdb, Bef, St);
679guard_cg(G, _Fail, Vdb, Bef, St) ->
680    %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{G,Fail,Vdb,Bef}]),
681    {Gis,Aft,St1} = cg(G, Vdb, Bef, St),
682    %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Aft}]),
683    {Gis,Aft,St1}.
684
685%% protected_cg([Kexpr], [Ret], Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
686%%  Do a protected.  Protecteds without return values are just done
687%%  for effect, the return value is not checked, success passes on to
688%%  the next instruction and failure jumps to Fail.  If there are
689%%  return values then these must be set to 'false' on failure,
690%%  control always passes to the next instruction.
691
692protected_cg(Ts, [], Fail, I, Vdb, Bef, St0) ->
693    %% Protect these calls, revert when done.
694    {Tis,Aft,St1} = guard_cg_list(Ts, Fail, I, Vdb, Bef,
695				  St0#cg{btype=fail,bfail=Fail}),
696    {Tis,Aft,St1#cg{btype=St0#cg.btype,bfail=St0#cg.bfail}};
697protected_cg(Ts, Rs, _Fail, I, Vdb, Bef, St0) ->
698    {Pfail,St1} = new_label(St0),
699    {Psucc,St2} = new_label(St1),
700    {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, I, Vdb, Bef,
701				  St2#cg{btype=fail,bfail=Pfail}),
702    %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Rs,I,Vdb,Aft}]),
703    %% Set return values to false.
704    Mis = map(fun ({var,V}) -> {move,{atom,false},fetch_var(V, Aft)} end, Rs),
705    Live = {'%live',max_reg(Aft#sr.reg)},
706    {Tis ++ [Live,{jump,{f,Psucc}},
707	     {label,Pfail}] ++ Mis ++ [Live,{label,Psucc}],
708     Aft,St3#cg{btype=St0#cg.btype,bfail=St0#cg.bfail}}.
709
710%% test_cg(TestName, Args, Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
711%%  Generate test instruction.  Use explicit fail label here.
712
713test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
714    case test_type(Test, length(As)) of
715	{cond_op,Op} ->
716	    Ars = cg_reg_args(As, Bef),
717	    Int = clear_dead(Bef, I, Vdb),
718	    {[{test,Op,{f,Fail},Ars}],
719	     clear_dead(Int, I, Vdb),
720	     St};
721	{rev_cond_op,Op} ->
722	    [S1,S2] = cg_reg_args(As, Bef),
723	    Int = clear_dead(Bef, I, Vdb),
724	    {[{test,Op,{f,Fail},[S2,S1]}],
725	     clear_dead(Int, I, Vdb),
726	     St}
727    end.
728
729test_type(is_atom, 1)      -> {cond_op,is_atom};
730test_type(is_boolean, 1)   -> {cond_op,is_boolean};
731test_type(is_binary, 1)    -> {cond_op,is_binary};
732test_type(is_constant, 1)  -> {cond_op,is_constant};
733test_type(is_float, 1)     -> {cond_op,is_float};
734test_type(is_function, 1)  -> {cond_op,is_function};
735test_type(is_integer, 1)   -> {cond_op,is_integer};
736test_type(is_list, 1)      -> {cond_op,is_list};
737test_type(is_number, 1)    -> {cond_op,is_number};
738test_type(is_pid, 1)       -> {cond_op,is_pid};
739test_type(is_port, 1)      -> {cond_op,is_port};
740test_type(is_reference, 1) -> {cond_op,is_reference};
741test_type(is_tuple, 1)     -> {cond_op,is_tuple};
742test_type('=<', 2)  -> {rev_cond_op,is_ge};
743test_type('>', 2)   -> {rev_cond_op,is_lt};
744test_type('<', 2)   -> {cond_op,is_lt};
745test_type('>=', 2)  -> {cond_op,is_ge};
746test_type('==', 2)  -> {cond_op,is_eq};
747test_type('/=', 2)  -> {cond_op,is_ne};
748test_type('=:=', 2) -> {cond_op,is_eq_exact};
749test_type('=/=', 2) -> {cond_op,is_ne_exact};
750test_type(internal_is_record, 3) -> {cond_op,internal_is_record}.
751
752%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
753%%      {[Ainstr],StackReg,St}.
754
755guard_cg_list(Kes, Fail, I, Vdb, Bef, St0) ->
756    {Keis,{Aft,St1}} =
757	flatmapfoldl(fun (Ke, {Inta,Sta}) ->
758			     {Keis,Intb,Stb} =
759				 guard_cg(Ke, Fail, Vdb, Inta, Sta),
760			     {comment(Inta) ++ Keis,{Intb,Stb}}
761		     end, {Bef,St0}, need_heap(Kes, I)),
762    {Keis,Aft,St1}.
763
764%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,Aft,State}.
765%%  This is a special flatmapfoldl for match code gen where we
766%%  generate a "failure" label for each clause. The last clause uses
767%%  an externally generated failure label, LastFail.  N.B. We do not
768%%  know or care how the failure labels are used.
769
770match_fmf(F, LastFail, St, [H]) ->
771    F(H, LastFail, St);
772match_fmf(F, LastFail, St0, [H|T]) ->
773    {Fail,St1} = new_label(St0),
774    {R,Aft1,St2} = F(H, Fail, St1),
775    {Rs,Aft2,St3} = match_fmf(F, LastFail, St2, T),
776    {R ++ [{label,Fail}] ++ Rs,sr_merge(Aft1, Aft2),St3};
777match_fmf(_, _, St, []) -> {[],void,St}.
778
779%% call_cg(Func, [Arg], [Ret], Le, Vdb, StackReg, State) ->
780%%      {[Ainstr],StackReg,State}.
781%% enter_cg(Func, [Arg], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
782%%  Call and enter first put the arguments into registers and save any
783%%  other registers, then clean up and compress the stack and set the
784%%  frame size. Finally the actual call is made.  Call then needs the
785%%  return values filled in.
786
787call_cg({var,V}, As, Rs, Le, Vdb, Bef, St0) ->
788    {Sis,Int} = cg_setup_call(As++[{var,V}], Bef, Le#l.i, Vdb),
789    %% Put return values in registers.
790    Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
791    %% Build complete code and final stack/register state.
792    Arity = length(As),
793    {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
794    {comment({call_fun,{var,V},As}) ++ Sis ++ Frees ++ [{call_fun,Arity}],
795     Aft,need_stack_frame(St0)};
796call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
797  when element(1, Mod) == var;
798       element(1, Name) == var ->
799    {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
800    %% Put return values in registers.
801    Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
802    %% Build complete code and final stack/register state.
803    Arity = length(As),
804    Call = {apply,Arity},
805    St = need_stack_frame(St0),
806    %%{Call,St1} = build_call(Func, Arity, St0),
807    {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
808    {Sis ++ Frees ++ [Call],Aft,St};
809call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
810    {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
811    %% Put return values in registers.
812    Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
813    %% Build complete code and final stack/register state.
814    Arity = length(As),
815    {Call,St1} = build_call(Func, Arity, St0),
816    {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
817    {comment({call,Func,As}) ++ Sis ++ Frees ++ Call,Aft,St1}.
818
819build_call({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
820    {[send],need_stack_frame(St0)};
821build_call({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
822    {[{call_ext,Arity,{extfunc,Mod,Name,Arity}}],need_stack_frame(St0)};
823build_call(Name, Arity, St0) when atom(Name) ->
824    {Lbl,St1} = local_func_label(Name, Arity, need_stack_frame(St0)),
825    {[{call,Arity,{f,Lbl}}],St1}.
826
827free_dead(#sr{stk=Stk0}=Aft) ->
828    {Instr,Stk} = free_dead(Stk0, 0, [], []),
829    {Instr,Aft#sr{stk=Stk}}.
830
831free_dead([dead|Stk], Y, Instr, StkAcc) ->
832    %% Note: kill/1 is equivalent to init/1 (translated by beam_asm).
833    %% We use kill/1 to help further optimisation passes.
834    free_dead(Stk, Y+1, [{kill,{yy,Y}}|Instr], [free|StkAcc]);
835free_dead([Any|Stk], Y, Instr, StkAcc) ->
836    free_dead(Stk, Y+1, Instr, [Any|StkAcc]);
837free_dead([], _, Instr, StkAcc) -> {Instr,reverse(StkAcc)}.
838
839enter_cg({var,V}, As, Le, Vdb, Bef, St0) ->
840    {Sis,Int} = cg_setup_call(As++[{var,V}], Bef, Le#l.i, Vdb),
841    %% Build complete code and final stack/register state.
842    Arity = length(As),
843    {comment({call_fun,{var,V},As}) ++ Sis ++ [{call_fun,Arity},return],
844     clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
845     need_stack_frame(St0)};
846enter_cg({remote,Mod,Name}=Func, As, Le, Vdb, Bef, St0)
847  when element(1, Mod) == var;
848       element(1, Name) == var ->
849    {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
850    %% Build complete code and final stack/register state.
851    Arity = length(As),
852    Call = {apply_only,Arity},
853    St = need_stack_frame(St0),
854    {comment({enter,Func,As}) ++ Sis ++ [Call],
855     clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
856     St};
857enter_cg(Func, As, Le, Vdb, Bef, St0) ->
858    {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
859    %% Build complete code and final stack/register state.
860    Arity = length(As),
861    {Call,St1} = build_enter(Func, Arity, St0),
862    {comment({enter,Func,As}) ++ Sis ++ Call,
863     clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
864     St1}.
865
866build_enter({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
867    {[send,return],need_stack_frame(St0)};
868build_enter({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
869    St1 = case trap_bif(Mod, Name, Arity) of
870	      true -> need_stack_frame(St0);
871	      false -> St0
872	  end,
873    {[{call_ext_only,Arity,{extfunc,Mod,Name,Arity}}],St1};
874build_enter(Name, Arity, St0) when is_atom(Name) ->
875    {Lbl,St1} = local_func_label(Name, Arity, St0),
876    {[{call_only,Arity,{f,Lbl}}],St1}.
877
878%% local_func_label(Name, Arity, State) -> {Label,State'}
879%%  Get the function entry label for a local function.
880
881local_func_label(Name, Arity, St0) ->
882    Key = {Name,Arity},
883    case keysearch(Key, 1, St0#cg.functable) of
884	{value,{Key,Label}} ->
885	    {Label,St0};
886	false ->
887	    {Label,St1} = new_label(St0),
888	    {Label,St1#cg{functable=[{Key,Label}|St1#cg.functable]}}
889    end.
890
891%% need_stack_frame(State) -> State'
892%%  Make a note in the state that this function will need a stack frame.
893
894need_stack_frame(#cg{need_frame=true}=St) -> St;
895need_stack_frame(St) -> St#cg{need_frame=true}.
896
897%% trap_bif(Mod, Name, Arity) -> true|false
898%%   Trap bifs that need a stack frame.
899
900trap_bif(erlang, '!', 2) -> true;
901trap_bif(erlang, link, 1) -> true;
902trap_bif(erlang, unlink, 1) -> true;
903trap_bif(erlang, monitor_node, 2) -> true;
904trap_bif(erlang, group_leader, 2) -> true;
905trap_bif(erlang, exit, 2) -> true;
906trap_bif(_, _, _) -> false.
907
908%% bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
909%%      {[Ainstr],StackReg,State}.
910
911bif_cg(dsetelement, [Index0,Tuple0,New0], _Rs, Le, Vdb, Bef, St0) ->
912    [New,Tuple,{integer,Index1}] = cg_reg_args([New0,Tuple0,Index0], Bef),
913    Index = Index1-1,
914    {[{set_tuple_element,New,Tuple,Index}],
915     clear_dead(Bef, Le#l.i, Vdb), St0};
916bif_cg({make_fun,Func,Arity,Index,Uniq}, As, Rs, Le, Vdb, Bef, St0) ->
917    %% This behaves more like a function call.
918    {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
919    Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
920    {FuncLbl,St1} = local_func_label(Func, Arity, St0),
921    MakeFun = case St0#cg.new_funs of
922		  true -> {make_fun2,{f,FuncLbl},Index,Uniq,length(As)};
923		  false -> {make_fun,{f,FuncLbl},Uniq,length(As)}
924	      end,
925    {comment({make_fun,{Func,Arity,Uniq},As}) ++ Sis ++
926     [MakeFun],
927     clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),
928     St1};
929bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
930    Ars = cg_reg_args(As, Bef),
931
932    %% If we are inside a catch, we must save everything that will
933    %% be alive after the catch (because the BIF might fail and there
934    %% will be a jump to the code after the catch).
935    %%   Currently, we are somewhat pessimistic in
936    %% that we save any variable that will be live after this BIF call.
937
938    {Sis,Int0} =
939	case St0#cg.in_catch of
940	    true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb);
941	    false -> {[],Bef}
942	end,
943
944    Int1 = clear_dead(Int0, Le#l.i, Vdb),
945    Reg = put_reg(V, Int1#sr.reg),
946    Int = Int1#sr{reg=Reg},
947    Dst = fetch_reg(V, Reg),
948    {Sis ++ [{bif,Bif,bif_fail(St0#cg.btype, St0#cg.bfail, length(Ars)),Ars,Dst}],
949     clear_dead(Int, Le#l.i, Vdb), St0}.
950
951bif_fail(_, _, 0) -> nofail;
952bif_fail(exit, _, _) -> {f,0};
953bif_fail(fail, Fail, _) -> {f,Fail}.
954
955%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
956%%              [Ret], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
957
958recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
959    {Sis,Int0} = adjust_stack(Bef, Le#l.i, Le#l.i, Vdb),
960    Int1 = Int0#sr{reg=clear_regs(Int0#sr.reg)},
961    %% Get labels.
962    {Rl,St1} = new_label(St0),
963    {Tl,St2} = new_label(St1),
964    {Bl,St3} = new_label(St2),
965    St4 = St3#cg{break=Bl,recv=Rl},		%Set correct receive labels
966    {Ris,Raft,St5} = cg_recv_mesg(Rvar, Rm, Tl, Int1, St4),
967    {Wis,Taft,St6} = cg_recv_wait(Te, Tes, Le#l.i, Int1, St5),
968    Int2 = sr_merge(Raft, Taft),		%Merge stack/registers
969    Reg = load_vars(Rs, Int2#sr.reg),
970    {Sis ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
971     clear_dead(Int2#sr{reg=Reg}, Le#l.i, Vdb),
972     St6#cg{break=St0#cg.break,recv=St0#cg.recv}}.
973
974%% cg_recv_mesg( ) -> {[Ainstr],Aft,St}.
975
976cg_recv_mesg({var,R}, Rm, Tl, Bef, St0) ->
977    Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
978    Ret = fetch_reg(R, Int0#sr.reg),
979    %% Int1 = clear_dead(Int0, I, Rm#l.vdb),
980    Int1 = Int0,
981    {Mis,Int2,St1} = match_cg(Rm, none, Int1, St0),
982    {[{'%live',0},{label,St1#cg.recv},{loop_rec,{f,Tl},Ret}|Mis],Int2,St1}.
983
984%% cg_recv_wait(Te, Tes, I, Vdb, Int2, St3) -> {[Ainstr],Aft,St}.
985
986cg_recv_wait({atom,infinity}, Tes, I, Bef, St0) ->
987    %% We know that the 'after' body will never be executed.
988    %% But to keep the stack and register information up to date,
989    %% we will generate the code for the 'after' body, and then discard it.
990    Int1 = clear_dead(Bef, I, Tes#l.vdb),
991    {_,Int2,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
992			      Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
993    {[{wait,{f,St1#cg.recv}}],Int2,St1};
994cg_recv_wait({integer,0}, Tes, _I, Bef, St0) ->
995    {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb, Bef, St0),
996    {[timeout|Tis],Int,St1};
997cg_recv_wait(Te, Tes, I, Bef, St0) ->
998    Reg = cg_reg_arg(Te, Bef),
999    %% Must have empty registers here!  Bug if anything in registers.
1000    Int0 = clear_dead(Bef, I, Tes#l.vdb),
1001    {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
1002			     Int0#sr{reg=clear_regs(Int0#sr.reg)}, St0),
1003    {[{wait_timeout,{f,St1#cg.recv},Reg},timeout] ++ Tis,Int,St1}.
1004
1005%% recv_next_cg(Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
1006%%  Use adjust stack to clear stack, but only need it for Aft.
1007
1008recv_next_cg(Le, Vdb, Bef, St) ->
1009    {Sis,Aft} = adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb),
1010    {[{loop_rec_end,{f,St#cg.recv}}] ++ Sis,Aft,St}.	%Joke
1011
1012%% try_cg(TryBlock, [BodyVar], TryBody, [ExcpVar], TryHandler, [Ret],
1013%%        Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
1014
1015try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St0) ->
1016    {B,St1} = new_label(St0),			%Body label
1017    {H,St2} = new_label(St1),			%Handler label
1018    {E,St3} = new_label(St2),			%End label
1019    TryTag = Ta#l.i,
1020    Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
1021    TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
1022    {Ais,Int2,St4} = cg(Ta, Vdb, Int1, St3#cg{break=B,in_catch=true}),
1023    Int3 = Int2#sr{stk=drop_catch(TryTag, Int2#sr.stk)},
1024    St5 = St4#cg{break=E,in_catch=St3#cg.in_catch},
1025    {Bis,Baft,St6} = cg(Tb, Vdb, Int3#sr{reg=load_vars(Vs, Int3#sr.reg)}, St5),
1026    {His,Haft,St7} = cg(Th, Vdb, Int3#sr{reg=load_vars(Evs, Int3#sr.reg)}, St6),
1027    Int4 = sr_merge(Baft, Haft),		%Merge stack/registers
1028    Aft = Int4#sr{reg=load_vars(Rs, Int4#sr.reg)},
1029    {[{'try',TryReg,{f,H}}] ++ Ais ++
1030     [{label,B},{try_end,TryReg}] ++ Bis ++
1031     [{label,H},{try_case,TryReg}] ++ His ++
1032     [{label,E}],
1033     clear_dead(Aft, Le#l.i, Vdb),
1034     St7#cg{break=St0#cg.break}}.
1035
1036%% catch_cg(CatchBlock, Ret, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
1037
1038catch_cg(C, {var,R}, Le, Vdb, Bef, St0) ->
1039    {B,St1} = new_label(St0),
1040    CatchTag = Le#l.i,
1041    Int1 = Bef#sr{stk=put_catch(CatchTag, Bef#sr.stk)},
1042    CatchReg = fetch_stack({catch_tag,CatchTag}, Int1#sr.stk),
1043    {Cis,Int2,St2} = cg_block(C, Le#l.i, Le#l.vdb, Int1,
1044			      St1#cg{break=B,in_catch=true}),
1045    Aft = Int2#sr{reg=load_reg(R, 0, Int2#sr.reg),
1046		  stk=drop_catch(CatchTag, Int2#sr.stk)},
1047    {[{'catch',CatchReg,{f,B}}] ++ Cis ++
1048     [{label,B},{catch_end,CatchReg}],
1049     clear_dead(Aft, Le#l.i, Vdb),
1050     St2#cg{break=St1#cg.break,in_catch=St1#cg.in_catch}}.
1051
1052%% set_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
1053%%  We have to be careful how a 'set' works. First the structure is
1054%%  built, then it is filled and finally things can be cleared. The
1055%%  annotation must reflect this and make sure that the return
1056%%  variable is allocated first.
1057%%
1058%%  put_list for constructing a cons is an atomic instruction
1059%%  which can safely resuse one of the source registers as target.
1060%%  Also binaries can reuse a source register as target.
1061
1062set_cg([{var,R}], {cons,Es}, Le, Vdb, Bef, St) ->
1063    [S1,S2] = map(fun ({var,V}) -> fetch_var(V, Bef);
1064		      (Other) -> Other
1065		  end, Es),
1066    Int0 = clear_dead(Bef, Le#l.i, Vdb),
1067    Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
1068    Ret = fetch_reg(R, Int1#sr.reg),
1069    {[{put_list,S1,S2,Ret}], Int1, St};
1070set_cg([{var,R}], {old_binary,Segs}, Le, Vdb, Bef, St) ->
1071    Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
1072    PutCode = cg_bin_put(Segs, Fail, Bef),
1073    Code = cg_binary_old(PutCode),
1074    Int0 = clear_dead(Bef, Le#l.i, Vdb),
1075    Aft = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
1076    Ret = fetch_reg(R, Aft#sr.reg),
1077    {Code ++ [{bs_final,Fail,Ret}],Aft,St};
1078set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, #cg{in_catch=InCatch}=St) ->
1079    Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
1080    Target = fetch_reg(R, Int0#sr.reg),
1081    Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
1082    Temp = find_scratch_reg(Int0#sr.reg),
1083    PutCode = cg_bin_put(Segs, Fail, Bef),
1084    {Sis,Int1} =
1085	case InCatch of
1086	    true -> adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb);
1087	    false -> {[],Int0}
1088	end,
1089    Aft = clear_dead(Int1, Le#l.i, Vdb),
1090    Code = cg_binary(PutCode, Target, Temp, Fail, Aft),
1091    {Sis++Code,Aft,St};
1092set_cg([{var,R}], Con, Le, Vdb, Bef, St) ->
1093    %% Find a place for the return register first.
1094    Int = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
1095    Ret = fetch_reg(R, Int#sr.reg),
1096    Ais = case Con of
1097	      {tuple,Es} ->
1098		  [{put_tuple,length(Es),Ret}] ++ cg_build_args(Es, Bef);
1099	      {var,V} ->			% Normally removed by kernel optimizer.
1100		  [{move,fetch_var(V, Int),Ret}];
1101	      {string,Str} ->
1102		  [{put_string,length(Str),{string,Str},Ret}];
1103	      Other ->
1104		  [{move,Other,Ret}]
1105	  end,
1106    {Ais,clear_dead(Int, Le#l.i, Vdb),St};
1107set_cg([], {binary,Segs}, Le, Vdb, Bef, St) ->
1108    Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
1109    Target = find_scratch_reg(Bef#sr.reg),
1110    Temp = find_scratch_reg(put_reg(Target, Bef#sr.reg)),
1111    PutCode = cg_bin_put(Segs, Fail, Bef),
1112    Code = cg_binary(PutCode, Target, Temp, Fail, Bef),
1113    Aft = clear_dead(Bef, Le#l.i, Vdb),
1114    {Code,Aft,St};
1115set_cg([], {old_binary,Segs}, Le, Vdb, Bef, St) ->
1116    Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
1117    PutCode = cg_bin_put(Segs, Fail, Bef),
1118    Ais0 = cg_binary_old(PutCode),
1119    Ret = find_scratch_reg(Bef#sr.reg),
1120    Ais = Ais0 ++ [{bs_final,Fail,Ret}],
1121    {Ais,clear_dead(Bef, Le#l.i, Vdb),St};
1122set_cg([], _, Le, Vdb, Bef, St) ->
1123    %% This should have been stripped by compiler, just cleanup.
1124    {[],clear_dead(Bef, Le#l.i, Vdb), St}.
1125
1126
1127%%%
1128%%% Code generation for constructing binaries.
1129%%%
1130
1131cg_binary(PutCode, Target, Temp, Fail, Bef) ->
1132    SzCode = cg_binary_size(PutCode, Target, Temp, Fail),
1133    MaxRegs = max_reg(Bef#sr.reg),
1134    Code = SzCode ++ [{bs_init2,Fail,Target,MaxRegs,{field_flags,[]},Target}|PutCode],
1135    cg_bin_opt(Code).
1136
1137cg_binary_size(PutCode, Target, Temp, Fail) ->
1138    Szs = cg_binary_size_1(PutCode, 0, []),
1139    cg_binary_size_expr(Szs, Target, Temp, Fail).
1140
1141cg_binary_size_1([{_Put,_Fail,S,U,_Flags,Src}|T], Bits, Acc) ->
1142    cg_binary_size_2(S, U, Src, T, Bits, Acc);
1143cg_binary_size_1([], Bits, Acc) ->
1144    Bytes = Bits div 8,
1145    RemBits = Bits rem 8,
1146    Res = sort([{1,{integer,RemBits}},{8,{integer,Bytes}}|Acc]),
1147    cg_binary_size_3(Res).
1148
1149cg_binary_size_2({integer,N}, U, _, Next, Bits, Acc) ->
1150    cg_binary_size_1(Next, Bits+N*U, Acc);
1151cg_binary_size_2({atom,all}, 8, E, Next, Bits, Acc) ->
1152    cg_binary_size_1(Next, Bits, [{8,{size,E}}|Acc]);
1153cg_binary_size_2(Reg, 1, _, Next, Bits, Acc) ->
1154    cg_binary_size_1(Next, Bits, [{1,Reg}|Acc]);
1155cg_binary_size_2(Reg, 8, _, Next, Bits, Acc) ->
1156    cg_binary_size_1(Next, Bits, [{8,Reg}|Acc]);
1157cg_binary_size_2(Reg, U, _, Next, Bits, Acc) ->
1158    cg_binary_size_1(Next, Bits, [{1,{'*',Reg,U}}|Acc]).
1159
1160cg_binary_size_3([{_,{integer,0}}|T]) ->
1161    cg_binary_size_3(T);
1162cg_binary_size_3([{U,S1},{U,S2}|T]) ->
1163    {L0,Rest} = cg_binary_size_4(T, U, []),
1164    L = [S1,S2|L0],
1165    [{U,L}|cg_binary_size_3(Rest)];
1166cg_binary_size_3([{U,S}|T]) ->
1167    [{U,[S]}|cg_binary_size_3(T)];
1168cg_binary_size_3([]) -> [].
1169
1170cg_binary_size_4([{U,S}|T], U, Acc) ->
1171    cg_binary_size_4(T, U, [S|Acc]);
1172cg_binary_size_4(T, _, Acc) ->
1173    {Acc,T}.
1174
1175%% cg_binary_size_expr/4
1176%%  Generate code for calculating the resulting size of a binary.
1177cg_binary_size_expr(Sizes, Target, Temp, Fail) ->
1178    cg_binary_size_expr_1(Sizes, Target, Temp, Fail,
1179			  [{move,{integer,0},Target}]).
1180
1181cg_binary_size_expr_1([{1,E0}|T], Target, Temp, Fail, Acc) ->
1182    E1 = cg_gen_binsize(E0, Target, Temp, Fail, Acc),
1183    E = [{bs_bits_to_bytes,Fail,Target,Target}|E1],
1184    cg_binary_size_expr_1(T, Target, Temp, Fail, E);
1185cg_binary_size_expr_1([{8,E0}], Target, Temp, Fail, Acc) ->
1186    E = cg_gen_binsize(E0, Target, Temp, Fail, Acc),
1187    reverse(E);
1188cg_binary_size_expr_1([], _, _, _, Acc) -> reverse(Acc).
1189
1190cg_gen_binsize([{'*',A,B}|T], Target, Temp, Fail, Acc) ->
1191    cg_gen_binsize(T, Target, Temp, Fail,
1192		   [{bs_add,Fail,[Target,A,B],Target}|Acc]);
1193cg_gen_binsize([{size,B}|T], Target, Temp, Fail, Acc) ->
1194    cg_gen_binsize([Temp|T], Target, Temp, Fail,
1195		   [{bif,size,Fail,[B],Temp}|Acc]);
1196cg_gen_binsize([E0|T], Target, Temp, Fail, Acc) ->
1197    cg_gen_binsize(T, Target, Temp, Fail,
1198		   [{bs_add,Fail,[Target,E0,1],Target}|Acc]);
1199cg_gen_binsize([], _, _, _, Acc) -> Acc.
1200
1201%% cg_bin_opt(Code0) -> Code
1202%%  Optimize the size calculations for binary construction.
1203
1204cg_bin_opt([{move,{integer,0},D},{bs_add,_,[D,{integer,_}=S,1],Dst}|Is]) ->
1205    cg_bin_opt([{move,S,Dst}|Is]);
1206cg_bin_opt([{move,{integer,0},D},{bs_add,Fail,[D,S,U],Dst}|Is]) ->
1207    cg_bin_opt([{bs_add,Fail,[{integer,0},S,U],Dst}|Is]);
1208cg_bin_opt([{move,{integer,Bytes},D},{bs_init2,Fail,D,Regs0,Flags,D}|Is]) ->
1209    Regs = cg_bo_newregs(Regs0, D),
1210    cg_bin_opt([{bs_init2,Fail,Bytes,Regs,Flags,D}|Is]);
1211cg_bin_opt([{move,Src,D},{bs_init2,Fail,D,Regs0,Flags,D}|Is]) ->
1212    Regs = cg_bo_newregs(Regs0, D),
1213    cg_bin_opt([{bs_init2,Fail,Src,Regs,Flags,D}|Is]);
1214cg_bin_opt([{move,Src,Dst},{bs_bits_to_bytes,Fail,Dst,Dst}|Is]) ->
1215    cg_bin_opt([{bs_bits_to_bytes,Fail,Src,Dst}|Is]);
1216cg_bin_opt([{move,Src1,Dst},{bs_add,Fail,[Dst,Src2,U],Dst}|Is]) ->
1217    cg_bin_opt([{bs_add,Fail,[Src1,Src2,U],Dst}|Is]);
1218cg_bin_opt([{bs_bits_to_bytes,Fail,{integer,N},_}|Is0]) when N rem 8 =/= 0 ->
1219    case Fail of
1220	{f,0} ->
1221	    Is = [{move,{atom,badarg},{x,0}},
1222		  {call_ext_only,1,{extfunc,erlang,error,1}}|Is0],
1223	    cg_bin_opt(Is);
1224	_ ->
1225	    cg_bin_opt([{jump,Fail}|Is0])
1226    end;
1227cg_bin_opt([I|Is]) ->
1228    [I|cg_bin_opt(Is)];
1229cg_bin_opt([]) -> [].
1230
1231cg_bo_newregs(R, {x,X}) when R-1 =:= X -> R-1;
1232cg_bo_newregs(R, _) -> R.
1233
1234%% Common for new and old binary code generation.
1235
1236cg_bin_put({bin_seg,S0,U,T,Fs,[E0,Next]}, Fail, Bef) ->
1237    S1 = case S0 of
1238	     {var,Sv} -> fetch_var(Sv, Bef);
1239	     _ -> S0
1240	 end,
1241    E1 = case E0 of
1242	     {var,V} -> fetch_var(V, Bef);
1243	     Other ->   Other
1244	 end,
1245    Op = case T of
1246	     integer -> bs_put_integer;
1247	     binary  -> bs_put_binary;
1248	     float   -> bs_put_float
1249	 end,
1250    [{Op,Fail,S1,U,{field_flags,Fs},E1}|cg_bin_put(Next, Fail, Bef)];
1251cg_bin_put(bin_end, _, _) -> [].
1252
1253%% Old style.
1254
1255cg_binary_old(PutCode) ->
1256    [cg_bs_init(PutCode)] ++ need_bin_buf(PutCode).
1257
1258cg_bs_init(Code) ->
1259    {Size,Fs} = foldl(fun ({_,_,{integer,N},U,_,_}, {S,Fs}) ->
1260			      {S + N*U,Fs};
1261			  (_, {S,_}) ->
1262			      {S,[]}
1263		      end, {0,[exact]}, Code),
1264    {bs_init,(Size+7) div 8,{field_flags,Fs}}.
1265
1266need_bin_buf(Code0) ->
1267    {Code1,F,H} = foldr(fun ({_,_,{integer,N},U,_,_}=Bs, {Code,F,H}) ->
1268				{[Bs|Code],F,H + N*U};
1269			    ({_,_,_,_,_,_}=Bs, {Code,F,H}) ->
1270				{[Bs|need_bin_buf_need(H, F, Code)],true,0}
1271			end, {[],false,0}, Code0),
1272    need_bin_buf_need(H, F, Code1).
1273
1274need_bin_buf_need(0, false, Rest) -> Rest;
1275need_bin_buf_need(H, _, Rest) -> [{bs_need_buf,H}|Rest].
1276
1277cg_build_args(As, Bef) ->
1278    map(fun ({var,V}) -> {put,fetch_var(V, Bef)};
1279	    (Other) -> {put,Other}
1280	end, As).
1281
1282%% return_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
1283%% break_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
1284%%  These are very simple, just put return/break values in registers
1285%%  from 0, then return/break.  Use the call setup to clean up stack,
1286%%  but must clear registers to ensure sr_merge works correctly.
1287
1288return_cg(Rs, Le, Vdb, Bef, St) ->
1289    {Ms,Int} = cg_setup_call(Rs, Bef, Le#l.i, Vdb),
1290    {comment({return,Rs}) ++ Ms ++ [return],
1291     Int#sr{reg=clear_regs(Int#sr.reg)},St}.
1292
1293break_cg(Bs, Le, Vdb, Bef, St) ->
1294    {Ms,Int} = cg_setup_call(Bs, Bef, Le#l.i, Vdb),
1295    {comment({break,Bs}) ++ Ms ++ [{jump,{f,St#cg.break}}],
1296     Int#sr{reg=clear_regs(Int#sr.reg)},St}.
1297
1298%% cg_reg_arg(Arg0, Info) -> Arg
1299%% cg_reg_args([Arg0], Info) -> [Arg]
1300%%  Convert argument[s] into registers. Literal values are returned unchanged.
1301
1302cg_reg_args(As, Bef) -> [cg_reg_arg(A, Bef) || A <- As].
1303
1304cg_reg_arg({var,V}, Bef) -> fetch_var(V, Bef);
1305cg_reg_arg(Literal, _) -> Literal.
1306
1307%% cg_setup_call([Arg], Bef, Cur, Vdb) -> {[Instr],Aft}.
1308%%  Do the complete setup for a call/enter.
1309
1310cg_setup_call(As, Bef, I, Vdb) ->
1311    {Ms,Int0} = cg_call_args(As, Bef, I, Vdb),
1312    %% Have set up arguments, can now clean up, compress and save to stack.
1313    Int1 = Int0#sr{stk=clear_dead_stk(Int0#sr.stk, I, Vdb),res=[]},
1314    {Sis,Int2} = adjust_stack(Int1, I, I+1, Vdb),
1315    {Ms ++ Sis ++ [{'%live',length(As)}],Int2}.
1316
1317%% cg_call_args([Arg], SrState) -> {[Instr],SrState}.
1318%%  Setup the arguments to a call/enter/bif. Put the arguments into
1319%%  consecutive registers starting at {x,0} moving any data which
1320%%  needs to be saved. Return a modified SrState structure with the
1321%%  new register contents.  N.B. the resultant register info will
1322%%  contain non-variable values when there are non-variable values.
1323%%
1324%%  This routine is complicated by unsaved values in x registers.
1325%%  We'll move away any unsaved values that are in the registers
1326%%  to be overwritten by the arguments.
1327
1328cg_call_args(As, Bef, I, Vdb) ->
1329    Regs0 = load_arg_regs(Bef#sr.reg, As),
1330    Unsaved = unsaved_registers(Regs0, Bef#sr.stk, I, I+1, Vdb),
1331    {UnsavedMoves,Regs} = move_unsaved(Unsaved, Bef#sr.reg, Regs0),
1332    Moves0 = gen_moves(As, Bef),
1333    Moves = order_moves(Moves0, find_scratch_reg(Regs)),
1334    {UnsavedMoves ++ Moves,Bef#sr{reg=Regs}}.
1335
1336%% load_arg_regs([Reg], Arguments) -> [Reg]
1337%%  Update the register descriptor to include the arguments (from {x,0}
1338%%  and upwards). Values in argument register are overwritten.
1339%%  Values in x registers above the arguments are preserved.
1340
1341load_arg_regs(Regs, As) -> load_arg_regs(Regs, As, 0).
1342
1343load_arg_regs([_|Rs], [{var,V}|As], I) -> [{I,V}|load_arg_regs(Rs, As, I+1)];
1344load_arg_regs([_|Rs], [A|As], I) -> [{I,A}|load_arg_regs(Rs, As, I+1)];
1345load_arg_regs([], [{var,V}|As], I) -> [{I,V}|load_arg_regs([], As, I+1)];
1346load_arg_regs([], [A|As], I) -> [{I,A}|load_arg_regs([], As, I+1)];
1347load_arg_regs(Rs, [], _) -> Rs.
1348
1349%% Returns the variables must be saved and are currently in the
1350%% x registers that are about to be overwritten by the arguments.
1351
1352unsaved_registers(Regs, Stk, Fb, Lf, Vdb) ->
1353    [V || {V,F,L} <- Vdb,
1354	  F < Fb,
1355	  L >= Lf,
1356	  not on_stack(V, Stk),
1357	  not in_reg(V, Regs)].
1358
1359in_reg(V, Regs) -> keymember(V, 2, Regs).
1360
1361%% Move away unsaved variables from the registers that are to be
1362%% overwritten by the arguments.
1363move_unsaved(Vs, OrigRegs, NewRegs) ->
1364    move_unsaved(Vs, OrigRegs, NewRegs, []).
1365
1366move_unsaved([V|Vs], OrigRegs, NewRegs0, Acc) ->
1367    NewRegs = put_reg(V, NewRegs0),
1368    Src = fetch_reg(V, OrigRegs),
1369    Dst = fetch_reg(V, NewRegs),
1370    move_unsaved(Vs, OrigRegs, NewRegs, [{move,Src,Dst}|Acc]);
1371move_unsaved([], _, Regs, Acc) -> {Acc,Regs}.
1372
1373%% gen_moves(As, Sr)
1374%%  Generate the basic move instruction to move the arguments
1375%%  to their proper registers. The list will be sorted on
1376%%  destinations. (I.e. the move to {x,0} will be first --
1377%%  see the comment to order_moves/2.)
1378
1379gen_moves(As, Sr) -> gen_moves(As, Sr, 0, []).
1380
1381gen_moves([{var,V}|As], Sr, I, Acc) ->
1382    case fetch_var(V, Sr) of
1383	{x,I} -> gen_moves(As, Sr, I+1, Acc);
1384	Reg -> gen_moves(As, Sr, I+1, [{move,Reg,{x,I}}|Acc])
1385    end;
1386gen_moves([A|As], Sr, I, Acc) ->
1387    gen_moves(As, Sr, I+1, [{move,A,{x,I}}|Acc]);
1388gen_moves([], _, _, Acc) -> lists:keysort(3, Acc).
1389
1390%% order_moves([Move], ScratchReg) -> [Move]
1391%%  Orders move instruction so that source registers are not
1392%%  destroyed before they are used. If there are cycles
1393%%  (such as {move,{x,0},{x,1}}, {move,{x,1},{x,1}}),
1394%%  the scratch register is used to break up the cycle.
1395%%    If possible, the first move of the input list is placed
1396%%  last in the result list (to make the move to {x,0} occur
1397%%  just before the call to allow the Beam loader to coalesce
1398%%  the instructions).
1399
1400order_moves(Ms, Scr) -> order_moves(Ms, Scr, []).
1401
1402order_moves([{move,_,_}=M|Ms0], ScrReg, Acc0) ->
1403    {Chain,Ms} = collect_chain(Ms0, [M], ScrReg),
1404    Acc = reverse(Chain, Acc0),
1405    order_moves(Ms, ScrReg, Acc);
1406order_moves([], _, Acc) -> Acc.
1407
1408collect_chain(Ms, Path, ScrReg) ->
1409    collect_chain(Ms, Path, [], ScrReg).
1410
1411collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others, ScrReg) ->
1412    case keysearch(Src, 3, Path) of
1413	{value,_} ->				%We have a cycle.
1414	    {break_up_cycle(M, Path, ScrReg),reverse(Others, Ms0)};
1415	false ->
1416	    collect_chain(reverse(Others, Ms0), [M|Path], [], ScrReg)
1417    end;
1418collect_chain([M|Ms], Path, Others, ScrReg) ->
1419    collect_chain(Ms, Path, [M|Others], ScrReg);
1420collect_chain([], Path, Others, _) ->
1421    {Path,Others}.
1422
1423break_up_cycle({move,Src,_}=M, Path, ScrReg) ->
1424    [{move,ScrReg,Src},M|break_up_cycle1(Src, Path, ScrReg)].
1425
1426break_up_cycle1(Dst, [{move,Src,Dst}|Path], ScrReg) ->
1427    [{move,Src,ScrReg}|Path];
1428break_up_cycle1(Dst, [M|Path], LastMove) ->
1429    [M|break_up_cycle1(Dst, Path, LastMove)].
1430
1431%% clear_dead(Sr, Until, Vdb) -> Aft.
1432%%  Remove all variables in Sr which have died AT ALL so far.
1433
1434clear_dead(Sr, Until, Vdb) ->
1435    Sr#sr{reg=clear_dead_reg(Sr, Until, Vdb),
1436	  stk=clear_dead_stk(Sr#sr.stk, Until, Vdb)}.
1437
1438clear_dead_reg(Sr, Until, Vdb) ->
1439    Reg = map(fun ({I,V}) ->
1440		      case vdb_find(V, Vdb) of
1441			  {V,_,L} when L > Until -> {I,V};
1442			  _ -> free		%Remove anything else
1443		      end;
1444		  ({reserved,I,V}) -> {reserved,I,V};
1445		  (free) -> free
1446	      end, Sr#sr.reg),
1447    reserve(Sr#sr.res, Reg, Sr#sr.stk).
1448
1449clear_dead_stk(Stk, Until, Vdb) ->
1450    map(fun ({V}) ->
1451		case vdb_find(V, Vdb) of
1452		    {V,_,L} when L > Until -> {V};
1453		    _ -> dead			%Remove anything else
1454		end;
1455	    (free) -> free;
1456	    (dead) -> dead
1457	end, Stk).
1458
1459%% sr_merge(Sr1, Sr2) -> Sr.
1460%%  Merge two stack/register states keeping the longest of both stack
1461%%  and register. Perform consistency check on both, elements must be
1462%%  the same.  Allow frame size 'void' to make easy creation of
1463%%  "empty" frame.
1464
1465sr_merge(#sr{reg=R1,stk=S1,res=[]}, #sr{reg=R2,stk=S2,res=[]}) ->
1466    #sr{reg=longest(R1, R2),stk=longest(S1, S2),res=[]};
1467sr_merge(void, S2) -> S2#sr{res=[]};
1468sr_merge(S1, void) -> S1#sr{res=[]}.
1469
1470longest([H|T1], [H|T2]) -> [H|longest(T1, T2)];
1471longest([dead|T1], [free|T2]) -> [dead|longest(T1, T2)];
1472longest([free|T1], [dead|T2]) -> [dead|longest(T1, T2)];
1473longest([dead|T1], []) -> [dead|T1];
1474longest([], [dead|T2]) -> [dead|T2];
1475longest([free|T1], []) -> [free|T1];
1476longest([], [free|T2]) -> [free|T2];
1477longest([], []) -> [].
1478
1479%% adjust_stack(Bef, FirstBefore, LastFrom, Vdb) -> {[Ainstr],Aft}.
1480%%  Do complete stack adjustment by compressing stack and adding
1481%%  variables to be saved.  Try to optimise ordering on stack by
1482%%  having reverse order to their lifetimes.
1483%%
1484%%  In Beam, there is a fixed stack frame and no need to do stack compression.
1485
1486adjust_stack(Bef, Fb, Lf, Vdb) ->
1487    Stk0 = Bef#sr.stk,
1488    {Stk1,Saves} = save_stack(Stk0, Fb, Lf, Vdb),
1489    {saves(Saves, Bef#sr.reg, Stk1),
1490     Bef#sr{stk=Stk1}}.
1491
1492%% save_stack(Stack, FirstBefore, LastFrom, Vdb) -> {[SaveVar],NewStack}.
1493%%  Save variables which are used past current point and which are not
1494%%  already on the stack.
1495
1496save_stack(Stk0, Fb, Lf, Vdb) ->
1497    %% New variables that are in use but not on stack.
1498    New = [ {V,F,L} || {V,F,L} <- Vdb,
1499		   F < Fb,
1500		   L >= Lf,
1501		   not on_stack(V, Stk0) ],
1502    %% Add new variables that are not just dropped immediately.
1503    %% N.B. foldr works backwards from the end!!
1504    Saves = [ V || {V,_,_} <- keysort(3, New) ],
1505    Stk1 = foldr(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
1506    {Stk1,Saves}.
1507
1508%% saves([SaveVar], Reg, Stk) -> [{move,Reg,Stk}].
1509%%  Generate move instructions to save variables onto stack.  The
1510%%  stack/reg info used is that after the new stack has been made.
1511
1512saves(Ss, Reg, Stk) ->
1513    Res = map(fun (V) ->
1514		      {move,fetch_reg(V, Reg),fetch_stack(V, Stk)}
1515	      end, Ss),
1516    Res.
1517
1518%% comment(C) -> ['%'{C}].
1519
1520%comment(C) -> [{'%',C}].
1521comment(_) -> [].
1522
1523%% fetch_var(VarName, StkReg) -> r{R} | sp{Sp}.
1524%% find_var(VarName, StkReg) -> ok{r{R} | sp{Sp}} | error.
1525%%  Fetch/find a variable in either the registers or on the
1526%%  stack. Fetch KNOWS it's there.
1527
1528fetch_var(V, Sr) ->
1529    case find_reg(V, Sr#sr.reg) of
1530	{ok,R} -> R;
1531	error -> fetch_stack(V, Sr#sr.stk)
1532    end.
1533
1534% find_var(V, Sr) ->
1535%     case find_reg(V, Sr#sr.reg) of
1536% 	{ok,R} -> {ok,R};
1537% 	error ->
1538% 	    case find_stack(V, Sr#sr.stk) of
1539% 		{ok,S} -> {ok,S};
1540% 		error -> error
1541% 	    end
1542%     end.
1543
1544load_vars(Vs, Regs) ->
1545    foldl(fun ({var,V}, Rs) -> put_reg(V, Rs) end, Regs, Vs).
1546
1547%% put_reg(Val, Regs) -> Regs.
1548%% load_reg(Val, Reg, Regs) -> Regs.
1549%% free_reg(Val, Regs) -> Regs.
1550%% find_reg(Val, Regs) -> ok{r{R}} | error.
1551%% fetch_reg(Val, Regs) -> r{R}.
1552%%  Functions to interface the registers.
1553%%  put_reg puts a value into a free register,
1554%%  load_reg loads a value into a fixed register
1555%%  free_reg frees a register containing a specific value.
1556
1557% put_regs(Vs, Rs) -> foldl(fun put_reg/2, Rs, Vs).
1558
1559put_reg(V, Rs) -> put_reg_1(V, Rs, 0).
1560
1561put_reg_1(V, [free|Rs], I) -> [{I,V}|Rs];
1562put_reg_1(V, [{reserved,I,V}|Rs], I) -> [{I,V}|Rs];
1563put_reg_1(V, [R|Rs], I) -> [R|put_reg_1(V, Rs, I+1)];
1564put_reg_1(V, [], I) -> [{I,V}].
1565
1566load_reg(V, R, Rs) -> load_reg_1(V, R, Rs, 0).
1567
1568load_reg_1(V, I, [_|Rs], I) -> [{I,V}|Rs];
1569load_reg_1(V, I, [R|Rs], C) -> [R|load_reg_1(V, I, Rs, C+1)];
1570load_reg_1(V, I, [], I) -> [{I,V}];
1571load_reg_1(V, I, [], C) -> [free|load_reg_1(V, I, [], C+1)].
1572
1573% free_reg(V, [{I,V}|Rs]) -> [free|Rs];
1574% free_reg(V, [R|Rs]) -> [R|free_reg(V, Rs)];
1575% free_reg(V, []) -> [].
1576
1577fetch_reg(V, [{I,V}|_]) -> {x,I};
1578fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
1579
1580find_reg(V, [{I,V}|_]) -> {ok,{x,I}};
1581find_reg(V, [_|SRs]) -> find_reg(V, SRs);
1582find_reg(_, []) -> error.
1583
1584%% For the bit syntax, we need a scratch register if we are constructing
1585%% a binary that will not be used.
1586
1587find_scratch_reg(Rs) -> find_scratch_reg(Rs, 0).
1588
1589find_scratch_reg([free|_], I) -> {x,I};
1590find_scratch_reg([_|Rs], I) -> find_scratch_reg(Rs, I+1);
1591find_scratch_reg([], I) -> {x,I}.
1592
1593%%copy_reg(Val, R, Regs) -> load_reg(Val, R, Regs).
1594%%move_reg(Val, R, Regs) -> load_reg(Val, R, free_reg(Val, Regs)).
1595
1596%%clear_regs(Regs) -> map(fun (R) -> free end, Regs).
1597clear_regs(_) -> [].
1598
1599max_reg(Regs) ->
1600    foldl(fun ({I,_}, _) -> I;
1601	      (_, Max) -> Max end,
1602	  -1, Regs) + 1.
1603
1604%% put_stack(Val, [{Val}]) -> [{Val}].
1605%% fetch_stack(Var, Stk) -> sp{S}.
1606%% find_stack(Var, Stk) -> ok{sp{S}} | error.
1607%%  Functions to interface the stack.
1608
1609put_stack(Val, []) -> [{Val}];
1610put_stack(Val, [dead|Stk]) -> [{Val}|Stk];
1611put_stack(Val, [free|Stk]) -> [{Val}|Stk];
1612put_stack(Val, [NotFree|Stk]) -> [NotFree|put_stack(Val, Stk)].
1613
1614put_stack_carefully(Val, Stk0) ->
1615    case catch put_stack_carefully1(Val, Stk0) of
1616	error -> error;
1617	Stk1 when list(Stk1) -> Stk1
1618    end.
1619
1620put_stack_carefully1(_, []) -> throw(error);
1621put_stack_carefully1(Val, [dead|Stk]) -> [{Val}|Stk];
1622put_stack_carefully1(Val, [free|Stk]) -> [{Val}|Stk];
1623put_stack_carefully1(Val, [NotFree|Stk]) ->
1624    [NotFree|put_stack_carefully1(Val, Stk)].
1625
1626fetch_stack(Var, Stk) -> fetch_stack(Var, Stk, 0).
1627
1628fetch_stack(V, [{V}|_], I) -> {yy,I};
1629fetch_stack(V, [_|Stk], I) -> fetch_stack(V, Stk, I+1).
1630
1631% find_stack(Var, Stk) -> find_stack(Var, Stk, 0).
1632
1633% find_stack(V, [{V}|Stk], I) -> {ok,{yy,I}};
1634% find_stack(V, [O|Stk], I) -> find_stack(V, Stk, I+1);
1635% find_stack(V, [], I) -> error.
1636
1637on_stack(V, Stk) -> keymember(V, 1, Stk).
1638
1639%% put_catch(CatchTag, Stack) -> Stack'
1640%% drop_catch(CatchTag, Stack) -> Stack'
1641%%  Special interface for putting and removing catch tags, to ensure that
1642%%  catches nest properly. Also used for try tags.
1643
1644put_catch(Tag, Stk0) -> put_catch(Tag, reverse(Stk0), []).
1645
1646put_catch(Tag, [], Stk) ->
1647    put_stack({catch_tag,Tag}, Stk);
1648put_catch(Tag, [{{catch_tag,_}}|_]=RevStk, Stk) ->
1649    reverse(RevStk, put_stack({catch_tag,Tag}, Stk));
1650put_catch(Tag, [Other|Stk], Acc) ->
1651    put_catch(Tag, Stk, [Other|Acc]).
1652
1653drop_catch(Tag, [{{catch_tag,Tag}}|Stk]) -> [free|Stk];
1654drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
1655
1656%%%
1657%%% Finish the code generation for the bit syntax matching.
1658%%%
1659
1660bs_function({function,Name,Arity,CLabel,Asm0}=Func) ->
1661    case bs_needed(Asm0, 0, false, []) of
1662	{false,[]} -> Func;
1663	{true,Dict} ->
1664	    Asm = bs_replace(Asm0, Dict, []),
1665	    {function,Name,Arity,CLabel,Asm}
1666    end.
1667
1668%%%
1669%%% Pass 1: Found out which bs_restore's that are needed. For now we assume
1670%%% that a bs_restore is needed unless it is directly preceded by a bs_save.
1671%%%
1672
1673bs_needed([{bs_save,Name},{bs_restore,Name}|T], N, _BsUsed, Dict) ->
1674    bs_needed(T, N, true, Dict);
1675bs_needed([{bs_save,_Name}|T], N, _BsUsed, Dict) ->
1676    bs_needed(T, N, true, Dict);
1677bs_needed([{bs_restore,Name}|T], N, _BsUsed, Dict) ->
1678    case keysearch(Name, 1, Dict) of
1679	{value,{Name,_}} -> bs_needed(T, N, true, Dict);
1680	false -> bs_needed(T, N+1, true, [{Name,N}|Dict])
1681    end;
1682bs_needed([{bs_init,_,_}|T], N, _, Dict) ->
1683    bs_needed(T, N, true, Dict);
1684bs_needed([{bs_init2,_,_,_,_,_}|T], N, _, Dict) ->
1685    bs_needed(T, N, true, Dict);
1686bs_needed([{bs_start_match,_,_}|T], N, _, Dict) ->
1687    bs_needed(T, N, true, Dict);
1688bs_needed([_|T], N, BsUsed, Dict) ->
1689    bs_needed(T, N, BsUsed, Dict);
1690bs_needed([], _, BsUsed, Dict) -> {BsUsed,Dict}.
1691
1692%%%
1693%%% Pass 2: Only needed if there were some bs_* instructions found.
1694%%%
1695%%% Remove any bs_save with a name that never were found to be restored
1696%%% in the first pass.
1697%%%
1698
1699bs_replace([{bs_save,Name}=Save,{bs_restore,Name}|T], Dict, Acc) ->
1700    bs_replace([Save|T], Dict, Acc);
1701bs_replace([{bs_save,Name}|T], Dict, Acc) ->
1702    case keysearch(Name, 1, Dict) of
1703	{value,{Name,N}} ->
1704	    bs_replace(T, Dict, [{bs_save,N}|Acc]);
1705	false ->
1706	    bs_replace(T, Dict, Acc)
1707    end;
1708bs_replace([{bs_restore,Name}|T], Dict, Acc) ->
1709    case keysearch(Name, 1, Dict) of
1710	{value,{Name,N}} ->
1711	    bs_replace(T, Dict, [{bs_restore,N}|Acc]);
1712	false ->
1713	    bs_replace(T, Dict, Acc)
1714    end;
1715bs_replace([{bs_init2,Fail,Bytes,Regs,Flags,Dst}|T0], Dict, Acc) ->
1716    case bs_find_test_heap(T0) of
1717	none ->
1718	    bs_replace(T0, Dict, [{bs_init2,Fail,Bytes,0,Regs,Flags,Dst}|Acc]);
1719	{T,Words} ->
1720	    bs_replace(T, Dict, [{bs_init2,Fail,Bytes,Words,Regs,Flags,Dst}|Acc])
1721    end;
1722bs_replace([H|T], Dict, Acc) ->
1723    bs_replace(T, Dict, [H|Acc]);
1724bs_replace([], _, Acc) -> reverse(Acc).
1725
1726bs_find_test_heap(Is) ->
1727    bs_find_test_heap_1(Is, []).
1728
1729bs_find_test_heap_1([{bs_put_integer,_,_,_,_,_}=I|Is], Acc) ->
1730    bs_find_test_heap_1(Is, [I|Acc]);
1731bs_find_test_heap_1([{bs_put_float,_,_,_,_,_}=I|Is], Acc) ->
1732    bs_find_test_heap_1(Is, [I|Acc]);
1733bs_find_test_heap_1([{bs_put_binary,_,_,_,_,_}=I|Is], Acc) ->
1734    bs_find_test_heap_1(Is, [I|Acc]);
1735bs_find_test_heap_1([{test_heap,Words,_}|Is], Acc) ->
1736    {reverse(Acc, Is),Words};
1737bs_find_test_heap_1(_, _) -> none.
1738
1739%% new_label(St) -> {L,St}.
1740
1741new_label(St) ->
1742    L = St#cg.lcount,
1743    {L,St#cg{lcount=L+1}}.
1744
1745flatmapfoldl(F, Accu0, [Hd|Tail]) ->
1746    {R,Accu1} = F(Hd, Accu0),
1747    {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
1748    {R++Rs,Accu2};
1749flatmapfoldl(_, Accu, []) -> {[],Accu}.
1750
1751flatmapfoldr(F, Accu0, [Hd|Tail]) ->
1752    {Rs,Accu1} = flatmapfoldr(F, Accu0, Tail),
1753    {R,Accu2} = F(Hd, Accu1),
1754    {R++Rs,Accu2};
1755flatmapfoldr(_, Accu, []) -> {[],Accu}.
1756