~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/hipe/cerl/cerl_to_icode.erl

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
%%
18
18
%% $Id$
19
19
%%
20
 
%% @author Richard Carlsson <richardc@csd.uu.se>
21
 
%% @copyright 2000-2002 Richard Carlsson
22
 
%% @doc Translation from (HiPE-ified) Core Erlang to HiPE Icode.
23
 
%% @see cerl_hipeify
24
 
%% @end
 
20
%% @author Richard Carlsson <richardc@it.uu.se>
 
21
%% @copyright 2000-2006 Richard Carlsson
 
22
%% @doc Translation from Core Erlang to HiPE Icode.
25
23
 
26
 
%% TODO: use type information to avoid tests, remove dead code, etc.
27
 
%% TODO: compile case-switches over true/false using shortcut code.
28
 
%% TODO: handle binaries
29
 
%% TODO: compile tail-called letrec-defined functions as goto-loops.
30
 
%% TODO: remove unnecessary reduction tests
31
 
%% TODO: generate branch prediction info
 
24
%% TODO: annotate Icode leaf functions as such.
 
25
%% TODO: add a pass to remove unnecessary reduction tests
 
26
%% TODO: generate branch prediction info?
32
27
 
33
28
-module(cerl_to_icode).
34
29
 
35
 
-export([function/3, function/4, module/1, module/2]).
36
 
 
37
 
-import(lists, [mapfoldl/3]).
38
 
 
39
 
%% @spec module(Module::cerl()) -> [icode()]
40
 
%% @equiv module(T, [])
41
 
 
42
 
module(T) ->
43
 
    module(T, []).
44
 
 
45
 
%% @spec module(Module::cerl(), Options::[term()]) -> [icode()]
46
 
%%
47
 
%%          cerl() = cerl:cerl()
48
 
%%          icode() = hipe_icode:icode()
49
 
%%
50
 
%% @doc Transforms a Core Erlang module to linear HiPE Icode. The result
51
 
%% is a list of Icode function definitions. Currently, no options are
52
 
%% available.
53
 
%%
54
 
%% <p>Note: Except for the module name, which is included in the header
55
 
%% of each Icode function definition, the remaining information (exports
56
 
%% and attributes) associated with the module definition is not included
57
 
%% in the resulting Icode.</p>
58
 
%%
59
 
%% @see function/4
60
 
%% @see cerl_hipeify:module/1
61
 
%% @see cerl_lambdalift:module/1
62
 
 
63
 
module(T, Options) ->
64
 
    %% TODO: when we handle local letrecs, change the order of these:
65
 
    module_1(cerl_lambdalift:module(cerl_hipeify:module(T)), Options).
66
 
 
67
 
module_1(T, _Options) ->
68
 
    M = cerl:atom_val(cerl:module_name(T)),
69
 
    if atom(M) ->
70
 
            ok;
71
 
       true ->
72
 
            error_msg("bad module name: ~P.", [M, 5]),
73
 
            throw(error)
74
 
    end,
75
 
    S = init(M),
76
 
    {Icode, _} = mapfoldl(fun function_definition/2,
77
 
                          S, cerl:module_defs(T)),
78
 
    Icode.
79
 
 
80
 
%% For now, we simply assume that all function bodies should have degree
81
 
%% one (i.e., return exactly one value). We clear the code ackumulator
82
 
%% before we start compiling each function.
83
 
 
84
 
function_definition({V, F}, S) ->
85
 
    N = var_name_to_fname(cerl:var_name(V)),
86
 
    S1 = s__set_code([], S),
87
 
    {Icode, S2} = function_1(N, F, 1, S1),
88
 
    {{hipe_icode:icode_fun(Icode), Icode}, S2}.
89
 
 
90
 
var_name_to_fname({A, N}) when atom(A), integer(N) ->
91
 
    A;    %% The stated arity is ignored.
92
 
var_name_to_fname(A) when atom(A) ->
93
 
    A;
94
 
var_name_to_fname(N) ->
95
 
    error_msg("bad function name: ~P.", [N, 5]),
96
 
    throw(error).
97
 
 
98
 
init(Module) ->
99
 
    reset_label_counter(),                   
100
 
    s__new(Module).
101
 
 
102
 
 
103
 
%% @spec function(Module::atom(), Name::atom(), Function::cerl()) ->
104
 
%%           icode()
105
 
%% @equiv function(Module, Name, Fun, 1)
106
 
 
107
 
function(Module, Name, Fun) ->
108
 
    function(Module, Name, Fun, 1).
109
 
 
110
 
 
111
 
%% @spec function(Module::atom(), Name::atom(), Fun::cerl(),
112
 
%%                Degree::integer()) -> icode()
113
 
%%
114
 
%% @doc Transforms a Core Erlang function to a HiPE Icode function
115
 
%% definition. <code>Fun</code> must represent a fun-expression, which
116
 
%% may not contain free variables. <code>Module</code> and
117
 
%% <code>Name</code> specify the module and function name of the
118
 
%% resulting Icode function.
119
 
%%
120
 
%% <p><code>Degree</code> specifies the number of values the function is
121
 
%% expected to return; this is typically 1 (one); cf.
122
 
%% <code>function/3</code>.</p>
123
 
%%
124
 
%% <p>Notes: 
125
 
%% <ul>
126
 
%%   <li>Last call optimization is handled, even when the tail call is
127
 
%%   "hidden" by let-definitions.</li>
128
 
%%
129
 
%%   <li>It is assumed that all <code>primop</code> calls in the code
130
 
%%   represent Icode primops or macro instructions, and that all
131
 
%%   inter-module calls (both calls to statically named functions, and
132
 
%%   dynamic meta-calls) represent <em>actual</em> inter-module calls -
133
 
%%   not primitive or built-in operations.</li>
134
 
%%
135
 
%%   <li>The following primops (see
136
 
%%   "<code>cerl_hipe_primops.hrl</code>") are detected by the
137
 
%%   translation and handled specially:
138
 
%%   <table>
139
 
%%     <tr><td><code>exit/1</code>, <code>throw/1</code>,
140
 
%%             <code>error/1</code></td>
141
 
%%           <td>generate exceptions</td></tr>
142
 
%%     <tr><td><code>not/1</code>, <code>and/2</code>,
143
 
%%             <code>or/2</code></td>
144
 
%%           <td>strict boolean operators</td></tr>
145
 
%%     <tr><td><code>'=='/2</code>, <code>'/='/2</code></td>
146
 
%%           <td>arithmetic (un)equality</td></tr>
147
 
%%     <tr><td><code>'=:='/2</code>, <code>'=/='/2</code></td>
148
 
%%           <td>exact (un)equality</td></tr>
149
 
%%     <tr><td><code>'&lt;'/2</code>, <code>'>'/2</code></td>
150
 
%%           <td>smaller/greater than</td></tr>
151
 
%%     <tr><td><code>'=&lt;'/2</code></td>
152
 
%%           <td>smaller than or equal to</td></tr>
153
 
%%     <tr><td><code>'>='/2</code></td>
154
 
%%           <td>greater than or equal to</td></tr>
155
 
%%     <tr><td><code>receive_select/0</code></td>
156
 
%%           <td>select current message</td></tr>
157
 
%%     <tr><td><code>receive_next/0</code></td>
158
 
%%           <td>loop to try next message</td></tr>
159
 
%%     <tr><td><code>make_fun/6</code></td>
160
 
%%           <td>create a functional value</td></tr>
161
 
%%     <tr><td><code>apply_fun/2</code></td>
162
 
%%           <td>apply a functional value</td></tr>
163
 
%%   </table>
164
 
%%   The boolean operators are expected to be used in guard expressions,
165
 
%%   as well as in other expressions. See below for details on the
166
 
%%   <code>receive_...</code> operations.</li>
167
 
%%
168
 
%%   <li>Compilation of clauses is simplistic. No pattern matching
169
 
%%   compilation or similar optimizations is done. Indexing is not (yet)
170
 
%%   done. Guards that are <code>true</code> or <code>false</code> are
171
 
%%   recognized as trivially true/false; for all other guards, code will
172
 
%%   be generated. Catch-all clauses (with <code>true</code> guard and
173
 
%%   variable-only patterns) are detected, and any following clauses are
174
 
%%   discarded.</li>
175
 
%% </ul></p>
176
 
%%
177
 
%% <p><b>Important</b>: This function does not handle occurrences of
178
 
%% fun-expressions inside the body of <code>Fun</code> itself, nor
179
 
%% <code>apply</code>-expressions whose operators are not locally bound
180
 
%% function variables. These must be transformed away before this
181
 
%% function is called, by use of lambda lifting and the
182
 
%% <code>make_fun</code> and <code>call_fun</code> primitive operations
183
 
%% to create and apply functional values.</p>
184
 
%%
185
 
%% <p><code>receive</code>-expressions are expected to have a particular
186
 
%% form:
187
 
%% <ul>
188
 
%%   <li>There must be exactly one clause, with the atom
189
 
%%   <code>true</code> as guard, and only a single variable as pattern.
190
 
%%   The variable will be bound to a message in the mailbox, and can be
191
 
%%   referred to in the clause body.</li>
192
 
%%
193
 
%%   <li>In the body of that clause, all paths must execute one of the
194
 
%%   primitive operations <code>receive_select/0</code> or
195
 
%%   <code>receive_next/0</code> before another
196
 
%%   <code>receive</code>-statement might be executed.
197
 
%%   <code>receive_select/0</code> always returns, but without a value,
198
 
%%   while <code>receive_next/0</code> never returns, either causing
199
 
%%   the nearest surrounding receive-expression to be re-tried with the
200
 
%%   next message in the input queue, or timing out.</li>
201
 
%% </ul></p>
202
 
%%
203
 
%% @see function/3
204
 
 
205
 
-include("cerl_hipe_primops.hrl").
 
30
-define(NO_UNUSED, true).
 
31
 
 
32
-export([module/2]).
 
33
-ifndef(NO_UNUSED).
 
34
-export([function/3, function/4, module/1]).
 
35
-endif.
 
36
 
 
37
%% Added in an attempt to suppress message by Dialyzer, but I run into
 
38
%% an internal compiler error in the old inliner and commented it out.
 
39
%% The inlining is performed manually instead :-(             - Kostis
 
40
%% -compile({inline, [{error_fun_value,1}]}).
 
41
 
 
42
%% ---------------------------------------------------------------------
 
43
%% Macros and records
206
44
 
207
45
%% Icode primitive operation names
208
46
 
209
47
-define(OP_REDTEST, redtest).
210
48
-define(OP_CONS, cons).
211
49
-define(OP_TUPLE, mktuple).
 
50
-define(OP_ELEMENT, {erlang,element,2}).  %% This has an MFA name
212
51
-define(OP_UNSAFE_HD, unsafe_hd).
213
52
-define(OP_UNSAFE_TL, unsafe_tl).
214
53
-define(OP_UNSAFE_ELEMENT(N), {unsafe_element, N}).
215
 
-define(OP_GET_MESSAGE, get_msg).
 
54
-define(OP_UNSAFE_SETELEMENT(N), {unsafe_update_element, N}).
 
55
-define(OP_CHECK_GET_MESSAGE, check_get_msg).
216
56
-define(OP_NEXT_MESSAGE, next_msg).
217
57
-define(OP_SELECT_MESSAGE, select_msg).
218
58
-define(OP_SET_TIMEOUT, set_timeout).
219
59
-define(OP_CLEAR_TIMEOUT, clear_timeout).
220
60
-define(OP_WAIT_FOR_MESSAGE, suspend_msg).
 
61
-define(OP_APPLY_FIXARITY(N), {apply_N, N}).
221
62
-define(OP_MAKE_FUN(M, F, A, H, I), {mkfun, {M, F, A}, H, I}).
222
63
-define(OP_FUN_ELEMENT(N), {closure_element, N}).
223
64
 
231
72
-define(TEST_GT, '>').
232
73
-define(TEST_LE, '=<').
233
74
-define(TEST_GE, '>=').
234
 
-define(TEST_MAILBOX_EMPTY, mbox_empty).
235
75
-define(TEST_WAIT_FOR_MESSAGE_OR_TIMEOUT, suspend_msg_timeout).
236
76
 
237
77
%% Icode type tests
241
81
-define(TYPE_FIXNUM(X), {integer, X}).    % for now
242
82
-define(TYPE_CONS, cons).
243
83
-define(TYPE_NIL, nil).
244
 
-define(TYPE_TUPLE(N), {tuple, N}).
 
84
-define(TYPE_IS_N_TUPLE(N), {tuple, N}).
245
85
-define(TYPE_IS_ATOM, atom).
246
86
-define(TYPE_IS_BIGNUM, bignum).
247
87
-define(TYPE_IS_BINARY, binary).
254
94
-define(TYPE_IS_NUMBER, number).
255
95
-define(TYPE_IS_PID, pid).
256
96
-define(TYPE_IS_PORT, port).
 
97
-define(TYPE_IS_RECORD(Atom_, Size_), {record, Atom_, Size_}).
257
98
-define(TYPE_IS_REFERENCE, reference).
258
99
-define(TYPE_IS_TUPLE, tuple).
259
100
 
260
 
%% Boolean temporary values
261
 
 
262
 
-define(BOOL_TRUE, 1).
263
 
-define(BOOL_FALSE, 0).
264
 
-define(BOOL_IS_TRUE, ?TYPE_FIXNUM(0)).
265
 
-define(BOOL_IS_FALSE, ?TYPE_FIXNUM(0)).
266
 
 
267
101
%% Record definitions
268
102
 
269
103
-record(ctxt, {final = false,
270
104
               effect = false,
271
 
               fail = [],
272
 
               class = expr,
273
 
               'receive'}).
 
105
               fail = [],               % [] or fail-to label
 
106
               class = expr,            % expr | guard
 
107
               line = 0,                % current line number
 
108
               'receive'                % undefined | #receive{}
 
109
              }).               
274
110
 
275
111
-record('receive', {loop}).
276
 
-record(var, {id}).
277
 
-record('fun', {label}).
 
112
-record(var, {name}).
 
113
-record('fun', {label, vars}).
 
114
 
 
115
 
 
116
%% ---------------------------------------------------------------------
 
117
%% Code
 
118
 
 
119
 
 
120
%% @spec module(Module::cerl()) -> [icode()]
 
121
%% @equiv module(Module, [])
 
122
 
 
123
-ifndef(NO_UNUSED).
 
124
module(E) ->
 
125
    module(E, []).
 
126
-endif.
 
127
%% @clear
 
128
 
 
129
 
 
130
%% @spec module(Module::cerl(), Options::[term()]) -> [icode()]
 
131
%%
 
132
%%          cerl() = cerl:cerl()
 
133
%%          icode() = hipe_icode:icode()
 
134
%%
 
135
%% @doc Transforms a Core Erlang module to linear HiPE Icode. The result
 
136
%% is a list of Icode function definitions. Currently, no options are
 
137
%% available.
 
138
%%
 
139
%% <p>This function first calls the {@link cerl_hipeify:transform/2}
 
140
%% function on the module.</p>
 
141
%%
 
142
%% <p>Note: Except for the module name, which is included in the header
 
143
%% of each Icode function definition, the remaining information (exports
 
144
%% and attributes) associated with the module definition is not included
 
145
%% in the resulting Icode.</p>
 
146
%%
 
147
%% @see function/4
 
148
%% @see cerl_hipeify:transform/1
 
149
 
 
150
module(E, Options) ->
 
151
    module_1(cerl_hipeify:transform(E, Options), Options).
 
152
 
 
153
module_1(E, Options) ->
 
154
    M = cerl:atom_val(cerl:module_name(E)),
 
155
    if is_atom(M) ->
 
156
            ok;
 
157
       true ->
 
158
            error_msg("bad module name: ~P.", [M, 5]),
 
159
            throw(error)
 
160
    end,
 
161
    S0 = init(M),
 
162
    S =  s__set_pmatch(proplists:get_value(pmatch, Options), S0),
 
163
    {Icode, _} = lists:mapfoldl(fun function_definition/2,
 
164
                                S, cerl:module_defs(E)),
 
165
    Icode.
 
166
 
 
167
%% For now, we simply assume that all function bodies should have degree
 
168
%% one (i.e., return exactly one value). We clear the code ackumulator
 
169
%% before we start compiling each function.
 
170
 
 
171
function_definition({V, F}, S) ->
 
172
    S1 = s__set_code([], S),
 
173
    {Icode, S2} = function_1(cerl:var_name(V), F, 1, S1),
 
174
    {{icode_icode_name(Icode), Icode}, S2}.
 
175
 
 
176
init(Module) ->
 
177
    reset_label_counter(),                   
 
178
    s__new(Module).
 
179
 
 
180
%% @spec function(Module::atom(), Name::atom(), Function::cerl()) ->
 
181
%%           icode()
 
182
%% @equiv function(Module, Name, Fun, 1)
 
183
 
 
184
-ifndef(NO_UNUSED).
 
185
function(Module, Name, Fun) ->
 
186
    function(Module, Name, Fun, 1).
 
187
-endif. % NO_UNUSED
 
188
%% @clear
 
189
 
 
190
%% @spec function(Module::atom(), Name::{atom(), integer()},
 
191
%%                Fun::cerl(), Degree::integer()) -> icode()
 
192
%%
 
193
%% @doc Transforms a Core Erlang function to a HiPE Icode function
 
194
%% definition. `Fun' must represent a fun-expression, which may not
 
195
%% contain free variables. `Module' and `Name' specify the module and
 
196
%% function name of the resulting Icode function. Note that the arity
 
197
%% part of `Name' is not necessarily equivalent to the number of
 
198
%% parameters of `Fun' (this can happen e.g., for lifted closure
 
199
%% functions).
 
200
%%
 
201
%% <p>`Degree' specifies the number of values the function is expected
 
202
%% to return; this is typically 1 (one); cf. {@link function/3}.</p>
 
203
%%
 
204
%% <p>Notes: 
 
205
%% <ul>
 
206
%%   <li>This function assumes that the code has been transformed into a
 
207
%%   very simple and explicit form, using the {@link cerl_hipeify}
 
208
%%   module.</li>
 
209
%%
 
210
%%   <li>Several primops (see "`cerl_hipe_primops.hrl'") are
 
211
%%   detected by the translation and handled specially.</li>
 
212
%%
 
213
%%   <li>Tail call optimization is handled, even when the call is
 
214
%%   "hidden" by let-definitions.</li>
 
215
%%
 
216
%%   <li>It is assumed that all `primop' calls in the code represent
 
217
%%   Icode primops or macro instructions, and that all inter-module
 
218
%%   calls (both calls to statically named functions, and dynamic
 
219
%%   meta-calls) represent <em>actual</em> inter-module calls - not
 
220
%%   primitive or built-in operations.</li>
 
221
%%
 
222
%%   <li>The following special form:
 
223
%%     ```case Test of
 
224
%%            'true' when 'true' -> True
 
225
%%            'false' when 'true' -> False
 
226
%%        end'''
 
227
%%   is recognized as an if-then-else switch where `Test' is known
 
228
%%   to always yield 'true' or 'false'. Efficient jumping code is
 
229
%%   generated for such expressions, in particular if nested. Note that
 
230
%%   there must be exactly two clauses; order is not important.</li>
 
231
%%
 
232
%%   <li>Compilation of clauses is simplistic. No pattern matching
 
233
%%   compilation or similar optimizations is done at this stage. Guards
 
234
%%   that are `true' or `false' are recognized as trivially true/false;
 
235
%%   for all other guards, code will be generated. Catch-all clauses
 
236
%%   (with `true' guard and variable-only patterns) are detected, and
 
237
%%   any following clauses are discarded.</li>
 
238
%% </ul></p>
 
239
%%
 
240
%% <p><b>Important</b>: This function does not handle occurrences of
 
241
%% fun-expressions in the body of `Fun', nor `apply'-expressions whose
 
242
%% operators are not locally bound function variables. These must be
 
243
%% transformed away before this function is called, by closure
 
244
%% conversion ({@link cerl_cconv}) using the `make_fun' and `call_fun'
 
245
%% primitive operations to create and apply functional values.</p>
 
246
%%
 
247
%% <p>`receive'-expressions are expected to have a particular
 
248
%% form:
 
249
%% <ul>
 
250
%%   <li>There must be exactly one clause, with the atom
 
251
%%   `true' as guard, and only a single variable as pattern.
 
252
%%   The variable will be bound to a message in the mailbox, and can be
 
253
%%   referred to in the clause body.</li>
 
254
%%
 
255
%%   <li>In the body of that clause, all paths must execute one of the
 
256
%%   primitive operations `receive_select/0' or
 
257
%%   `receive_next/0' before another
 
258
%%   `receive'-statement might be executed.
 
259
%%   `receive_select/0' always returns, but without a value,
 
260
%%   while `receive_next/0' never returns, either causing
 
261
%%   the nearest surrounding receive-expression to be re-tried with the
 
262
%%   next message in the input queue, or timing out.</li>
 
263
%% </ul></p>
 
264
%%
 
265
%% @see function/3
 
266
 
 
267
-include("cerl_hipe_primops.hrl").
278
268
 
279
269
%% Main translation function:
280
270
 
 
271
-ifndef(NO_UNUSED).
281
272
function(Module, Name, Fun, Degree) ->
282
273
    S = init(Module),
283
274
    {Icode, _} = function_1(Name, Fun, Degree, S),
284
275
    Icode.
285
 
 
286
 
%% We use the following convention for tail-recursive calls within the
287
 
%% same module:
 
276
-endif. % NO_UNUSED
 
277
%% @clear
288
278
 
289
279
function_1(Name, Fun, Degree, S) ->
290
280
    reset_var_counter(),
291
281
    LowV = max_var(),
292
282
    LowL = max_label(),
293
 
 
294
283
    %% Create input variables for the function parameters, and a list of
295
284
    %% target variables for the result of the function.
296
285
    Args = cerl:fun_vars(Fun),
297
 
    Arity = length(Args),
298
 
    ArgType = get_type(Args),
299
 
    Vs = make_vars(Arity),
300
 
    Vs1 = make_vars(Arity),    % input variable temporaries
 
286
    IcodeArity = length(Args),
 
287
    ArgType = get_arg_types(Fun),
 
288
    Vs = make_vars(IcodeArity),
 
289
    Vs1 = make_vars(IcodeArity),    % input variable temporaries
301
290
    Ts = make_vars(Degree),
302
291
 
303
292
    %% Initialise environment and context.
304
293
    Env = bind_vars(Args, Vs, env__new()),
305
 
    %% TODO: if the function returns no values, we can use effect mode.
 
294
    %% TODO: if the function returns no values, we can use effect mode
306
295
    Ctxt = #ctxt{final = true, effect = false},
307
 
 
308
 
    %% Each basic block must begin with a label; also, we need to do a
309
 
    %% reduction test at the start of each function. Note that we
 
296
    %% Each basic block must begin with a label. Note that we
310
297
    %% immediately transfer the input parameters to local variables, for
311
298
    %% our self-recursive calling convention.
312
299
    Start = new_label(),
313
300
    Local = new_label(),
314
301
    S1 = add_code([icode_label(Start)]
315
302
                  ++ make_moves(Vs, Vs1)
316
 
                  ++ [icode_label(Local)]
317
 
                  ++ make_op(?OP_REDTEST, [], [], #ctxt{}),
318
 
                  s__set_function({Name, Arity}, S)),
 
303
                  ++ [icode_label(Local)],
 
304
                  s__set_function(Name, S)),
319
305
    S2 = expr(cerl:fun_body(Fun), Ts, Ctxt, Env,
320
306
              s__set_local_entry({Local, Vs}, S1)),
321
307
 
322
308
    %% This creates an Icode function definition. The ranges of used
323
309
    %% variables and labels below should be nonempty. Note that the
324
 
    %% input variables are `Vs1', which will be transferred to `Vs' (see
325
 
    %% above).
 
310
    %% input variables for the Icode function are `Vs1', which will be
 
311
    %% transferred to `Vs' (see above).
326
312
    HighV = new_var(),    % assure nonempty range
327
313
    HighL = max_label(),
328
 
    Lambda = lists:member(lambda, cerl:get_ann(Fun)),
329
 
    Leaf = false,  %% TODO: annotate functions with is-leaf info
 
314
    Closure = lists:member(closure, cerl:get_ann(Fun)),
330
315
    Module = s__get_module(S2),
331
316
    Code = s__get_code(S2),
332
 
    Function = icode_icode({Module, Name, Arity}, Vs1, Lambda, Leaf,
333
 
                           Code, {LowV, HighV}, {LowL, HighL}, ArgType),
334
 
    {Function, S2}.
335
 
 
336
 
expr(E, Ts, Ctxt, Env, S) ->
 
317
    Function = icode_icode(Module, Name, Vs1, Closure, Code,
 
318
                           {LowV, HighV}, {LowL, HighL}, ArgType),
 
319
    if Closure -> 
 
320
            {value, {_, OrigArity}} =
 
321
                lists:keysearch(closure_orig_arity, 1, cerl:get_ann(Fun)),
 
322
            {hipe_icode:icode_closure_arity_update(Function, 
 
323
                                                   OrigArity), 
 
324
             S2};
 
325
       true -> {Function, S2}
 
326
    end.
 
327
 
 
328
%% ---------------------------------------------------------------------
 
329
%% Main expression handler
 
330
 
 
331
expr(E, Ts, Ctxt, Env, S0) ->
 
332
    %% Insert source code position information
 
333
    case get_line(cerl:get_ann(E)) of
 
334
        none ->
 
335
            expr_1(E, Ts, Ctxt, Env, S0);
 
336
        Line when Line > Ctxt#ctxt.line ->
 
337
            Txt = "Line: " ++ integer_to_list(Line),
 
338
            S1 = add_code([icode_comment(Txt)], S0),
 
339
            expr_1(E, Ts, Ctxt#ctxt{line = Line}, Env, S1);
 
340
        _ ->
 
341
            expr_1(E, Ts, Ctxt, Env, S0)
 
342
    end.
 
343
 
 
344
expr_1(E, Ts, Ctxt, Env, S) ->
337
345
    case cerl:type(E) of
338
346
        var ->
339
347
            expr_var(E, Ts, Ctxt, Env, S);
362
370
            expr_receive(E, Ts, Ctxt, Env, S);
363
371
        'try' ->
364
372
            expr_try(E, Ts, Ctxt, Env, S);
365
 
        'catch' ->
366
 
            expr_catch(E, Ts, Ctxt, Env, S);
367
373
        binary ->
368
374
            expr_binary(E, Ts, Ctxt, Env, S);
 
375
        letrec ->
 
376
            expr_letrec(E, Ts, Ctxt, Env, S);
369
377
        'fun' ->
370
 
            error_msg("cannot compile lambda-valued "
371
 
                      "expressions directly to Icode."),
372
 
            throw(error);
373
 
        letrec ->
374
 
            %% TODO: compile letrec-definitions as local code
375
 
            error_msg("cannot compile letrec-expressions "
376
 
                      "directly to Icode."),
 
378
            error_msg("cannot handle fun-valued expressions; "
 
379
                      "must be closure converted."),
377
380
            throw(error)
378
381
    end.
379
382
 
380
383
%% This is for when we need new target variables for all of the
381
384
%% expressions in the list, and evaluate them for value in a
382
 
%% non-last-call context.
 
385
%% non-tail-call context.
383
386
 
384
387
expr_list(Es, Ctxt, Env, S) ->
385
388
    Ctxt1 = Ctxt#ctxt{effect = false, final = false},
386
 
    mapfoldl(fun (E0, S0) ->
387
 
                     V = make_var(),
388
 
                     {V, expr(E0, [V], Ctxt1, Env, S0)}
389
 
             end,
390
 
             S, Es).
 
389
    lists:mapfoldl(fun (E0, S0) ->
 
390
                           V = make_var(),
 
391
                           {V, expr(E0, [V], Ctxt1, Env, S0)}
 
392
                   end,
 
393
                   S, Es).
391
394
 
392
395
%% This is for when we already have the target variables. It is expected
393
396
%% that each expression in the list has degree one, so the result can be
405
408
    error_high_degree(),
406
409
    throw(error).
407
410
 
408
 
 
 
411
get_line([L | _As]) when is_integer(L) ->
 
412
    L;
 
413
get_line([_ | As]) ->
 
414
    get_line(As);
 
415
get_line([]) ->
 
416
    none.
 
417
 
 
418
 
 
419
%% ---------------------------------------------------------------------
409
420
%% Variables
410
421
 
411
422
expr_var(_E, _Ts, #ctxt{effect = true}, _Env, S) ->
412
423
    S;
413
424
expr_var(E, Ts, Ctxt, Env, S) ->
414
 
    Id = cerl:var_name(E),
415
 
    case env__lookup(Id, Env) of
416
 
        {ok, #var{id = V}} ->
 
425
    Name = cerl:var_name(E),
 
426
    case env__lookup(Name, Env) of
 
427
        error ->
 
428
            %% Either an undefined variable or an attempt to use a local
 
429
            %% function name as a value.
 
430
            case Name of
 
431
                {N,A} when is_atom(N), is_integer(A) ->
 
432
                    %% error_fun_value(Name);
 
433
                    error_msg("cannot handle fun-values outside call context; "
 
434
                              "must be closure converted: ~P.",
 
435
                              [Name, 5]),
 
436
                    throw(error);
 
437
                _ ->
 
438
                    error_msg("undefined variable: ~P.", [Name, 5]),
 
439
                    throw(error)
 
440
            end;
 
441
        {ok, #var{name = V}} ->
417
442
            case Ctxt#ctxt.final of
418
443
                false ->
419
444
                    glue([V], Ts, S);
421
446
                    add_return([V], S)
422
447
            end;
423
448
        {ok, #'fun'{}} ->
424
 
            error_msg("cannot handle functional value: ~P.",
425
 
                      [Id, 5]),
426
 
            throw(error);
427
 
        error ->
428
 
            error_msg("undefined variable: ~P.", [Id, 5]),
 
449
            %% A letrec-defined function name, used as a value.
 
450
            %% error_fun_value(Name)
 
451
            error_msg("cannot handle fun-values outside call context; "
 
452
                      "must be closure converted: ~P.",
 
453
                      [Name, 5]),
429
454
            throw(error)
430
455
    end.
431
456
 
 
457
%% The function has been inlined manually above to suppress message by Dialyzer
 
458
%% error_fun_value(Name) ->
 
459
%%    error_msg("cannot handle fun-values outside call context; "
 
460
%%            "must be closure converted: ~P.",
 
461
%%            [Name, 5]),
 
462
%%    throw(error).
 
463
 
 
464
%% ---------------------------------------------------------------------
432
465
%% This handles all constants, both atomic and compound:
433
466
 
434
467
expr_literal(_E, _Ts, #ctxt{effect = true}, S) ->
435
468
    S;
436
469
expr_literal(E, [V] = Ts, Ctxt, S) ->
437
 
    Code = [icode_mov(V, icode_const(cerl:concrete(E)))],
 
470
    Code = [icode_move(V, icode_const(cerl:concrete(E)))],
438
471
    maybe_return(Ts, Ctxt, add_code(Code, S));
439
472
expr_literal(E, Ts, _Ctxt, _S) ->
440
473
    error_degree_mismatch(length(Ts), E),
441
474
    throw(error).
442
475
 
443
 
%% Multiple value aggregate
 
476
%% ---------------------------------------------------------------------
 
477
%% Multiple value aggregate <X1,...,Xn>
444
478
 
445
479
expr_values(E, Ts, #ctxt{effect = true} = Ctxt, Env, S) ->
446
480
    {_, S1} = exprs(cerl:values_es(E), Ts, Ctxt#ctxt{final = false},
450
484
    S1 = exprs(cerl:values_es(E), Ts, Ctxt#ctxt{final = false}, Env, S),
451
485
    maybe_return(Ts, Ctxt, S1).
452
486
 
453
 
%% Nonconstant tuples and cons cells
 
487
%% ---------------------------------------------------------------------
 
488
%% Nonconstant tuples
454
489
 
455
490
expr_tuple(E, _Ts, #ctxt{effect = true} = Ctxt, Env, S) ->
456
 
    expr_list(cerl:tuple_es(E), Ctxt, Env, S);
 
491
    {_Vs, S1} = expr_list(cerl:tuple_es(E), Ctxt, Env, S),
 
492
    S1;
457
493
expr_tuple(E, [_V] = Ts, Ctxt, Env, S) ->
458
494
    {Vs, S1} = expr_list(cerl:tuple_es(E), Ctxt, Env, S),
459
 
    S2 = add_code(make_op(?OP_TUPLE, Ts, Vs, Ctxt), S1),
460
 
    maybe_return(Ts, Ctxt, S2);
 
495
    add_code(make_op(?OP_TUPLE, Ts, Vs, Ctxt), S1);
461
496
expr_tuple(E, Ts, _Ctxt, _Env, _S) ->
462
497
    error_degree_mismatch(length(Ts), E),
463
498
    throw(error).
464
499
 
 
500
%% ---------------------------------------------------------------------
 
501
%% Nonconstant cons cells
 
502
 
465
503
expr_cons(E, _Ts, #ctxt{effect = true} = Ctxt, Env, S) ->
466
 
    expr_list([cerl:cons_hd(E), cerl:cons_tl(E)], Ctxt, Env, S);
 
504
    {_Vs, S1} =expr_list([cerl:cons_hd(E), cerl:cons_tl(E)], Ctxt, Env, S),
 
505
    S1;
467
506
expr_cons(E, [_V] = Ts, Ctxt, Env, S) ->
468
507
    {Vs, S1} = expr_list([cerl:cons_hd(E), cerl:cons_tl(E)],
469
508
                         Ctxt, Env, S),
470
 
    S2 = add_code(make_op(?OP_CONS, Ts, Vs, Ctxt), S1),
471
 
    maybe_return(Ts, Ctxt, S2);
 
509
    add_code(make_op(?OP_CONS, Ts, Vs, Ctxt), S1);
472
510
expr_cons(E, Ts, _Ctxt, _Env, _S) ->
473
511
    error_degree_mismatch(length(Ts), E),
474
512
    throw(error).
475
513
 
 
514
%% ---------------------------------------------------------------------
 
515
%% Let-expressions
 
516
 
476
517
%% We want to make sure we are not easily tricked by expressions hidden
477
 
%% in contexts like "let X = Expr in X"; this should not destroy last
 
518
%% in contexts like "let X = Expr in X"; this should not destroy tail
478
519
%% call properties.
479
520
 
480
521
expr_let(E, Ts, Ctxt, Env, S) ->
481
 
    E1 = reduce_expr(E),
 
522
    F = fun (B, Ctxt, Env, S) -> expr(B, Ts, Ctxt, Env, S) end,
 
523
    expr_let_1(E, F, Ctxt, Env, S).
 
524
 
 
525
expr_let_1(E, F, Ctxt, Env, S) ->
 
526
    E1 = cerl_lib:reduce_expr(E),
482
527
    case cerl:is_c_let(E1) of
483
528
        true ->
484
 
            expr_let_1(E1, Ts, Ctxt, Env, S);
 
529
            expr_let_2(E1, F, Ctxt, Env, S);
485
530
        false ->
486
531
            %% Redispatch the new expression.
487
 
            expr(E1, Ts, Ctxt, Env, S)
 
532
            F(E1, Ctxt, Env, S)
488
533
    end.
489
534
 
490
 
expr_let_1(E, Ts, Ctxt, Env, S) ->
 
535
expr_let_2(E, F, Ctxt, Env, S) ->
491
536
    Vars = cerl:let_vars(E),
492
537
    Vs = make_vars(length(Vars)),
493
538
    S1 = expr(cerl:let_arg(E), Vs,
494
539
              Ctxt#ctxt{effect = false, final = false}, Env, S),
495
540
    Env1 = bind_vars(Vars, Vs, Env),
496
 
    B = cerl:let_body(E),
497
 
    expr(B, Ts, Ctxt, Env1, S1).
 
541
    F(cerl:let_body(E), Ctxt, Env1, S1).
 
542
 
 
543
%% ---------------------------------------------------------------------
 
544
%% Sequencing
498
545
 
499
546
%% To compile a sequencing operator, we generate code for effect only
500
547
%% for the first expression (the "argument") and then use the
501
 
%% surrounding context for the second expression (the "body") .
 
548
%% surrounding context for the second expression (the "body"). Note that
 
549
%% we always create a new dummy target variable; this is necessary for
 
550
%% many ICode operations, even if the result is not used.
502
551
 
503
552
expr_seq(E, Ts, Ctxt, Env, S) ->
 
553
    F = fun (B, Ctxt, Env, S) -> expr(B, Ts, Ctxt, Env, S) end,
 
554
    expr_seq_1(E, F, Ctxt, Env, S).
 
555
 
 
556
expr_seq_1(E, F, Ctxt, Env, S) ->
504
557
    Ctxt1 = Ctxt#ctxt{effect = true, final = false},
505
 
    S1 = expr(cerl:seq_arg(E), [], Ctxt1, Env, S),
506
 
    expr(cerl:seq_body(E), Ts, Ctxt, Env, S1).
507
 
 
508
 
expr_binary(E, [V]=Ts, #ctxt{fail=FL, class = guard}=Ctxt, Env, S) ->
 
558
    S1 = expr(cerl:seq_arg(E), [make_var()], Ctxt1, Env, S),
 
559
    F(cerl:seq_body(E), Ctxt, Env, S1).
 
560
 
 
561
%% ---------------------------------------------------------------------
 
562
%% Binaries
 
563
 
 
564
expr_binary(E, [V]=Ts, Ctxt, Env, S) ->
 
565
    Offset = make_reg(),
 
566
    Base = make_reg(),
 
567
    Segs = cerl:binary_segments(E),
 
568
    S1 = case do_size_code(Segs, S, Env, Ctxt) of
 
569
             {const, S0, Size} ->
 
570
                 Primop = {hipe_bs_primop, {bs_init2, Size, 0}},
 
571
                 add_code([icode_call_primop([V, Base, Offset], Primop, [])],
 
572
                          S0);
 
573
             {var, S0, SizeVar} ->
 
574
                 Primop = {hipe_bs_primop, {bs_init2, 0}},
 
575
                 add_code([icode_call_primop([V, Base, Offset],
 
576
                                             Primop, [SizeVar])],
 
577
                          S0)
 
578
         end,
 
579
    Vars = make_vars(length(Segs)),
 
580
    S2 = binary_segments(Segs, Vars, Ctxt, Env, S1, 0, Base, Offset), 
 
581
    maybe_return(Ts, Ctxt, S2).
 
582
 
 
583
do_size_code(Segs, S, Env, Ctxt) ->
 
584
    case do_size_code(Segs, S, Env, cerl:c_int(0), [], []) of
 
585
        {[], [], Const, S1} ->
 
586
            {const, S1, (cerl:concrete(Const) + 7) div 8};
 
587
        {Pairs, Bins, Const, S1} ->
 
588
            V1 = make_var(),
 
589
            S2 = add_code([icode_move(V1, icode_const(cerl:int_val(Const)))], S1),
 
590
            {S3, SizeVar} = create_size_code(Pairs, Bins, Ctxt, V1, S2),
 
591
            {var, S3, SizeVar}
 
592
    end.
 
593
 
 
594
do_size_code([Seg|Rest], S, Env, Const, Pairs, Bins) ->
 
595
    Size = cerl:bitstr_size(Seg),
 
596
    Unit = cerl:bitstr_unit(Seg),
 
597
    Val = cerl:bitstr_val(Seg),
 
598
    case calculate_size(Unit, Size, 0, Env, S) of
 
599
        {NewVal, [], S, _} ->
 
600
            do_size_code(Rest, S, Env, add_val(NewVal, Const), Pairs, Bins);
 
601
        {UnitVal, [Var], S1, _} ->
 
602
            do_size_code(Rest, S1, Env, Const, [{UnitVal,Var}|Pairs], Bins);
 
603
        {all, _, S} ->
 
604
            Binary = make_var(),
 
605
            S1 = expr(Val, [Binary], #ctxt{final=false}, Env, S), 
 
606
            do_size_code(Rest, S1, Env, Const, Pairs, [{all,Binary}|Bins])
 
607
    end;
 
608
do_size_code([], S, _Env, Const, Pairs, Bins) ->
 
609
    {Pairs, Bins, Const, S}.
 
610
 
 
611
add_val(NewVal, Const) ->
 
612
    cerl:c_int(NewVal + cerl:concrete(Const)).
 
613
 
 
614
create_size_code([{UnitVal, Var}|Rest], Bins, Ctxt, Old, S0) ->
 
615
    Dst = make_var(),
 
616
    S = make_bs_add(UnitVal, Old, Var, Dst, Ctxt, S0),
 
617
    create_size_code(Rest, Bins, Ctxt, Dst, S);
 
618
create_size_code([], Bins, Ctxt, Old, S0) -> 
 
619
    Dst = make_var(),
 
620
    S = make_bs_bits_to_bytes(Old, Dst, Ctxt, S0),
 
621
    create_size_code(Bins, Ctxt, Dst, S).
 
622
 
 
623
create_size_code([{all,Bin}|Rest], Ctxt, Old, S0) ->
 
624
    Dst = make_var(),
 
625
    S = make_binary_size(Old, Bin, Dst, Ctxt, S0),
 
626
    create_size_code(Rest, Ctxt, Dst, S);
 
627
create_size_code([], _Ctxt, Dst, S) ->
 
628
    {S, Dst}.
 
629
 
 
630
make_bs_add(Unit, Old, Var, Dst, #ctxt{fail=FL, class=guard}, S0) ->
 
631
    SL = new_label(),
 
632
    Primop = {hipe_bs_primop, {bs_add, Unit}},
 
633
    add_code([icode_guardop([Dst], Primop, [Old, Var], SL, FL),
 
634
              icode_label(SL)], S0);
 
635
make_bs_add(Unit, Old, Var, Dst, _Ctxt, S0) ->
 
636
    Primop = {hipe_bs_primop, {bs_add, Unit}},
 
637
    add_code([icode_call_primop([Dst], Primop, [Old, Var])], S0).
 
638
 
 
639
make_bs_bits_to_bytes(Old, Dst, #ctxt{fail=FL, class=guard}, S0) -> 
 
640
    SL = new_label(),
 
641
    Primop = {hipe_bs_primop, bs_bits_to_bytes},
 
642
    add_code([icode_guardop([Dst], Primop, [Old], SL, FL),
 
643
              icode_label(SL)], S0);
 
644
make_bs_bits_to_bytes(Old, Dst, _Ctxt, S0) ->
 
645
    Primop = {hipe_bs_primop, bs_bits_to_bytes},
 
646
    add_code([icode_call_primop([Dst], Primop, [Old])], S0).
 
647
 
 
648
make_binary_size(Old, Bin, Dst, #ctxt{fail=FL, class=guard}, S0) -> 
509
649
    SL1 = new_label(),
510
650
    SL2 = new_label(),
511
 
    Segs = cerl:binary_segs(E),
512
 
    S1 = add_code([icode_guardop([], {hipe_bs_primop, {bs_init, 0,0}}, [], SL1, FL),
513
 
                   icode_label(SL1)], S),
514
 
    Vars = make_vars(length(Segs)),
515
 
    S2 = bin_segs(Segs, Vars, Ctxt, Env, 0, S1), 
516
 
    S3 = add_code([icode_guardop([V], {hipe_bs_primop, bs_final}, [], SL2, FL),
517
 
                   icode_label(SL2)], S2),
518
 
    maybe_return(Ts, Ctxt, S3);
519
 
 
520
 
expr_binary(E, [V]=Ts, Ctxt, Env, S) ->
521
 
    Segs = cerl:binary_segs(E),
522
 
    S1 = add_code([icode_call_primop([], {hipe_bs_primop, {bs_init, 0,0}}, [])], S),
523
 
    Vars = make_vars(length(Segs)),
524
 
    S2 = bin_segs(Segs, Vars, Ctxt, Env, S1, 0), 
525
 
    S3 = add_code([icode_call_primop([V], {hipe_bs_primop, bs_final}, [])], S2),
526
 
    maybe_return(Ts, Ctxt, S3).
527
 
 
528
 
bin_segs([Seg|Rest], [T|Ts], Ctxt=#ctxt{}, Env, S, Align) ->
529
 
    {S1, NewAlign} = bin_seg(Seg, [T], Ctxt, Env, S, Align),
530
 
    bin_segs(Rest, Ts, Ctxt, Env, S1, NewAlign);
531
 
bin_segs([], [], #ctxt{}, _Env, S, _Align) ->
532
 
    S.
533
 
 
534
 
bin_seg(E, Ts, Ctxt, Env, S, Align) ->
535
 
    Size = cerl:bin_seg_size(E),
536
 
    Unit = cerl:bin_seg_unit(E),
537
 
    LiteralFlags = cerl:bin_seg_flags(E),
538
 
    Val = cerl:bin_seg_val(E),
539
 
    Type = cerl:concrete(cerl:bin_seg_type(E)),
540
 
    S0 = expr(Val, Ts, Ctxt#ctxt{final = false}, Env, S),
 
651
    add_code([icode_guardop([Dst], {erlang, size, 1}, [Bin], SL1, FL),
 
652
              icode_label(SL1),
 
653
              icode_guardop([Dst], '+', [Old, Dst], SL2, FL),
 
654
              icode_label(SL2)], S0);
 
655
make_binary_size(Old, Bin, Dst, _Ctxt, S0) ->
 
656
    add_code([icode_call_primop([Dst], {erlang, size, 1}, [Bin]),
 
657
              icode_call_primop([Dst], '+', [Old, Dst])], S0).
 
658
 
 
659
binary_segments(SegList, TList, Ctxt=#ctxt{}, Env, S, Align, Base,
 
660
                Offset) ->
 
661
    case do_const_segs(SegList, TList, S, Align, Base, Offset) of
 
662
        {[Seg|Rest], [T|Ts], S1} ->
 
663
            {S2, NewAlign} = bitstr(Seg, [T], Ctxt, Env, S1, Align,
 
664
                                    Base, Offset),
 
665
            binary_segments(Rest, Ts, Ctxt, Env, S2, NewAlign, Base, Offset);
 
666
        {[], [], S1} ->
 
667
            S1
 
668
    end.
 
669
 
 
670
do_const_segs(SegList, TList, S, Align, Base, Offset) ->
 
671
    case get_segs(SegList, TList, [], 0, {[], SegList, TList}) of
 
672
        {[], SegList, TList} ->
 
673
            {SegList, TList, S};
 
674
        {ConstSegs, RestSegs, RestT} ->
 
675
            String = create_string(ConstSegs, <<>>, 0),
 
676
            Flags = translate_flags1([], Align),
 
677
            Name = {bs_put_string, String, length(String), Flags},
 
678
            Primop = {hipe_bs_primop, Name},
 
679
            {RestSegs, RestT,
 
680
             add_code([icode_call_primop([Offset], Primop, [Base, Offset])],
 
681
                      S)}
 
682
    end.
 
683
             
 
684
get_segs([Seg|Rest], [_|RestT], Acc, AccSize, BestPresent) ->
 
685
    Size = cerl:bitstr_size(Seg),
 
686
    Unit = cerl:bitstr_unit(Seg),
 
687
    Val = cerl:bitstr_val(Seg),
 
688
    case allowed(Size, Unit, Val, AccSize) of
 
689
        {true, NewAccSize} ->
 
690
            case Acc of
 
691
                [] ->
 
692
                    get_segs(Rest, RestT, [Seg|Acc], NewAccSize, BestPresent);
 
693
                _ ->
 
694
                    get_segs(Rest, RestT, [Seg|Acc], NewAccSize, 
 
695
                             {lists:reverse([Seg|Acc]), Rest, RestT})
 
696
            end;
 
697
        {possible, NewAccSize} ->
 
698
            get_segs(Rest, RestT, [Seg|Acc], NewAccSize, BestPresent);
 
699
        false ->
 
700
            BestPresent
 
701
    end;
 
702
get_segs([], [], _Acc, _AccSize, Best) ->
 
703
    Best.
 
704
 
 
705
                
 
706
create_string([Seg|Rest], Bin, TotalSize) ->
 
707
    Size = cerl:bitstr_size(Seg),
 
708
    Unit = cerl:bitstr_unit(Seg), 
 
709
    NewSize = cerl:int_val(Size) * cerl:int_val(Unit),
 
710
    LitVal = cerl:concrete(cerl:bitstr_val(Seg)),
 
711
    LiteralFlags = cerl:bitstr_flags(Seg),
 
712
    FlagVal = translate_flags(LiteralFlags, []),
 
713
    NewTotalSize = NewSize + TotalSize,
 
714
    Pad = (8 - NewTotalSize rem 8) rem 8,
 
715
    NewBin = case cerl:concrete(cerl:bitstr_type(Seg)) of
 
716
                 integer ->
 
717
                     case {FlagVal band 2, FlagVal band 4} of
 
718
                         {2, 4} ->
 
719
                             <<Bin:TotalSize/binary-unit:1, 
 
720
                              LitVal:NewSize/integer-little-signed, 0:Pad>>;
 
721
                         {0, 4} ->
 
722
                             <<Bin:TotalSize/binary-unit:1, 
 
723
                              LitVal:NewSize/integer-signed, 0:Pad>>;
 
724
                         {2, 0} ->
 
725
                             <<Bin:TotalSize/binary-unit:1, 
 
726
                              LitVal:NewSize/integer-little, 0:Pad>>;
 
727
                         {0, 0} ->
 
728
                             <<Bin:TotalSize/binary-unit:1, 
 
729
                              LitVal:NewSize/integer, 0:Pad>>
 
730
                     end;
 
731
                 float ->
 
732
                     case FlagVal band 2 of
 
733
                         2 ->
 
734
                             <<Bin:TotalSize/binary-unit:1,
 
735
                              LitVal:NewSize/float-little, 0:Pad>>;
 
736
                         0 ->
 
737
                             <<Bin:TotalSize/binary-unit:1,
 
738
                              LitVal:NewSize/float, 0:Pad>>
 
739
                     end
 
740
             end,
 
741
    create_string(Rest, NewBin, NewTotalSize);
 
742
 
 
743
create_string([], Bin, _Size) ->
 
744
    binary_to_list(Bin).
 
745
                
 
746
allowed(Size, Unit, Val, AccSize) ->
 
747
    case {cerl:is_c_int(Size), cerl:is_literal(Val)} of
 
748
        {true, true} ->
 
749
            NewAccSize = cerl:int_val(Size) * cerl:int_val(Unit) + AccSize,
 
750
            case NewAccSize rem 8 of
 
751
                0 ->
 
752
                    {true, NewAccSize};
 
753
                _ ->
 
754
                    {possible, NewAccSize}
 
755
            end;
 
756
        _ ->
 
757
            false
 
758
    end.
 
759
 
 
760
bitstr(E, Ts, Ctxt, Env, S, Align, Base, Offset) ->
 
761
    Size = cerl:bitstr_size(E),
 
762
    Unit = cerl:bitstr_unit(E),
 
763
    LiteralFlags = cerl:bitstr_flags(E),
 
764
    Val = cerl:bitstr_val(E),
 
765
    Type = cerl:concrete(cerl:bitstr_type(E)),
 
766
    S0 = expr(Val, Ts, Ctxt#ctxt{final = false, effect = false}, Env, S),
541
767
    ConstInfo = get_const_info(Val, Type),
542
768
    Flags = translate_flags(LiteralFlags, Align),
543
769
    SizeInfo = calculate_size(Unit, Size, Align, Env, S0),
544
 
    bin_seg_gen_op(Ts, Ctxt, SizeInfo, ConstInfo, Type, Flags).
 
770
    bitstr_gen_op(Ts, Ctxt, SizeInfo, ConstInfo, Type, Flags, Base, Offset).
545
771
 
546
 
bin_seg_gen_op([V], #ctxt{fail=FL, class=guard}, SizeInfo, ConstInfo, Type, Flags) ->
 
772
bitstr_gen_op([V], #ctxt{fail=FL, class=guard}, SizeInfo, ConstInfo,
 
773
               Type, Flags, Base, Offset) ->
547
774
    SL = new_label(),
548
775
    case SizeInfo of
549
776
        {NewUnit, NewArgs, S1, NewAlign} ->
550
 
            Args = [V|NewArgs],
 
777
            Args = [V|NewArgs] ++ [Base, Offset],
551
778
            Name =
552
779
                case Type of
553
780
                    integer ->
557
784
                    binary ->
558
785
                        {bs_put_binary, NewUnit, Flags}
559
786
                end,
560
 
            {add_code([icode_guardop([], {hipe_bs_primop, Name} ,Args, SL, FL),
 
787
            Primop = {hipe_bs_primop, Name},
 
788
            {add_code([icode_guardop([Offset], Primop, Args, SL, FL),
561
789
                       icode_label(SL)], S1), NewAlign};
562
790
        {all, NewAlign, S1} ->
563
791
            Type = binary,
564
792
            Name = {bs_put_binary_all, Flags},
565
 
            {add_code([icode_guardop([], {hipe_bs_primop, Name}, [V], SL, FL),
 
793
            Primop = {hipe_bs_primop, Name},
 
794
            {add_code([icode_guardop([Offset], Primop,
 
795
                                     [V, Base, Offset], SL, FL),
566
796
                       icode_label(SL)], S1), NewAlign}
567
797
    end;
568
798
 
569
 
bin_seg_gen_op([V], _Ctxt, SizeInfo, ConstInfo, Type, Flags) ->
 
799
bitstr_gen_op([V], _Ctxt, SizeInfo, ConstInfo, Type, Flags, Base,
 
800
              Offset) ->
570
801
    case SizeInfo of
571
802
        {NewUnit, NewArgs, S, NewAlign} ->
572
 
            Args = [V|NewArgs],
 
803
            Args = [V|NewArgs] ++ [Base, Offset],
573
804
            Name =
574
805
                case Type of
575
806
                    integer ->
579
810
                    binary ->
580
811
                        {bs_put_binary, NewUnit, Flags}
581
812
                end,
582
 
            {add_code([icode_call_primop([], {hipe_bs_primop, Name} ,Args)], S), NewAlign};
 
813
            Primop = {hipe_bs_primop, Name},
 
814
            {add_code([icode_call_primop([Offset], Primop, Args)], S), 
 
815
             NewAlign};
583
816
        {all, NewAlign, S} ->
584
817
            Type = binary,
585
818
            Name = {bs_put_binary_all, Flags},
586
 
            {add_code([icode_call_primop([], {hipe_bs_primop, Name}, [V])], S), NewAlign}
 
819
            Primop = {hipe_bs_primop, Name},
 
820
            {add_code([icode_call_primop([Offset], Primop, 
 
821
                                         [V, Base, Offset])], S), 
 
822
             NewAlign}
587
823
    end.
588
824
 
 
825
%% ---------------------------------------------------------------------
 
826
%% Apply-expressions
 
827
 
589
828
%% Note that the arity of the called function only depends on the length
590
829
%% of the argument list; the arity stated by the function name is
591
830
%% ignored.
592
831
 
593
832
expr_apply(E, Ts, Ctxt, Env, S) ->
594
 
    Op = reduce_expr(cerl:apply_op(E)),
595
 
    Name = case cerl:is_c_var(Op) of
596
 
               true ->
597
 
                   case cerl:var_name(Op) of
598
 
                       {N, A} = Id when atom(N), integer(A) ->
599
 
                           case env__lookup(Id, Env) of
600
 
                               error ->
601
 
                                   %% This is assumed to be a function
602
 
                                   %% in the same module, not
603
 
                                   %% necessarily exported.
604
 
                                   Id;
605
 
                               {ok, #'fun'{}} ->
606
 
                                   %% This is assumed to be a
607
 
                                   %% nonescaping, nonexported function,
608
 
                                   %% defined locally by a
609
 
                                   %% letrec-expression.
610
 
                                   %% TODO: letrec-calls
611
 
                                   throw(calling_local_function_not_handled);
612
 
                               {ok, #var{}} ->
613
 
                                   error_msg(
614
 
                                     "cannot use functional "
615
 
                                     "values indirectly: ~P.",
616
 
                                     [Id, 5]),
617
 
                                   throw(error)
618
 
                           end;
619
 
                       _ ->
620
 
                           error_nonlocal_application(Op),
621
 
                           throw(error)
622
 
                   end;
623
 
               false ->
624
 
                   error_nonlocal_application(Op),
625
 
                   throw(error)
626
 
           end,
 
833
    Op = cerl_lib:reduce_expr(cerl:apply_op(E)),
627
834
    {Vs, S1} = expr_list(cerl:apply_args(E), Ctxt, Env, S),
628
 
    add_local_call(Name, Vs, Ts, Ctxt, S1, get_type(E)).
629
 
 
630
 
%% If we know the module and function names statically, we do not have
631
 
%% to go through the much more inefficient generic meta-call operator.
 
835
    case cerl:is_c_var(Op) of
 
836
        true ->
 
837
            case cerl:var_name(Op) of
 
838
                {N, A} = V when is_atom(N), is_integer(A) ->
 
839
                    case env__lookup(V, Env) of
 
840
                        error ->
 
841
                            %% Assumed to be a function in the
 
842
                            %% current module; we don't check.
 
843
                            add_local_call(V, Vs, Ts, Ctxt, S1,
 
844
                                           get_type(E));
 
845
                        {ok, #'fun'{label = L, vars = Vs1}} ->
 
846
                            %% Call to a local letrec-bound function.
 
847
                            add_letrec_call(L, Vs1, Vs, Ctxt, S1);
 
848
                        {ok, #var{}} ->
 
849
                            error_msg("cannot call via variable; must "
 
850
                                      "be closure converted: ~P.",
 
851
                                      [V, 5]),
 
852
                            throw(error)
 
853
                    end;
 
854
                _ ->
 
855
                    error_nonlocal_application(Op),
 
856
                    throw(error)
 
857
            end;
 
858
        false ->
 
859
            error_nonlocal_application(Op),
 
860
            throw(error)
 
861
    end.
 
862
 
 
863
%% ---------------------------------------------------------------------
 
864
%% Call-expressions
 
865
 
 
866
%% Unless we know the module and function names statically, we have to
 
867
%% go through the meta-call operator for a static number of arguments.
632
868
 
633
869
expr_call(E, Ts, Ctxt, Env, S) ->
634
 
    Module = reduce_expr(cerl:call_module(E)),
635
 
    Name = reduce_expr(cerl:call_name(E)),
 
870
    Module = cerl_lib:reduce_expr(cerl:call_module(E)),
 
871
    Name = cerl_lib:reduce_expr(cerl:call_name(E)),
636
872
    case cerl:is_c_atom(Module) and cerl:is_c_atom(Name) of
637
873
        true ->
638
874
            M = cerl:atom_val(Module),
639
 
            N = cerl:atom_val(Name),
 
875
            F = cerl:atom_val(Name),
640
876
            {Vs, S1} = expr_list(cerl:call_args(E), Ctxt, Env, S),
641
 
            Code = case Ctxt#ctxt.final of
642
 
                       false ->
643
 
                           [icode_call_remote(Ts, M, N, Vs)];
644
 
                       true ->
645
 
                           [icode_enter_remote(M, N, Vs)]
646
 
                   end,
647
 
            add_code(Code, S1);
 
877
            add_code(make_call(M, F, Ts, Vs, Ctxt), S1);
648
878
        false ->
649
 
            %% Metacalls are handled using the Icode `apply'
650
 
            %% instruction.
651
 
            Args = cerl:make_list(cerl:call_args(E)),
652
 
            {As, S1} = expr_list([Module, Name, Args], Ctxt, Env, S),
653
 
            Code = case Ctxt#ctxt.final of
654
 
                       false ->
655
 
                           [icode_call_remote(Ts, erlang, apply, As)];
656
 
                       true ->
657
 
                           [icode_enter_remote(erlang, apply, As)]
658
 
                   end,
659
 
            add_code(Code, S1)
 
879
            Args = cerl:call_args(E),
 
880
            N = length(Args),
 
881
            {Vs, S1} = expr_list([Module, Name | Args], Ctxt, Env, S),
 
882
            add_code(make_op(?OP_APPLY_FIXARITY(N), Ts, Vs, Ctxt), S1)
660
883
    end.
661
884
 
 
885
%% ---------------------------------------------------------------------
 
886
%% Primop calls
 
887
 
662
888
%% Core Erlang primop calls are generally mapped directly to Icode
663
889
%% primop calls, with a few exceptions (listed above), which are
664
890
%% expanded inline, sometimes depending on context. Note that primop
665
 
%% calls do not have specialized last-call forms.
 
891
%% calls do not have specialized tail-call forms.
666
892
 
667
893
expr_primop(E, Ts, Ctxt, Env, S) ->
668
894
    Name = cerl:atom_val(cerl:primop_name(E)),
692
918
    primop_apply_fun(As, Ts, Ctxt, Env, S);
693
919
expr_primop_1(?PRIMOP_FUN_ELEMENT, 2, As, _E, Ts, Ctxt, Env, S) ->
694
920
    primop_fun_element(As, Ts, Ctxt, Env, S);
 
921
expr_primop_1(?PRIMOP_DSETELEMENT, 3, As, _E, Ts, Ctxt, Env, S) ->
 
922
    primop_dsetelement(As, Ts, Ctxt, Env, S);
695
923
expr_primop_1(?PRIMOP_RECEIVE_SELECT, 0, _As, _E, Ts, Ctxt, _Env, S) ->
696
924
    primop_receive_select(Ts, Ctxt, S);
697
925
expr_primop_1(?PRIMOP_RECEIVE_NEXT, 0, _As, _E, _Ts, Ctxt, _Env, S) ->
698
926
    primop_receive_next(Ctxt, S);
699
 
expr_primop_1(?PRIMOP_IDENTITY, 1, [A], _E, Ts, Ctxt, Env, S) ->
700
 
    expr(A, Ts, Ctxt, Env, S);  % used for unary plus
 
927
%expr_primop_1(?PRIMOP_IDENTITY, 1, [A], _E, Ts, Ctxt, Env, S) ->
 
928
%    expr(A, Ts, Ctxt, Env, S);  % used for unary plus
701
929
expr_primop_1(?PRIMOP_NEG, 1, [A], _, Ts, Ctxt, Env, S) ->
702
930
    E = cerl:c_primop(cerl:c_atom('-'), [cerl:c_int(0), A]),
703
931
    expr_primop(E, Ts, Ctxt, Env, S);
 
932
expr_primop_1(?PRIMOP_GOTO_LABEL, 1, [A], _, _Ts, _Ctxt, _Env, S) ->
 
933
    primop_goto_label(A, S);
 
934
expr_primop_1(?PRIMOP_REDUCTION_TEST, 0, [], _, _Ts, Ctxt, _Env, S) ->
 
935
    primop_reduction_test(Ctxt, S);
704
936
expr_primop_1(Name, Arity, As, E, Ts, Ctxt, Env, S) ->
705
937
    Bool = case is_bool_op(Name, Arity) of
706
938
               true ->
721
953
            expr_primop_2(Name, Arity, Vs, Ts, Ctxt, S1)
722
954
    end.
723
955
 
 
956
expr_primop_2(?PRIMOP_ELEMENT, 2, Vs, Ts, Ctxt, S) ->
 
957
    add_code(make_op(?OP_ELEMENT, Ts, Vs, Ctxt), S);
724
958
expr_primop_2(?PRIMOP_EXIT, 1, [V], _Ts, Ctxt, S) ->
725
959
    add_exit(V, Ctxt, S);
726
960
expr_primop_2(?PRIMOP_THROW, 1, [V], _Ts, Ctxt, S) ->
729
963
    add_error(V, Ctxt, S);
730
964
expr_primop_2(?PRIMOP_ERROR, 2, [V, F], _Ts, Ctxt, S) ->
731
965
    add_error(V, F, Ctxt, S);
 
966
expr_primop_2(?PRIMOP_RETHROW, 2, [E, V], _Ts, Ctxt, S) ->
 
967
    add_rethrow(E, V, Ctxt, S);
732
968
expr_primop_2(Name, _Arity, Vs, Ts, Ctxt, S) ->
733
 
    maybe_return(Ts, Ctxt, add_code(make_op(Name, Ts, Vs, Ctxt), S)).
 
969
    %% Other ops are assumed to be recognized by the backend.
 
970
    add_code(make_op(Name, Ts, Vs, Ctxt), S).
734
971
 
735
972
%% All of M, F, and A must be literals with the right types.
736
973
%% V must represent a proper list.
750
987
            Index = cerl:int_val(I),
751
988
            {Vs, S1} = expr_list(cerl:list_elements(V),
752
989
                                 Ctxt, Env, S),
753
 
            S2 = add_code(make_op(?OP_MAKE_FUN(Module, Name, Arity,
754
 
                                               Hash, Index),
755
 
                                  Ts, Vs, Ctxt),
756
 
                          S1),
757
 
            maybe_return(Ts, Ctxt, S2);
 
990
            add_code(make_op(?OP_MAKE_FUN(Module, Name, Arity,
 
991
                                          Hash, Index),
 
992
                             Ts, Vs, Ctxt),
 
993
                     S1);
758
994
        false ->
759
995
            error_primop_badargs(?PRIMOP_MAKE_FUN, As),
760
996
            throw(error)
783
1019
    case cerl:is_c_int(N) of
784
1020
        true ->
785
1021
            V = make_var(),
786
 
            S1 = expr(F, [V], Ctxt, Env, S),
787
 
            S2 = add_code(make_op(?OP_FUN_ELEMENT(cerl:int_val(N)),
788
 
                                  Ts, [V], Ctxt),
789
 
                          S1),
790
 
            maybe_return(Ts, Ctxt, S2);
 
1022
            S1 = expr(F, [V], Ctxt#ctxt{final = false, effect = false},
 
1023
                      Env, S),
 
1024
            add_code(make_op(?OP_FUN_ELEMENT(cerl:int_val(N)),
 
1025
                             Ts, [V], Ctxt),
 
1026
                     S1);
791
1027
        false ->
792
1028
            error_primop_badargs(?PRIMOP_FUN_ELEMENT, As),
793
1029
            throw(error)
794
1030
    end.
795
1031
 
796
 
%% Catch-expressions:
797
 
 
798
 
expr_catch(E, [T] = Ts, Ctxt, Env, S) ->
799
 
    Cont = new_label(),
 
1032
primop_goto_label(A, S) ->
 
1033
    {Label,S1} = s__get_label(A, S),
 
1034
    add_code([icode_goto(Label)], S1).
 
1035
 
 
1036
is_goto(E) ->
 
1037
    case cerl:type(E) of 
 
1038
        primop ->
 
1039
            Name = cerl:atom_val(cerl:primop_name(E)),
 
1040
            As = cerl:primop_args(E),
 
1041
            Arity = length(As),
 
1042
            case {Name, Arity} of
 
1043
                {?PRIMOP_GOTO_LABEL, 1} ->
 
1044
                    true;
 
1045
                _ ->
 
1046
                    false
 
1047
            end;
 
1048
        _ ->
 
1049
            false
 
1050
    end.
 
1051
                       
 
1052
primop_reduction_test(Ctxt, S) ->
 
1053
    add_code(make_op(?OP_REDTEST, [], [], Ctxt), S).
 
1054
 
 
1055
primop_dsetelement([N | As1] = As, Ts, Ctxt, Env, S) ->
 
1056
    case cerl:is_c_int(N) of
 
1057
        true ->
 
1058
            {Vs, S1} = expr_list(As1, Ctxt, Env, S),
 
1059
            add_code(make_op(?OP_UNSAFE_SETELEMENT(cerl:int_val(N)),
 
1060
                             Ts, Vs, Ctxt),
 
1061
                     S1);
 
1062
        false ->
 
1063
            error_primop_badargs(?PRIMOP_DSETELEMENT, As),
 
1064
            throw(error)
 
1065
    end.
 
1066
 
 
1067
%% ---------------------------------------------------------------------
 
1068
%% Try-expressions:
 
1069
 
 
1070
%% We want to rewrite trivial things like `try A of X -> B catch ...',
 
1071
%% where A is safe, into a simple let-binding `let X = A in B', avoiding
 
1072
%% unnecessary try-blocks. (The `let' might become further simplified.)
 
1073
 
 
1074
expr_try(E, Ts, Ctxt, Env, S) ->
 
1075
    F = fun (B, Ctxt, Env, S) -> expr(B, Ts, Ctxt, Env, S) end,
 
1076
    expr_try_1(E, F, Ctxt, Env, S).
 
1077
 
 
1078
expr_try_1(E, F, Ctxt, Env, S) ->
 
1079
    A = cerl:try_arg(E),
 
1080
    case is_safe_expr(A) of
 
1081
        true ->
 
1082
            E1 = cerl:c_let(cerl:try_vars(E), A, cerl:try_body(E)),
 
1083
            expr_let_1(E1, F, Ctxt, Env, S);
 
1084
        false ->
 
1085
            expr_try_2(E, F, Ctxt, Env, S)
 
1086
    end.
 
1087
 
 
1088
%% TODO: maybe skip begin_try/end_try and just use fail-labels...
 
1089
 
 
1090
expr_try_2(E, F, Ctxt, Env, S) ->
 
1091
    Cont = new_continuation_label(Ctxt),
800
1092
    Catch = new_label(),
801
 
    S1 = add_code([icode_pushcatch(Catch,Cont),icode_label(Cont)], S),
 
1093
    Next = new_label(),
 
1094
    S1 = add_code([icode_begin_try(Catch,Next),icode_label(Next)], S),
 
1095
    Vars = cerl:try_vars(E),
 
1096
    Vs = make_vars(length(Vars)),
 
1097
    Ctxt1 = Ctxt#ctxt{final = false},
 
1098
    S2 = expr(cerl:try_arg(E), Vs, Ctxt1, Env, S1),
 
1099
    Env1 = bind_vars(Vars, Vs, Env),
 
1100
    S3 = add_code([icode_end_try()], S2),
 
1101
    S4 = F(cerl:try_body(E), Ctxt, Env1, S3),
 
1102
    S5 = add_continuation_jump(Cont, Ctxt, S4),
 
1103
    EVars = cerl:try_evars(E),
 
1104
    EVs = make_vars(length(EVars)),
 
1105
    Env2 = bind_vars(EVars, EVs, Env),
 
1106
    S6 = add_code([icode_label(Catch), icode_begin_handler(EVs)], S5),
 
1107
    S7 = F(cerl:try_handler(E), Ctxt, Env2, S6),
 
1108
    add_continuation_label(Cont, Ctxt, S7).
 
1109
 
 
1110
%% ---------------------------------------------------------------------
 
1111
%% Letrec-expressions (local goto-labels)
 
1112
 
 
1113
%% We only handle letrec-functions as continuations. The fun-bodies are
 
1114
%% always compiled in the same context as the main letrec-body. Note
 
1115
%% that we cannot propagate "advanced" contexts like boolean-compilation
 
1116
%% into the letrec body like we do for ordinary lets or seqs, since the
 
1117
%% context for an individual local function would be depending on the
 
1118
%% contexts of its call sites.
 
1119
 
 
1120
expr_letrec(E, Ts, Ctxt, Env, S) ->
 
1121
    Ds = cerl:letrec_defs(E),
 
1122
    Env1 = add_defs(Ds, Env),
 
1123
    S1 = expr(cerl:letrec_body(E), Ts, Ctxt, Env1, S),
802
1124
    Next = new_continuation_label(Ctxt),
803
 
    S2 = expr(cerl:catch_body(E), Ts, Ctxt, Env, S1),
804
 
    S3 = add_code([icode_remove_catch(Catch)], S2),
805
 
    S4 = add_continuation_jump(Next, Ctxt, S3),
806
 
    S5 = add_code([icode_label(Catch),
807
 
                   icode_restore_catch(T, Catch)],
808
 
                  S4),
809
 
    add_continuation_label(Next, Ctxt, S5);
810
 
expr_catch(_E, _Ts, _Ctxt, _Env, _S) ->
811
 
    error_msg("use of catch expression expects degree other than 1."),
812
 
    throw(error).
813
 
 
814
 
%% Try-expressions:
815
 
 
816
 
%% For now, we rewrite try-expressions to be simulated using
817
 
%% catch-expressions and unique references. The generated code has the
818
 
%% following structure:
819
 
%%
820
 
%%  let V0 = primop 'make_ref'() in
821
 
%%    case catch {V0, #TryArg#} of
822
 
%%      {V1, V2} when primop '=:='(V0, V1) -> V2
823
 
%%      V1 when 'true' ->
824
 
%%        let <#TryVars#> =
825
 
%%          case V1 of
826
 
%%            {'EXIT', V2} when 'true' -> <'EXIT', V2>
827
 
%%            V2 when 'true' -> <'THROW', V2>
828
 
%%          end
829
 
%%        in #TryBody#
830
 
%%     end
831
 
%%
832
 
%% (Note that even though we introduce new variables, they are only used
833
 
%% locally, so we never need to rename existing variables.)
834
 
 
835
 
expr_try(E, Ts, Ctxt = #ctxt{class = guard}, Env, S) ->
836
 
    %% The limited form of try-expressions allowed in guards:
837
 
    %%     "try Expr of X -> X catch <X1,X2> -> 'false' end".
838
 
    Fail = new_label(),
839
 
    Next = new_label(),
840
 
    Ctxt1 = Ctxt#ctxt{fail = Fail},
841
 
    S1 = expr(cerl:try_arg(E), Ts, Ctxt1, Env, S),
842
 
    S2 = add_code([icode_goto(Next), icode_label(Fail)], S1),
843
 
    S3 = expr(cerl:c_atom(false), Ts, Ctxt, Env, S2),
844
 
    add_code([icode_label(Next)], S3);
845
 
expr_try(_E, _Ts, _Ctxt, _Env, _S) ->
846
 
    throw(try_expressions_not_handled).
847
 
%%%     [Id0, Id1, Id2] = env__new_integer_keys(3, Env),
848
 
%%%     V0 = cerl:c_var(Id0),
849
 
%%%     V1 = cerl:c_var(Id1),
850
 
%%%     V2 = cerl:c_var(Id2),
851
 
%%%     True = cerl:c_atom('true'),
852
 
%%%     Exit = cerl:c_atom('EXIT'),
853
 
%%%     Throw = cerl:c_atom('THROW'),
854
 
%%%     Cs2 = [cerl:c_clause([cerl:c_tuple([Exit, V2])], True,
855
 
%%%                       cerl:c_values([Exit, V2])),
856
 
%%%        cerl:c_clause([V2], True,
857
 
%%%                       cerl:c_values([Throw, V2]))],
858
 
%%%     Body = cerl:c_let(cerl:try_vars(E),
859
 
%%%                    cerl:c_case(V1, Cs2),
860
 
%%%                    cerl:try_body(E)),
861
 
%%%     Guard = cerl:c_primop(cerl:c_atom('=:='), [V0, V1]),
862
 
%%%     Cs1 = [cerl:c_clause([cerl:c_tuple([V1, V2])], Guard, V2),
863
 
%%%        cerl:c_clause([V1], True, Body)],
864
 
%%%     Catch = cerl:c_catch(cerl:c_tuple([V0, cerl:try_expr(E)])),
865
 
%%%     MakeRef = cerl:c_primop(cerl:c_atom(make_ref), []),
866
 
%%%     E1 = cerl:c_let([V0], MakeRef, cerl:c_case(Catch, Cs1)),
867
 
%%% %%%    info_msg("\n" ++ cerl_prettypr:format(E1), []),
868
 
%%%     expr(Effect, E1, Ts, Ctxt, Env, S).
869
 
 
870
 
%% Receive-expressions: There may only be exactly one clause, which must
871
 
%% be a trivial catch-all with exactly one (variable) pattern. Each
872
 
%% message will be read from the mailbox and bound to the pattern
873
 
%% variable; the body of the clause must do the switching and call
874
 
%% either of the primops `receive_select/0' or `receive_next/0'.
 
1125
    S2 = add_continuation_jump(Next, Ctxt, S1),
 
1126
    S3 = defs(Ds, Ts, Ctxt, Env1, S2),
 
1127
    add_continuation_label(Next, Ctxt, S3).
 
1128
 
 
1129
add_defs([{V, _F} | Ds], Env) ->
 
1130
    {_, A} = cerl:var_name(V),
 
1131
    Vs = make_vars(A),
 
1132
    L = new_label(),
 
1133
    Env1 = bind_fun(V, L, Vs, Env),
 
1134
    add_defs(Ds, Env1);
 
1135
add_defs([], Env) ->
 
1136
    Env.
 
1137
 
 
1138
defs([{V, F} | Ds], Ts, Ctxt, Env, S) ->
 
1139
    Name = cerl:var_name(V),
 
1140
    #'fun'{label = L, vars = Vs} = env__get(Name, Env),
 
1141
    S1 = add_code([icode_label(L)], S),
 
1142
    Env1 = bind_vars(cerl:fun_vars(F), Vs, Env),
 
1143
    S2 = expr(cerl:fun_body(F), Ts, Ctxt, Env1, S1),
 
1144
    defs(Ds, Ts, Ctxt, Env, S2);
 
1145
defs([], _Ts, _Ctxt, _Env, S) ->
 
1146
    S.
 
1147
 
 
1148
%% ---------------------------------------------------------------------
 
1149
%% Receive-expressions
 
1150
 
 
1151
%% There may only be exactly one clause, which must be a trivial
 
1152
%% catch-all with exactly one (variable) pattern. Each message will be
 
1153
%% read from the mailbox and bound to the pattern variable; the body of
 
1154
%% the clause must do the switching and call either of the primops
 
1155
%% `receive_select/0' or `receive_next/0'.
875
1156
 
876
1157
expr_receive(E, Ts, Ctxt, Env, S) ->
 
1158
    F = fun (B, Ctxt, Env, S) -> expr(B, Ts, Ctxt, Env, S) end,
 
1159
    expr_receive_1(E, F, Ctxt, Env, S).
 
1160
 
 
1161
expr_receive_1(E, F, Ctxt, Env, S) ->
877
1162
    case cerl:receive_clauses(E) of
878
1163
        [C] ->
879
1164
            case cerl:clause_pats(C) of
880
1165
                [_] ->
881
1166
                    case cerl_clauses:is_catchall(C) of
882
1167
                        true ->
883
 
                            expr_receive_1(C, E, Ts, Ctxt, Env, S);
 
1168
                            expr_receive_2(C, E, F, Ctxt, Env, S);
884
1169
                        false ->
885
1170
                            error_msg("receive-expression clause "
886
 
                                      "is not a catch-all."),
 
1171
                                      "must be a catch-all."),
887
1172
                            throw(error)
888
1173
                    end;
889
1174
                _ ->
900
1185
%% There are a number of primitives to do the work involved in receiving
901
1186
%% messages:
902
1187
%%
903
 
%%      if-tests:       mbox_empty()
904
 
%%                      suspend_msg_timeout()
 
1188
%%      if-tests:       suspend_msg_timeout()
905
1189
%%
906
 
%%      primops:        V = get_msg()
 
1190
%%      primops:        V = check_get_msg()
907
1191
%%                      select_msg()
908
1192
%%                      next_msg()
909
1193
%%                      set_timeout(T)
910
1194
%%                      clear_timeout()
911
1195
%%                      suspend_msg()
912
1196
%%
913
 
%% `mbox_empty' tests if the mailbox is empty or not. `get_msg' reads
914
 
%% the message currently pointed to by the implicit message pointer.
 
1197
%% `check_get_msg' tests if the mailbox is empty or not, and if not it
 
1198
%% reads the message currently pointed to by the implicit message pointer.
915
1199
%% `select_msg' removes the current message from the mailbox, resets the
916
1200
%% message pointer and clears any timeout. `next_msg' advances the
917
1201
%% message pointer but does nothing else. `set_timeout(T)' sets up the
919
1203
%% until a message has arrived and does not check for timeout. The test
920
1204
%% `suspend_msg_timeout' suspends the process and upon resuming
921
1205
%% execution selects the `true' branch if a message has arrived and the
922
 
%% `false' branch otherwise. `clear_timeout' (the name is misleading)
923
 
%% resets the message pointer when a timeout has occurred.
 
1206
%% `false' branch otherwise. `clear_timeout' resets the message pointer
 
1207
%% when a timeout has occurred (the name is somewhat misleading).
924
1208
%%
925
1209
%% Note: the receiving of a message must be performed so that the
926
1210
%% message pointer is always reset when the receive is done; thus, all
930
1214
%% the clauses *and* the timeout action (but not over the
931
1215
%% timeout-expression, which is always executed for its value).
932
1216
 
933
 
expr_receive_1(C, E, Ts, Ctxt, Env, S0) ->
934
 
    Expiry = reduce_expr(cerl:receive_timeout(E)),
 
1217
%% This is the code we generate for a full receive:
 
1218
%%
 
1219
%%   Loop:      check_get_msg(Match, Wait)
 
1220
%%   Wait:      set_timeout
 
1221
%%              suspend_msg_timeout(Loop, Timeout)
 
1222
%%   Timeout:   clear_timeout
 
1223
%%              TIMEOUT-ACTION
 
1224
%%              goto Next
 
1225
%%   Match:     RECEIVE-CLAUSES(Loop, Next)
 
1226
%%   Next:      ...
 
1227
%%
 
1228
%% For a receive with infinity timout, we generate
 
1229
%%
 
1230
%%   Wait:      suspend_msg
 
1231
%%              goto Loop
 
1232
%%
 
1233
%% For a receive with zero timout, we generate
 
1234
%%
 
1235
%%   Wait:      clear_timeout
 
1236
%%              TIMEOUT-ACTION
 
1237
%%              goto Next
 
1238
 
 
1239
expr_receive_2(C, E, F, Ctxt, Env, S0) ->
 
1240
    Expiry = cerl_lib:reduce_expr(cerl:receive_timeout(E)),
935
1241
    After = case cerl:is_literal(Expiry) of
936
1242
                true ->
937
1243
                    cerl:concrete(Expiry);
941
1247
    T = make_var(),    % T will hold the timeout value
942
1248
    %% It would be harmless to generate code for `infinity', but we
943
1249
    %% might as well avoid it if we can.
944
 
    S1 = if After == 'infinity' -> S0;
 
1250
    S1 = if After =:= 'infinity' -> S0;
945
1251
            true ->
946
1252
                 expr(Expiry, [T],
947
1253
                      Ctxt#ctxt{final = false, effect = false},
955
1261
    Match = new_label(),
956
1262
    V = make_var(),
957
1263
    S2 = add_code([icode_label(Loop),
958
 
                   make_if(?TEST_MAILBOX_EMPTY, [], Wait, Match),
 
1264
                   icode_call_primop([V], ?OP_CHECK_GET_MESSAGE, [],
 
1265
                                     Match, Wait),
959
1266
                   icode_label(Wait)], S1),
960
1267
 
961
1268
    %% The wait-for-message section looks a bit different depending on
962
1269
    %% whether we actually need to set a timer or not.
 
1270
    Ctxt0 = #ctxt{},
963
1271
    S3 = case After of
964
1272
             'infinity' ->
965
1273
                 %% Only wake up when we get new messages, and never
966
1274
                 %% execute the expiry body.
967
 
                 add_code(make_op(?OP_WAIT_FOR_MESSAGE, [], [], #ctxt{})
968
 
                          ++ [icode_goto(Match)], S2);
 
1275
                 add_code(make_op(?OP_WAIT_FOR_MESSAGE, [], [], Ctxt0)
 
1276
                          ++ [icode_goto(Loop)], S2);
969
1277
             0 ->
970
 
                 %% Zero limit - go directly to the expiry body.
971
 
                 S2;
 
1278
                 %% Zero limit - reset the message pointer (this is what
 
1279
                 %% "clear timeout" does) and execute the expiry body.
 
1280
                 add_code(make_op(?OP_CLEAR_TIMEOUT, [], [], Ctxt0),
 
1281
                          S2);
972
1282
             _ ->
973
1283
                 %% Other value - set the timer (if it is already set,
974
1284
                 %% nothing is changed) and wait for a message or
975
1285
                 %% timeout. Reset the message pointer upon timeout.
976
1286
                 Timeout = new_label(),
977
 
                 Ctxt0 = #ctxt{},
978
1287
                 add_code(make_op(?OP_SET_TIMEOUT, [], [T], Ctxt0)
979
1288
                          ++ [make_if(?TEST_WAIT_FOR_MESSAGE_OR_TIMEOUT,
980
 
                                      [], Match, Timeout),
 
1289
                                      [], Loop, Timeout),
981
1290
                              icode_label(Timeout)]
982
1291
                          ++ make_op(?OP_CLEAR_TIMEOUT, [], [], Ctxt0),
983
1292
                          S2)
990
1299
    %% single constant value such as 'true', while the clauses may be
991
1300
    %% producing 2 or more values.)
992
1301
    Next = new_continuation_label(Ctxt),
993
 
    S4 = if After == 'infinity' -> S3;
 
1302
    S4 = if After =:= 'infinity' -> S3;
994
1303
            true ->
995
1304
                 add_continuation_jump(Next, Ctxt,
996
 
                                       expr(cerl:receive_action(E), Ts,
997
 
                                            Ctxt, Env, S3))
 
1305
                                       F(cerl:receive_action(E), Ctxt,
 
1306
                                         Env, S3))
998
1307
         end,
999
1308
 
1000
1309
    %% When we compile the primitive operations that select the current
1006
1315
 
1007
1316
    %% The pattern variable of the clause will be mapped to `V', which
1008
1317
    %% holds the message, so it can be accessed in the clause body:
1009
 
    S5 = add_code([icode_label(Match)]
1010
 
                  ++ make_op(?OP_GET_MESSAGE, [V], [], #ctxt{}),
1011
 
                  S4),
1012
 
    S6 = clauses([C], Ts, [V], Ctxt1, Env, S5),
1013
 
    add_continuation_label(Next, Ctxt, S6).
 
1318
    S5 = clauses([C], F, [V], Ctxt1, Env,
 
1319
                 add_code([icode_label(Match)], S4)),
 
1320
    add_continuation_label(Next, Ctxt, S5).
1014
1321
 
1015
1322
%% Primops supporting "expanded" receive-expressions on the Core level:
1016
1323
 
1023
1330
            %% same - add a dummy label if necessary.
1024
1331
            S1 = add_code(make_op(?OP_NEXT_MESSAGE, [], [], #ctxt{})
1025
1332
                          ++ [icode_goto(Loop)], S0),
1026
 
            L = new_continuation_label(Ctxt),
1027
 
            add_continuation_label(L, Ctxt, S1);
 
1333
            add_new_continuation_label(Ctxt, S1);
1028
1334
        _ ->
1029
 
            warning_not_in_receive(?PRIMOP_RECEIVE_NEXT),
1030
 
            S0
 
1335
            error_not_in_receive(?PRIMOP_RECEIVE_NEXT),
 
1336
            throw(error)
1031
1337
    end.
1032
1338
 
1033
1339
primop_receive_select(Ts, #ctxt{'receive' = R} = Ctxt, S) ->
1034
1340
    case R of
1035
1341
        #'receive'{} ->
1036
 
            S1 = add_code(make_op(?OP_SELECT_MESSAGE, [], [], Ctxt),
1037
 
                          S),
1038
 
            maybe_return(Ts, Ctxt, S1);
 
1342
            add_code(make_op(?OP_SELECT_MESSAGE, Ts, [], Ctxt), S);
1039
1343
        _ ->
1040
 
            warning_not_in_receive(?PRIMOP_RECEIVE_SELECT),
1041
 
            S
 
1344
            error_not_in_receive(?PRIMOP_RECEIVE_SELECT),
 
1345
            throw(error)
1042
1346
    end.
1043
1347
 
 
1348
%% ---------------------------------------------------------------------
1044
1349
%% Case expressions
1045
1350
 
1046
 
%% We know that the pattern matching compilation has split all switches
1047
 
%% into separate groups of tuples, integers, atoms, etc., and that each
1048
 
%% such switch over a group of constructors is protected by a type test.
1049
 
%% Thus, it is straightforward to generate switch instructions.
 
1351
%% Typically, pattern matching compilation has split all switches into
 
1352
%% separate groups of tuples, integers, atoms, etc., where each such
 
1353
%% switch over a group of constructors is protected by a type test.
 
1354
%% Thus, it is straightforward to generate switch instructions. (If no
 
1355
%% pattern matching compilation has been done, we don't care about
 
1356
%% efficiency anyway, so we don't spend any extra effort here.)
1050
1357
 
1051
1358
expr_case(E, Ts, Ctxt, Env, S) ->
 
1359
    F = fun (B, Ctxt, Env, S) -> expr(B, Ts, Ctxt, Env, S) end,
 
1360
    expr_case_1(E, F, Ctxt, Env, S).
 
1361
 
 
1362
expr_case_1(E, F, Ctxt, Env, S) ->
1052
1363
    Cs = cerl:case_clauses(E),
1053
 
    Vs = make_vars(clauses_degree(Cs)),
1054
 
    S1 = expr(cerl:case_arg(E), Vs,
1055
 
              Ctxt#ctxt{final = false, effect = false}, Env, S),
 
1364
    A = cerl:case_arg(E),
 
1365
    case cerl_lib:is_bool_switch(Cs) of
 
1366
        true ->
 
1367
            %% An if-then-else with a known boolean argument
 
1368
            {True, False} = cerl_lib:bool_switch_cases(Cs),
 
1369
            bool_switch(A, True, False, F, Ctxt, Env, S);
 
1370
        false ->
 
1371
            Vs = make_vars(cerl:clause_arity(hd(Cs))),
 
1372
            Ctxt1 = Ctxt#ctxt{final = false, effect = false},
 
1373
            S1 = expr(A, Vs, Ctxt1, Env, S),
 
1374
            expr_case_2(Vs, Cs, F, Ctxt, Env, S1)
 
1375
    end.
 
1376
 
 
1377
%% Switching on a value
 
1378
 
 
1379
expr_case_2(Vs, Cs, F, Ctxt, Env, S1) ->
1056
1380
    case is_constant_switch(Cs) of
1057
1381
        true ->
1058
 
            switch_val_clauses(Cs, Ts, Vs, Ctxt, Env, S1);
 
1382
            switch_val_clauses(Cs, F, Vs, Ctxt, Env, S1);
1059
1383
        false ->
1060
1384
            case is_tuple_switch(Cs) of
1061
1385
                true ->
1062
 
                    switch_tuple_clauses(Cs, Ts, Vs, Ctxt, Env, S1);
 
1386
                    switch_tuple_clauses(Cs, F, Vs, Ctxt, Env, S1);
1063
1387
                false ->
1064
 
                    clauses(Cs, Ts, Vs, Ctxt, Env, S1)
 
1388
                    case is_binary_switch(Cs, S1) of
 
1389
                        true ->
 
1390
                            switch_binary_clauses(Cs, F, Vs, Ctxt, Env, S1);
 
1391
                        false ->
 
1392
                            clauses(Cs, F, Vs, Ctxt, Env, S1)
 
1393
                    end
1065
1394
            end
1066
1395
    end.
1067
1396
 
1068
 
%% We check only the first clause to see what the degree of the
1069
 
%% corresponding switch expression should be. (I.e., we assume that we
1070
 
%% are given nice code that does not combine clauses with differing
1071
 
%% pattern degrees.)
1072
 
 
1073
 
clauses_degree([C | _Cs]) ->
1074
 
    length(cerl:clause_pats(C)).
1075
 
 
1076
1397
%% Check if a list of clauses represents a switch over a number (more
1077
1398
%% than 1) of constants (atoms or integers/floats), or tuples (whose
1078
1399
%% elements are all variables)
1079
1400
 
1080
1401
is_constant_switch(Cs) ->
1081
 
    is_switch(Cs, fun (P) -> (cerl:type(P) == literal) andalso
 
1402
    is_switch(Cs, fun (P) -> (cerl:type(P) =:= literal) andalso
1082
1403
                                 is_constant(cerl:concrete(P)) end).
1083
1404
 
1084
1405
is_tuple_switch(Cs) ->
1085
1406
    is_switch(Cs, fun (P) -> cerl:is_c_tuple(P) andalso
1086
1407
                                 all_vars(cerl:tuple_es(P)) end).
1087
1408
 
 
1409
is_binary_switch(Cs, S) ->
 
1410
    case s__get_pmatch(S) of
 
1411
        False when False =:= false; False =:= undefined ->
 
1412
            false;
 
1413
        Other when Other =:= duplicate_all; Other =:= no_duplicates; Other =:= true->
 
1414
            is_binary_switch1(Cs, 0)
 
1415
    end.
 
1416
 
 
1417
is_binary_switch1([C|Cs], N) ->
 
1418
    case cerl:clause_pats(C) of
 
1419
        [P] ->
 
1420
            case cerl:is_c_binary(P) of
 
1421
                true ->
 
1422
                    is_binary_switch1(Cs, N + 1);
 
1423
                false -> 
 
1424
                    if Cs =:= [], N > 0 ->
 
1425
                            %% The final clause may be a catch-all.
 
1426
                            cerl:type(P) =:= var;
 
1427
                       true ->
 
1428
                            false
 
1429
                    end
 
1430
            end;
 
1431
        _ ->
 
1432
            false
 
1433
    end;
 
1434
is_binary_switch1([], N) ->
 
1435
    N > 0.
 
1436
 
1088
1437
all_vars([E | Es]) ->
1089
1438
    case cerl:is_c_var(E) of
1090
1439
        true -> all_vars(Es);
1096
1445
    is_switch(Cs, F, 0).
1097
1446
 
1098
1447
is_switch([C | Cs], F, N) ->
1099
 
    case is_simple_clause(C) of
1100
 
        {true, P} ->
 
1448
    case cerl_lib:is_simple_clause(C) of
 
1449
        true ->
 
1450
            [P] = cerl:clause_pats(C),
1101
1451
            case F(P) of
1102
1452
                true ->
1103
1453
                    is_switch(Cs, F, N + 1);
1104
1454
                false ->
1105
 
                    if Cs == [], N > 1 ->
 
1455
                    if Cs =:= [], N > 1 ->
1106
1456
                            %% The final clause may be a catch-all.
1107
 
                            cerl:type(P) == var;
 
1457
                            cerl:type(P) =:= var;
1108
1458
                       true ->
1109
1459
                            false
1110
1460
                    end
1114
1464
is_switch([], _F, N) ->
1115
1465
    N > 1.
1116
1466
 
1117
 
is_simple_clause(C) ->
1118
 
    case cerl:clause_pats(C) of
1119
 
        [P] ->
1120
 
            G = cerl:clause_guard(C),
1121
 
            case cerl_clauses:eval_guard(G) of
1122
 
                {value, true} -> {true, P};
1123
 
                _ -> false
1124
 
            end;
1125
 
        _ -> false
1126
 
    end.
1127
 
 
1128
 
switch_val_clauses(Cs, Ts, Vs, Ctxt, Env, S) ->
1129
 
    switch_clauses(Cs, Ts, Vs, Ctxt, Env,
 
1467
switch_val_clauses(Cs, F, Vs, Ctxt, Env, S) ->
 
1468
    switch_clauses(Cs, F, Vs, Ctxt, Env,
1130
1469
                   fun (P) -> cerl:concrete(P) end,
1131
1470
                   fun icode_switch_val/4,
1132
1471
                   fun val_clause_body/9,
1133
1472
                   S).
1134
1473
 
1135
 
val_clause_body(_N, _V, C, Ts, Next, _Fail, Ctxt, Env, S) ->
1136
 
    clause_body(C, Ts, Next, Ctxt, Env, S).
 
1474
val_clause_body(_N, _V, C, F, Next, _Fail, Ctxt, Env, S) ->
 
1475
    clause_body(C, F, Next, Ctxt, Env, S).
1137
1476
 
1138
 
switch_tuple_clauses(Cs, Ts, Vs, Ctxt, Env, S) ->
1139
 
    switch_clauses(Cs, Ts, Vs, Ctxt, Env, 
 
1477
switch_tuple_clauses(Cs, F, Vs, Ctxt, Env, S) ->
 
1478
    switch_clauses(Cs, F, Vs, Ctxt, Env, 
1140
1479
                   fun (P) -> cerl:tuple_arity(P) end,
1141
1480
                   fun icode_switch_tuple_arity/4,
1142
1481
                   fun tuple_clause_body/9,
1143
1482
                   S).
1144
1483
 
1145
 
tuple_clause_body(N, V, C, Ts, Next, Fail, Ctxt, Env, S0) ->
 
1484
tuple_clause_body(N, V, C, F, Next, Fail, Ctxt, Env, S0) ->
1146
1485
    Vs = make_vars(N),
1147
1486
    S1 = tuple_elements(Vs, V, S0),
1148
1487
    Es = cerl:tuple_es(hd(cerl:clause_pats(C))),
1149
1488
    {Env1, S2} = patterns(Es, Vs, Fail, Env, S1),
1150
 
    clause_body(C, Ts, Next, Ctxt, Env1, S2).
 
1489
    clause_body(C, F, Next, Ctxt, Env1, S2).
1151
1490
 
1152
 
switch_clauses(Cs, Ts, [V], Ctxt, Env, GetVal, Switch, Body, S0) ->
 
1491
switch_clauses(Cs, F, [V], Ctxt, Env, GetVal, Switch, Body, S0) ->
1153
1492
    Cs1 = [switch_clause(C, GetVal) || C <- Cs],
1154
1493
    Cases = [{V, L} || {V, L, _} <- Cs1],
1155
1494
    Default = [C || {default, C} <- Cs1],
1156
1495
    Fail = new_label(),
1157
1496
    S1 = add_code([Switch(V, Fail, length(Cases), Cases)], S0),
1158
1497
    Next = new_continuation_label(Ctxt),
1159
 
    S2 = case Default of
1160
 
             [] -> add_infinite_loop(Fail, S1);
 
1498
    S3 = case Default of
 
1499
             [] -> add_default_case(Fail, Ctxt, S1);
1161
1500
             [C] ->
1162
 
                 clause_body(C, Ts, Next, Ctxt, Env,
1163
 
                             add_code([icode_label(Fail)], S1))
 
1501
                 %% Bind the catch-all variable (this always succeeds)
 
1502
                 {Env1, S2} = patterns(cerl:clause_pats(C), [V], Fail,
 
1503
                                       Env, S1),
 
1504
                 clause_body(C, F, Next, Ctxt, Env1,
 
1505
                             add_code([icode_label(Fail)], S2))
1164
1506
         end,
1165
 
    S3 = switch_cases(Cs1, V, Ts, Next, Fail, Ctxt, Env, Body, S2),
1166
 
    add_continuation_label(Next, Ctxt, S3).
 
1507
    S4 = switch_cases(Cs1, V, F, Next, Fail, Ctxt, Env, Body, S3),
 
1508
    add_continuation_label(Next, Ctxt, S4).
1167
1509
 
1168
1510
switch_clause(C, F) ->
1169
1511
    [P] = cerl:clause_pats(C),
1173
1515
        _ -> {icode_const(F(P)), L, C}
1174
1516
    end.
1175
1517
 
1176
 
switch_cases([{N, L, C} | Cs], V, Ts, Next, Fail, Ctxt, Env, Body,
1177
 
             S0) ->
 
1518
switch_binary_clauses(Cs, F, Vs, Ctxt, Env, S) ->
 
1519
    {Bins, Default} = get_binary_clauses(Cs),
 
1520
    BMatch = cerl_binary_pattern_match:add_offset_to_bin(Bins),
 
1521
    Fail = new_label(),
 
1522
    Next = new_continuation_label(Ctxt),
 
1523
    S1 = binary_match(BMatch, F, Vs, Next, Fail, Ctxt, Env, S),
 
1524
    S2 = case Default of
 
1525
             [] -> add_default_case(Fail, Ctxt, S1);
 
1526
             [C] ->
 
1527
                 clause_body(C, F, Next, Ctxt, Env,
 
1528
                             add_code([icode_label(Fail)], S1))
 
1529
         end,
 
1530
    add_continuation_label(Next, Ctxt, S2).
 
1531
    
 
1532
get_binary_clauses(Cs) ->    
 
1533
    get_binary_clauses(Cs, []).
 
1534
 
 
1535
get_binary_clauses([C|Cs], Acc) ->
 
1536
    [P] = cerl:clause_pats(C),
 
1537
    case cerl:is_c_binary(P) of 
 
1538
        true ->
 
1539
            get_binary_clauses(Cs, [C|Acc]);
 
1540
        false ->
 
1541
            {lists:reverse(Acc),[C]}
 
1542
    end;
 
1543
get_binary_clauses([], Acc) ->
 
1544
    {lists:reverse(Acc),[]}.
 
1545
 
 
1546
switch_cases([{N, L, C} | Cs], V, F, Next, Fail, Ctxt, Env, Body, S0) ->
1178
1547
    S1 = add_code([icode_label(L)], S0),
1179
 
    S2 = Body(icode_const_val(N), V, C, Ts, Next, Fail, Ctxt, Env, S1),
1180
 
    switch_cases(Cs, V, Ts, Next, Fail, Ctxt, Env, Body, S2);
1181
 
switch_cases([_ | Cs], V, Ts, Next, Fail, Ctxt, Env, Body, S) ->
1182
 
    switch_cases(Cs, V, Ts, Next, Fail, Ctxt, Env, Body, S);
1183
 
switch_cases([], _V, _Ts, _Next, _Fail, _Ctxt, _Env, _Body, S) ->
 
1548
    S2 = Body(icode_const_val(N), V, C, F, Next, Fail, Ctxt, Env, S1),
 
1549
    switch_cases(Cs, V, F, Next, Fail, Ctxt, Env, Body, S2);
 
1550
switch_cases([_ | Cs], V, F, Next, Fail, Ctxt, Env, Body, S) ->
 
1551
    switch_cases(Cs, V, F, Next, Fail, Ctxt, Env, Body, S);
 
1552
switch_cases([], _V, _F, _Next, _Fail, _Ctxt, _Env, _Body, S) ->
1184
1553
    S.
1185
1554
 
1186
 
%% The exact behaviour if all clauses fail is undefined; we generate
1187
 
%% code to keep the executing program in an infinite loop if this
1188
 
%% happens, which is safe and will not destroy information for later
1189
 
%% analyses. (We do not want to throw an arbitrary exception, and
1190
 
%% continuing execution after the `case', as in a C `switch' statement,
1191
 
%% would add a new possible path to the program, which could destroy
1192
 
%% program properties.) Recall that the `final' and `effect' context
1193
 
%% flags distribute over the clause bodies.
 
1555
%% Recall that the `final' and `effect' context flags distribute over
 
1556
%% the clause bodies.
1194
1557
 
1195
 
clauses(Cs, Ts, Vs, Ctxt, Env, S) ->
 
1558
clauses(Cs, F, Vs, Ctxt, Env, S) ->
1196
1559
    Next = new_continuation_label(Ctxt),
1197
 
    S1 = clauses_1(Cs, Ts, Vs, undefined, Next, Ctxt, Env, S),
 
1560
    S1 = clauses_1(Cs, F, Vs, undefined, Next, Ctxt, Env, S),
1198
1561
    add_continuation_label(Next, Ctxt, S1).
1199
1562
 
1200
 
clauses_1([C | Cs], Ts, Vs, Fail, Next, Ctxt, Env, S) ->
 
1563
clauses_1([C | Cs], F, Vs, Fail, Next, Ctxt, Env, S) ->
1201
1564
    case cerl_clauses:is_catchall(C) of
1202
1565
        true ->
1203
1566
            %% The fail label will not actually be used in this case.
1204
 
            clause(C, Ts, Vs, Fail, Next, Ctxt, Env, S);
 
1567
            clause(C, F, Vs, Fail, Next, Ctxt, Env, S);
1205
1568
        false ->
1206
1569
            %% The previous `Fail' is not used here.
1207
1570
            Fail1 = new_label(),
1208
 
            S1 = clause(C, Ts, Vs, Fail1, Next, Ctxt, Env, S),
 
1571
            S1 = clause(C, F, Vs, Fail1, Next, Ctxt, Env, S),
1209
1572
            S2 = add_code([icode_label(Fail1)], S1),
1210
 
            clauses_1(Cs, Ts, Vs, Fail1, Next, Ctxt, Env, S2)
 
1573
            clauses_1(Cs, F, Vs, Fail1, Next, Ctxt, Env, S2)
1211
1574
    end;
1212
 
clauses_1([], _Ts, _Vs, Fail, _Next, _Ctxt, _Env, S) ->
1213
 
    if Fail == undefined ->
 
1575
clauses_1([], _F, _Vs, Fail, _Next, Ctxt, _Env, S) ->
 
1576
    if Fail =:= undefined ->
1214
1577
            L = new_label(),
1215
 
            add_infinite_loop(L, S);
 
1578
            add_default_case(L, Ctxt, S);
1216
1579
       true ->
1217
1580
            add_code([icode_goto(Fail)], S)    % use existing label
1218
1581
    end.
1219
1582
 
1220
 
add_infinite_loop(L, S) ->
1221
 
    add_code([icode_label(L), icode_goto(L)], S).
1222
 
 
1223
 
clause(C, Ts, Vs, Fail, Next, Ctxt, Env, S) ->
 
1583
%% The exact behaviour if all clauses fail is undefined; we generate an
 
1584
%% 'internal_error' exception if this happens, which is safe and will
 
1585
%% not get in the way of later analyses. (Continuing execution after the
 
1586
%% `case', as in a C `switch' statement, would add a new possible path
 
1587
%% to the program, which could destroy program properties.) Note that
 
1588
%% this code is only generated if some previous stage has created a
 
1589
%% switch over clauses without a final catch-all; this could be both
 
1590
%% legal and non-redundant, e.g. if the last clause does pattern
 
1591
%% matching to extract components of a (known) constructor. The
 
1592
%% generated default-case code *should* be unreachable, but we need it
 
1593
%% in order to have a safe fail-label.
 
1594
 
 
1595
add_default_case(L, Ctxt, S) ->
 
1596
    S1 = add_code([icode_label(L)], S),
 
1597
    add_error(icode_const(internal_error), Ctxt, S1).
 
1598
 
 
1599
clause(C, F, Vs, Fail, Next, Ctxt, Env, S) ->
1224
1600
    G = cerl:clause_guard(C),
1225
1601
    case cerl_clauses:eval_guard(G) of
1226
1602
        {value, true} ->
1227
1603
            {Env1, S1} = patterns(cerl:clause_pats(C), Vs, Fail, Env,
1228
1604
                                  S),
1229
 
            clause_body(C, Ts, Next, Ctxt, Env1, S1);
 
1605
            clause_body(C, F, Next, Ctxt, Env1, S1);
1230
1606
        {value, false} ->
1231
1607
            add_code([icode_goto(Fail)], S);
1232
1608
        _ ->
1238
1614
                              class = guard},
1239
1615
            S2 = boolean(G, Succ, Fail, Ctxt1, Env1, S1),
1240
1616
            S3 = add_code([icode_label(Succ)], S2),
1241
 
            clause_body(C, Ts, Next, Ctxt, Env1, S3)
 
1617
            clause_body(C, F, Next, Ctxt, Env1, S3)
1242
1618
    end.
1243
1619
 
1244
 
clause_body(C, Ts, Next, Ctxt, Env, S) ->
1245
 
    S1 = expr(cerl:clause_body(C), Ts, Ctxt, Env, S),
1246
 
    add_continuation_jump(Next, Ctxt, S1).
 
1620
clause_body(C, F, Next, Ctxt, Env, S) ->
 
1621
    %% This check is inserted as a goto is always final 
 
1622
    case is_goto(cerl:clause_body(C)) of
 
1623
        true ->
 
1624
            F(cerl:clause_body(C), Ctxt, Env, S);
 
1625
        false ->
 
1626
            S1 = F(cerl:clause_body(C), Ctxt, Env, S),
 
1627
            add_continuation_jump(Next, Ctxt, S1)
 
1628
    end.
1247
1629
 
1248
1630
patterns([P | Ps], [V | Vs], Fail, Env, S) ->
1249
1631
    {Env1, S1} = pattern(P, V, Fail, Env, S),
1276
1658
 
1277
1659
literal_pattern_1(P, V, Fail, Next, S) ->
1278
1660
    case cerl:concrete(P) of
1279
 
        X when atom(X) ->
1280
 
            add_code([make_type(V, ?TYPE_ATOM(X), Next, Fail)],
1281
 
                     S);
1282
 
        X when integer(X) ->
1283
 
            add_code([make_type(V, ?TYPE_INTEGER(X), Next, Fail)],
1284
 
                     S);
1285
 
        X when float(X) ->
 
1661
        X when is_atom(X) ->
 
1662
            add_code([make_type([V], ?TYPE_ATOM(X), Next, Fail)],
 
1663
                     S);
 
1664
        X when is_integer(X) ->
 
1665
            add_code([make_type([V], ?TYPE_INTEGER(X), Next, Fail)],
 
1666
                     S);
 
1667
        X when is_float(X) ->
1286
1668
            V1 = make_var(),
1287
1669
            L = new_label(),
1288
1670
            %% First doing an "is float" test here might allow later
1289
1671
            %% stages to use a specialized equality test.
1290
 
            add_code([make_type(V, ?TYPE_IS_FLOAT, L, Fail),
 
1672
            add_code([make_type([V], ?TYPE_IS_FLOAT, L, Fail),
1291
1673
                      icode_label(L),
1292
 
                      icode_mov(V1, icode_const(X)),
 
1674
                      icode_move(V1, icode_const(X)),
1293
1675
                      make_if(?TEST_EQ, [V, V1], Next, Fail)],
1294
1676
                     S);
1295
1677
        [] ->
1296
 
            add_code([make_type(V, ?TYPE_NIL, Next, Fail)], S);
 
1678
            add_code([make_type([V], ?TYPE_NIL, Next, Fail)], S);
1297
1679
        X ->
1298
1680
            %% Compound constants are compared with the generic exact
1299
1681
            %% equality test.
1300
1682
            V1 = make_var(),
1301
 
            add_code([icode_mov(V1, icode_const(X)),
1302
 
                      make_if(?TEST_EQ, [V, V1], Next, Fail)],
 
1683
            add_code([icode_move(V1, icode_const(X)),
 
1684
                      make_if(?TEST_EXACT_EQ, [V, V1], Next, Fail)],
1303
1685
                     S)
1304
1686
    end.
1305
1687
 
1307
1689
    V1 = make_var(),
1308
1690
    V2 = make_var(),
1309
1691
    Next = new_label(),
1310
 
    S1 = add_code([make_type(V, ?TYPE_CONS, Next, Fail),
 
1692
    Ctxt = #ctxt{},
 
1693
    S1 = add_code([make_type([V], ?TYPE_CONS, Next, Fail),
1311
1694
                   icode_label(Next)]
1312
 
                  ++ make_op(?OP_UNSAFE_HD, [V1], [V], #ctxt{})
1313
 
                  ++ make_op(?OP_UNSAFE_TL, [V2], [V], #ctxt{}),
 
1695
                  ++ make_op(?OP_UNSAFE_HD, [V1], [V], Ctxt)
 
1696
                  ++ make_op(?OP_UNSAFE_TL, [V2], [V], Ctxt),
1314
1697
                  S),
1315
1698
    patterns([cerl:cons_hd(P), cerl:cons_tl(P)], [V1, V2],
1316
1699
             Fail, Env, S1).
1320
1703
    N = length(Es),
1321
1704
    Vs = make_vars(N),
1322
1705
    Next = new_label(),
1323
 
    S1 = add_code([make_type(V, ?TYPE_TUPLE(N), Next, Fail),
 
1706
    S1 = add_code([make_type([V], ?TYPE_IS_N_TUPLE(N), Next, Fail),
1324
1707
                   icode_label(Next)],
1325
1708
                  S),
1326
1709
    S2 = tuple_elements(Vs, V, S1),
1337
1720
 
1338
1721
binary_pattern(P, V, Fail, Env, S) ->
1339
1722
    L1 = new_label(),
1340
 
    Segs = cerl:binary_segs(P),
 
1723
    Segs = cerl:binary_segments(P),
1341
1724
    Arity = length(Segs),
1342
1725
    Vars = make_vars(Arity),
1343
 
    S1 = add_code([icode_guardop([], {hipe_bs_primop, bs_start_match}, [V], L1, Fail),
 
1726
    Primop1 = {hipe_bs_primop, bs_start_match},
 
1727
    S1 = add_code([icode_guardop([], Primop1, [V], L1, Fail),
1344
1728
                   icode_label(L1)],S),
1345
1729
    {Env1,S2} = bin_seg_patterns(Segs, Vars, Fail, Env, S1, 0),
1346
1730
    L2 = new_label(),
1347
 
    {Env1,add_code([icode_guardop([], {hipe_bs_primop, {bs_test_tail,0}}, [], L2, Fail),
1348
 
                    icode_label(L2)], S2)}.
 
1731
    Primop2 = {hipe_bs_primop, {bs_test_tail, 0}},
 
1732
    {Env1, add_code([icode_guardop([], Primop2, [], L2, Fail),
 
1733
                     icode_label(L2)], S2)}.
1349
1734
 
1350
1735
bin_seg_patterns([Seg|Rest], [T|Ts], Fail, Env, S, Align) ->
1351
1736
    {{NewEnv, S1}, NewAlign} = bin_seg_pattern(Seg, T, Fail, Env, S, Align),
1356
1741
 
1357
1742
bin_seg_pattern(P, V, Fail, Env, S, Align) ->
1358
1743
    L = new_label(),
1359
 
    Size = cerl:bin_seg_size(P),
1360
 
    Unit = cerl:bin_seg_unit(P),
1361
 
    Type = cerl:concrete(cerl:bin_seg_type(P)),
1362
 
    LiteralFlags = cerl:bin_seg_flags(P),
1363
 
    T = cerl:bin_seg_val(P), 
1364
 
    Flags=translate_flags(LiteralFlags, Align),
 
1744
    Size = cerl:bitstr_size(P),
 
1745
    Unit = cerl:bitstr_unit(P),
 
1746
    Type = cerl:concrete(cerl:bitstr_type(P)),
 
1747
    LiteralFlags = cerl:bitstr_flags(P),
 
1748
    T = cerl:bitstr_val(P), 
 
1749
    Flags = translate_flags(LiteralFlags, Align),
1365
1750
    case calculate_size(Unit, Size, Align, Env, S) of
1366
1751
        {NewUnit, Args, S0, NewAlign} ->
1367
1752
            Name =
1373
1758
                    binary ->
1374
1759
                        {bs_get_binary, NewUnit, Flags}
1375
1760
                end,
1376
 
            S1= add_code([icode_guardop([V],{hipe_bs_primop, Name}, Args, L, Fail),
1377
 
                          icode_label(L)], S0),
 
1761
            Primop = {hipe_bs_primop, Name},
 
1762
            S1 = add_code([icode_guardop([V], Primop, Args, L, Fail),
 
1763
                           icode_label(L)], S0),
1378
1764
            {pattern(T, V, Fail, Env, S1), NewAlign};
1379
1765
        {all, NewAlign, S0} ->
1380
1766
            Type = binary,
1381
1767
            Name = {bs_get_binary_all, Flags},
1382
 
            S1= add_code([icode_guardop([V], {hipe_bs_primop, Name}, [], L, Fail),
1383
 
                          icode_label(L)], S0),
 
1768
            Primop = {hipe_bs_primop, Name},
 
1769
            S1 = add_code([icode_guardop([V], Primop, [], L, Fail),
 
1770
                           icode_label(L)], S0),
1384
1771
            {pattern(T, V, Fail, Env, S1), NewAlign}
1385
1772
    end.
1386
1773
 
 
1774
%binary_pattern(P, V, Fail, Env, S) ->
 
1775
%    L1 = new_label(),
 
1776
%    L2 = new_label(),
 
1777
%    Orig = make_var(), 
 
1778
%    OrigOffset = make_var(),
 
1779
%    BinSize = make_var(),
 
1780
%    State = {Orig, OrigOffset, BinSize},
 
1781
%    {Size, NewBinSegs} = cerl_binary_pattern_match:add_offset_to_pattern(P), 
 
1782
%    Arity = length(NewBinSegs),
 
1783
%    Vars = make_vars(Arity),
 
1784
%    S1 = add_code([icode_guardop([Orig], {hipe_bsi_primop, bs_get_orig}, [V], L1, Fail),
 
1785
%                  icode_label(L1),
 
1786
%                  icode_call_primop([OrigOffset], {hipe_bsi_primop, bs_get_orig_offset}, [V]),
 
1787
%                  icode_call_primop([BinSize], {hipe_bsi_primop, bs_get_size}, [V])], S),
 
1788
%    S2 = translate_size_expr(Size, State, L2, Fail, Env, S1), 
 
1789
%    S3 = add_code([icode_label(L2)], S2),
 
1790
%    bitstr_patterns(NewBinSegs, Vars, State, Fail, Env, S3).
 
1791
 
 
1792
%bitstr_patterns([Seg|Rest], [T|Ts], State, Fail, Env, S) ->
 
1793
%    {NewEnv, S1} = bitstr_pattern(Seg, T, State, Fail, Env, S),
 
1794
%    bitstr_patterns(Rest, Ts, State, Fail, NewEnv, S1);
 
1795
 
 
1796
%bitstr_patterns([], [], _State, _Fail, Env, S) ->
 
1797
%    {Env, S}.
 
1798
 
 
1799
%bitstr_pattern(P, V, State, Fail, Env, S) ->
 
1800
%    T = cerl_binary_pattern_match:new_bitstr_val(P),
 
1801
%    Size = cerl_binary_pattern_match:new_bitstr_size(P),
 
1802
%    Offset = cerl_binary_pattern_match:new_bitstr_offset(P),
 
1803
%    {LiteralType,LiteralFlags} = cerl_binary_pattern_match:new_bitstr_type(P),
 
1804
%    Align = test_align(Offset),
 
1805
%    Flags=translate_flags(LiteralFlags, Align),
 
1806
%    Type = cerl:atom_val(LiteralType),
 
1807
%    OffsetVar = make_var(),
 
1808
%    OffsetConst = cerl_binary_pattern_match:size_const(Offset),
 
1809
%    {S1, SizeExpr} =
 
1810
%       case type_of_size(Size) of
 
1811
%           const ->
 
1812
%               {S, Size};
 
1813
%           all ->
 
1814
%               {S, Size};
 
1815
%           var ->
 
1816
%               SizeVar = make_var(),
 
1817
%               S0 = add_size_code(Size, SizeVar, Env, S),
 
1818
%               {S0, SizeVar}
 
1819
%       end,
 
1820
%    S2 = add_offset_code(Offset, OffsetVar, Env, S1),
 
1821
%    S3 = add_final_code(Type, V, SizeExpr, OffsetVar, OffsetConst, State, Flags, S2),
 
1822
%    pattern(T, V, Fail, Env, S3).
 
1823
 
 
1824
 
 
1825
%% ---------------------------------------------------------------------
 
1826
%% Boolean expressions
 
1827
 
1387
1828
%% This generates code for a boolean expression (such as "primop
1388
1829
%% 'and'(X, Y)") in a normal expression context, when an actual `true'
1389
 
%% or `false' value is to be computed.
 
1830
%% or `false' value is to be computed. We set up a default fail-label
 
1831
%% for generating a `badarg' error, unless we are in a guard.
1390
1832
 
 
1833
boolean_expr(E, [V], Ctxt=#ctxt{class = guard}, Env, S) ->
 
1834
    {Code, True, False} = make_bool_glue(V),
 
1835
    S1 = boolean(E, True, False, Ctxt, Env, S),
 
1836
    add_code(Code, S1);
1391
1837
boolean_expr(E, [V] = Ts, Ctxt, Env, S) ->
1392
 
    {Code, True, False} = make_bool_glue(V, true, false),
1393
 
    Ctxt1 = Ctxt#ctxt{final = false},
 
1838
    {Code, True, False} = make_bool_glue(V),
 
1839
    Fail = new_label(),
 
1840
    Cont = new_continuation_label(Ctxt),
 
1841
    Ctxt1 = Ctxt#ctxt{final = false, effect = false, fail = Fail},
1394
1842
    S1 = boolean(E, True, False, Ctxt1, Env, S),
1395
 
    maybe_return(Ts, Ctxt, add_code(Code, S1));
 
1843
    S2 = maybe_return(Ts, Ctxt, add_code(Code, S1)),
 
1844
    S3 = add_continuation_jump(Cont, Ctxt, S2),
 
1845
    S4 = add_code([icode_label(Fail)], S3),
 
1846
    S5 = add_error(icode_const(badarg), Ctxt, S4),  % can add dummy label
 
1847
    S6 = add_continuation_jump(Cont, Ctxt, S5),  % avoid empty basic block
 
1848
    add_continuation_label(Cont, Ctxt, S6);
1396
1849
boolean_expr(_, [], _Ctxt, _Env, _S) ->
1397
1850
    error_high_degree(),
1398
1851
    throw(error);
1400
1853
    error_low_degree(),
1401
1854
    throw(error).
1402
1855
 
1403
 
%% This generates jumping code for booleans, but does not generally use
1404
 
%% shortcuts for logical operators, unless the expression is "safe"
1405
 
%% (i.e., has no side effects and cannot fail), or we are in guard
1406
 
%% context; otherwise, we set a flag to be checked if necessary after
1407
 
%% both branches have been evaluated. Note that since subexpressions are
1408
 
%% checked repeatedly to see if they are safe, etc., this is really
1409
 
%% quadratic, but I don't expect booleans to be very deeply nested.
1410
 
 
1411
 
%% TODO: use a pre-pass instead to annotate expressions as safe.
1412
 
 
1413
 
boolean(E, True, False, Ctxt, Env, S) ->
1414
 
    case Ctxt#ctxt.class of
1415
 
        guard ->
1416
 
            pure_boolean(E, True, False, Ctxt, Env, S);
1417
 
        _ ->
1418
 
            case is_safe_expr(E) of
 
1856
%% This is for when we expect a boolean result in jumping code context,
 
1857
%% but are not sure what the expression will produce, or we know that
 
1858
%% the result is not a boolean and we just want error handling.
 
1859
 
 
1860
expect_boolean_value(E, True, False, Ctxt, Env, S) ->
 
1861
    V = make_var(),
 
1862
    S1 = expr(E, [V], Ctxt#ctxt{final = false}, Env, S),
 
1863
    case Ctxt#ctxt.fail of
 
1864
        [] ->
 
1865
            %% No fail-label set - this means we are *sure* that the
 
1866
            %% result can only be 'true' or 'false'.
 
1867
            add_code([make_type([V], ?TYPE_ATOM(true), True, False)],
 
1868
                     S1);
 
1869
        Fail ->
 
1870
            Next = new_label(),
 
1871
            add_code([make_type([V], ?TYPE_ATOM(true), True, Next),
 
1872
                      icode_label(Next),
 
1873
                      make_type([V], ?TYPE_ATOM(false), False, Fail)],
 
1874
                     S1)
 
1875
    end.
 
1876
 
 
1877
%% This generates code for a case-switch with exactly one 'true' branch
 
1878
%% and one 'false' branch, and no other branches (not even a catch-all).
 
1879
%% Note that E must be guaranteed to produce a boolean value for such a
 
1880
%% switch to have been generated.
 
1881
 
 
1882
bool_switch(E, TrueExpr, FalseExpr, F, Ctxt, Env, S) ->
 
1883
    Cont = new_continuation_label(Ctxt),
 
1884
    True = new_label(),
 
1885
    False = new_label(),
 
1886
    Ctxt1 = Ctxt#ctxt{final = false, effect = false},
 
1887
    S1 = boolean(E, True, False, Ctxt1, Env, S),
 
1888
    S2 = add_code([icode_label(True)], S1),
 
1889
    S3 = F(TrueExpr, Ctxt, Env, S2),
 
1890
    S4 = add_continuation_jump(Cont, Ctxt, S3),
 
1891
    S5 = add_code([icode_label(False)], S4),
 
1892
    S6 = F(FalseExpr, Ctxt, Env, S5),
 
1893
    add_continuation_label(Cont, Ctxt, S6).
 
1894
 
 
1895
%% This generates jumping code for booleans. If the fail-label is set,
 
1896
%% it tells where to go in case a value turns out not to be a boolean.
 
1897
 
 
1898
%% In strict boolean expressions, we set a flag to be checked if
 
1899
%% necessary after both branches have been evaluated. An alternative
 
1900
%% would be to duplicate the code for the second argument, for each
 
1901
%% value ('true' or 'false') of the first argument.
 
1902
 
 
1903
%% (Note that subexpressions are checked repeatedly to see if they are
 
1904
%% safe - this is quadratic, but I don't expect booleans to be very
 
1905
%% deeply nested.)
 
1906
 
 
1907
%% Note that 'and', 'or' and 'xor' are strict (like all primops)!
 
1908
 
 
1909
boolean(E0, True, False, Ctxt, Env, S) ->
 
1910
    E = cerl_lib:reduce_expr(E0),
 
1911
    case cerl:type(E) of
 
1912
        literal ->
 
1913
            case cerl:concrete(E) of
1419
1914
                true ->
1420
 
                    safe_boolean(E, True, False, Ctxt, Env, S);
 
1915
                    add_code([icode_goto(True)], S);
1421
1916
                false ->
1422
 
                    generic_boolean(E, True, False, Ctxt, Env, S)
1423
 
            end
1424
 
    end.
1425
 
 
1426
 
%% Note that 'and' and 'or' are strict! Unless we know more about their
1427
 
%% subexpressions, we must evaluate both branches.
1428
 
 
1429
 
generic_boolean(E0, True, False, Ctxt, Env, S) ->
1430
 
    E = reduce_expr(E0),
1431
 
    case cerl:type(E) of
 
1917
                    add_code([icode_goto(False)], S);
 
1918
                _ ->
 
1919
                    expect_boolean_value(E, True, False, Ctxt, Env, S)
 
1920
            end;
 
1921
        values ->
 
1922
            case cerl:values_es(E) of
 
1923
                [E1] ->
 
1924
                    boolean(E1, True, False, Ctxt, Env, S);
 
1925
                _ ->
 
1926
                    error_msg("degree mismatch - expected boolean: ~P",
 
1927
                              [E, 10]),
 
1928
                    throw(error)
 
1929
            end;
1432
1930
        primop ->
1433
1931
            Name = cerl:atom_val(cerl:primop_name(E)),
1434
1932
            As = cerl:primop_args(E),
1435
1933
            Arity = length(As),
1436
1934
            case {Name, Arity} of
1437
1935
                {?PRIMOP_NOT, 1} ->
 
1936
                    %% `not' simply switches true and false labels.
1438
1937
                    [A] = As,
1439
1938
                    boolean(A, False, True, Ctxt, Env, S);
1440
1939
                {?PRIMOP_AND, 2} ->
1441
 
                    [A, B] = As,
1442
 
                    V = make_var(),
1443
 
                    {Glue, True1, False1} =
1444
 
                        make_bool_glue(V, ?BOOL_TRUE, ?BOOL_FALSE),
1445
 
                    S1 = boolean(A, True1, False1, Ctxt, Env, S),
1446
 
                    S2 = add_code(Glue, S1),
1447
 
                    Test = new_label(),
1448
 
                    S3 = boolean(B, Test, False, Ctxt, Env, S2),
1449
 
                    add_code([icode_label(Test),
1450
 
                              make_type(V, ?BOOL_IS_FALSE,
1451
 
                                        False, True)],
1452
 
                             S3);
 
1940
                    strict_and(As, True, False, Ctxt, Env, S);
1453
1941
                {?PRIMOP_OR, 2} ->
1454
 
                    [A, B] = As,
1455
 
                    V = make_var(),
1456
 
                    {Glue, True1, False1} =
1457
 
                        make_bool_glue(V, ?BOOL_TRUE, ?BOOL_FALSE),
1458
 
                    S1 = boolean(A, True1, False1, Ctxt, Env, S),
1459
 
                    S2 = add_code(Glue, S1),
1460
 
                    Test = new_label(),
1461
 
                    S3 = boolean(B, True, Test, Ctxt, Env, S2),
1462
 
                    add_code([icode_label(Test),
1463
 
                              make_type(V, ?BOOL_IS_FALSE,
1464
 
                                        False, True)],
1465
 
                             S3);
 
1942
                    strict_or(As, True, False, Ctxt, Env, S);
 
1943
                {?PRIMOP_XOR, 2} ->
 
1944
                    %% `xor' always needs to evaluate both arguments
 
1945
                    strict_xor(As, True, False, Ctxt, Env, S);
1466
1946
                _ ->
1467
1947
                    case is_comp_op(Name, Arity) of
1468
1948
                        true ->
1474
1954
                                    type_test(Name, As, True, False,
1475
1955
                                              Ctxt, Env, S);
1476
1956
                                false ->
1477
 
                                    other_boolean(E, True, False, Ctxt,
1478
 
                                                  Env, S)
 
1957
                                    expect_boolean_value(E, True, False,
 
1958
                                                         Ctxt, Env, S)
1479
1959
                            end
1480
1960
                    end
1481
1961
            end;
1482
 
        literal ->
1483
 
            case cerl:concrete(E) of
1484
 
                true ->
1485
 
                    add_code([icode_goto(True)], S);
1486
 
                false ->
1487
 
                    add_code([icode_goto(False)], S);
1488
 
                X ->
1489
 
                    error_msg("not a boolean value: ~P.", [X, 5]),
1490
 
                    throw(error)
1491
 
            end;
1492
 
        values ->
1493
 
            case cerl:values_es(E) of
1494
 
                [E1] ->
1495
 
                    boolean(E1, True, False, Ctxt, Env, S);
1496
 
                _ ->
1497
 
                    error_msg("degree mismatch - expected boolean: ~P",
1498
 
                              [E, 10]),
1499
 
                    throw(error)
1500
 
            end;
 
1962
        'case' ->
 
1963
            %% Propagate boolean handling into clause bodies.
 
1964
            %% (Note that case switches assume fallthrough code in the
 
1965
            %% clause bodies, so we must add a dummy label as needed.)
 
1966
            F = fun (B, Ctxt, Env, S) ->
 
1967
                        S1 = boolean(B, True, False, Ctxt, Env, S),
 
1968
                        add_new_continuation_label(Ctxt, S1)
 
1969
                end,
 
1970
            S1 = expr_case_1(E, F, Ctxt, Env, S),
 
1971
            %% Add a final goto if necessary, to compensate for the
 
1972
            %% final continuation label of the case-expression. This
 
1973
            %% should be unreachable, so the value does not matter.
 
1974
            add_continuation_jump(False, Ctxt, S1);
1501
1975
        seq ->
1502
 
            %% Cf. 'expr_seq(...)'.
1503
 
            Ctxt1 = Ctxt#ctxt{effect = true, final = false},
1504
 
            S1 = expr(cerl:seq_arg(E), [], Ctxt1, Env, S),
1505
 
            boolean(cerl:seq_body(E), True, False, Ctxt, Env, S1);
 
1976
            %% Propagate boolean handling into body.
 
1977
            F = fun (B, Ctxt, Env, S) ->
 
1978
                        boolean(B, True, False, Ctxt, Env, S)
 
1979
                end,
 
1980
            expr_seq_1(E, F, Ctxt, Env, S);
1506
1981
        'let' ->
1507
 
            %% Note that we have called 'reduce_expr' above.
1508
 
            Vars = cerl:let_vars(E),
1509
 
            Vs = make_vars(length(Vars)),
1510
 
            S1 = expr(cerl:let_arg(E), Vs,
1511
 
                      Ctxt#ctxt{effect = false, final = false}, Env, S),
1512
 
            Env1 = bind_vars(Vars, Vs, Env),
1513
 
            B = cerl:let_body(E),
1514
 
            boolean(B, True, False, Ctxt, Env1, S1);
 
1982
            %% Propagate boolean handling into body. Note that we have
 
1983
            %% called 'cerl_lib:reduce_expr/1' above.
 
1984
            F = fun (B, Ctxt, Env, S) ->
 
1985
                        boolean(B, True, False, Ctxt, Env, S)
 
1986
                end,
 
1987
            expr_let_1(E, F, Ctxt, Env, S);
 
1988
        'try' ->
 
1989
            case Ctxt#ctxt.class of
 
1990
                guard ->
 
1991
                    %% This *must* be a "protected" guard expression on
 
1992
                    %% the form "try E of X -> X catch <...> -> 'false'"
 
1993
                    %% (we could of course test if the handler body is
 
1994
                    %% the atom 'false', etc.).
 
1995
                    Ctxt1 = Ctxt#ctxt{fail = False},
 
1996
                    boolean(cerl:try_arg(E), True, False, Ctxt1, Env,
 
1997
                            S);
 
1998
                _ ->
 
1999
                    %% Propagate boolean handling into the handler and body
 
2000
                    %% (see propagation into case switches for comparison)
 
2001
                    F = fun (B, Ctxt, Env, S) ->
 
2002
                                boolean(B, True, False, Ctxt, Env, S)
 
2003
                        end,
 
2004
                    S1 = expr_try_1(E, F, Ctxt, Env, S),
 
2005
                    add_continuation_jump(False, Ctxt, S1)
 
2006
            end;
1515
2007
        _ ->
1516
2008
            %% This handles everything else, including cases that are
1517
2009
            %% known to not return a boolean.
1518
 
            other_boolean(E, True, False, Ctxt, Env, S)
1519
 
    end.
1520
 
 
1521
 
%% This is for when we expect a boolean result, but are not sure what
1522
 
%% the expression will produce, or we know that the result is not a
1523
 
%% boolean and we just want the error handling.
1524
 
 
1525
 
other_boolean(E, True, False, Ctxt, Env, S) ->
1526
 
    V = make_var(),
1527
 
    S1 = expr(E, [V], Ctxt#ctxt{final = false}, Env, S),
1528
 
    L1 = new_label(),
1529
 
    S2 = add_code([make_type(V, ?TYPE_ATOM(true), True, L1),
1530
 
                   icode_label(L1)],
1531
 
                  S1),
1532
 
    case Ctxt#ctxt.class of
1533
 
        guard ->
1534
 
            add_code([make_type(V, ?TYPE_ATOM(false), False,
1535
 
                                Ctxt#ctxt.fail)],
1536
 
                     S2);
1537
 
        _ ->
1538
 
            L2 = new_label(),
1539
 
            S3 = add_code([make_type(V, ?TYPE_ATOM(false), False, L2),
1540
 
                           icode_label(L2)], S2),
1541
 
            add_exit(icode_const(error), Ctxt, S3)
1542
 
    end.
1543
 
 
1544
 
%% This generates jumping code for boolean expressions where no
1545
 
%% subexpression can have side effects *and* no subexpression can fail.
1546
 
 
1547
 
safe_boolean(E0, True, False, Ctxt, Env, S) ->
1548
 
    E = reduce_expr(E0),
1549
 
    case cerl:type(E) of
1550
 
        primop ->
1551
 
            Name = cerl:atom_val(cerl:primop_name(E)),
1552
 
            As = cerl:primop_args(E),
1553
 
            Arity = length(As),
1554
 
            case {Name, Arity} of
1555
 
                {?PRIMOP_AND, 2} ->
1556
 
                    [A, B] = As,
1557
 
                    Next = new_label(),
1558
 
                    S1 = safe_boolean(A, Next, False, Ctxt, Env,
1559
 
                                      S),
1560
 
                    S2 = add_code([icode_label(Next)], S1),
1561
 
                    safe_boolean(B, True, False, Ctxt, Env, S2);
1562
 
                {?PRIMOP_OR, 2} ->
1563
 
                    [A, B] = As,
1564
 
                    Next = new_label(),
1565
 
                    S1 = safe_boolean(A, True, Next, Ctxt, Env,
1566
 
                                      S),
1567
 
                    S2 = add_code([icode_label(Next)], S1),
1568
 
                    safe_boolean(B, True, False, Ctxt, Env, S2);
1569
 
                _ ->
1570
 
                    generic_boolean(E, True, False, Ctxt, Env, S)
1571
 
            end;
1572
 
        seq ->
1573
 
            safe_boolean(cerl:seq_body(E), True, False, Ctxt, Env, S);
1574
 
        'try' ->
1575
 
            safe_boolean(cerl:try_arg(E), True, False, Ctxt, Env, S);
1576
 
        'catch' ->
1577
 
            safe_boolean(cerl:catch_body(E), True, False, Ctxt, Env, S);
1578
 
        _ ->
1579
 
            generic_boolean(E, True, False, Ctxt, Env, S)
1580
 
    end.
1581
 
 
1582
 
%% This generates jumping code for boolean expressions where no
1583
 
%% subexpression can have side effects (as e.g. in a clause guard),
1584
 
%% *but* subexpressions might fail.
1585
 
 
1586
 
pure_boolean(E, True, False, Ctxt, Env, S) ->
1587
 
    case is_safe_expr(E) of
1588
 
        true ->
1589
 
            safe_boolean(E, True, False, Ctxt, Env, S);
1590
 
        false ->
1591
 
            unsafe_pure_boolean(E, True, False, Ctxt, Env, S)
1592
 
    end.
1593
 
 
1594
 
unsafe_pure_boolean(E0, True, False, Ctxt, Env, S) ->
1595
 
    E = reduce_expr(E0),
1596
 
    case cerl:type(E) of
1597
 
        primop ->
1598
 
            Name = cerl:atom_val(cerl:primop_name(E)),
1599
 
            As = cerl:primop_args(E),
1600
 
            Arity = length(As),
1601
 
            case {Name, Arity} of
1602
 
                {?PRIMOP_AND, 2} ->
1603
 
                    %% Done as in the "safe" case:
1604
 
                    [A, B] = As,
1605
 
                    Next = new_label(),
1606
 
                    S1 = pure_boolean(A, Next, False, Ctxt, Env,
1607
 
                                      S),
1608
 
                    S2 = add_code([icode_label(Next)], S1),
1609
 
                    pure_boolean(B, True, False, Ctxt, Env, S2);
1610
 
                {?PRIMOP_OR, 2} ->
1611
 
                    %% This is done as in the generic case: since the
1612
 
                    %% second argument might crash, it must be evaluated
1613
 
                    %% even if the first yields `true'.
1614
 
                    [A, B] = As,
1615
 
                    V = make_var(),
1616
 
                    {Glue, True1, False1} =
1617
 
                        make_bool_glue(V, ?BOOL_TRUE, ?BOOL_FALSE),
1618
 
                    S1 = pure_boolean(A, True1, False1, Ctxt, Env,
1619
 
                                      S),
1620
 
                    S2 = add_code(Glue, S1),
1621
 
                    Test = new_label(),
1622
 
                    S3 = pure_boolean(B, True, Test, Ctxt, Env,
1623
 
                                      S2),
1624
 
                    add_code([icode_label(Test),
1625
 
                              make_type(V, ?BOOL_IS_FALSE,
1626
 
                                        False, True)],
1627
 
                             S3);
1628
 
                _ ->
1629
 
                    generic_boolean(E, True, False, Ctxt, Env, S)
1630
 
            end;
1631
 
        'try' ->
1632
 
            case Ctxt#ctxt.class of
1633
 
                guard ->
1634
 
                    %% This should be a "protected" guard expression on
1635
 
                    %% the form "try E of X -> X catch <T,R> -> 'false'"
1636
 
                    %% but we don't actually check for this.
1637
 
                    Ctxt1 = Ctxt#ctxt{fail = False, class = guard},
1638
 
                    boolean(cerl:try_arg(E), True, False, Ctxt1, Env, S);
1639
 
                _ ->
1640
 
                    generic_boolean(E, True, False, Ctxt, Env, S)
1641
 
            end;
1642
 
        _ ->
1643
 
            generic_boolean(E, True, False, Ctxt, Env, S)
1644
 
    end.
 
2010
            expect_boolean_value(E, True, False, Ctxt, Env, S)
 
2011
    end.
 
2012
 
 
2013
strict_and([A, B], True, False, Ctxt, Env, S) ->
 
2014
    V = make_var(),
 
2015
    {Glue, True1, False1} = make_bool_glue(V),
 
2016
    S1 = boolean(A, True1, False1, Ctxt, Env, S),
 
2017
    S2 = add_code(Glue, S1),
 
2018
    Test = new_label(),
 
2019
    S3 = boolean(B, Test, False, Ctxt, Env, S2),
 
2020
    add_code([icode_label(Test),
 
2021
              make_bool_test(V, True, False)],
 
2022
             S3).
 
2023
 
 
2024
strict_or([A, B], True, False, Ctxt, Env, S) ->
 
2025
    V = make_var(),
 
2026
    {Glue, True1, False1} = make_bool_glue(V),
 
2027
    S1 = boolean(A, True1, False1, Ctxt, Env, S),
 
2028
    S2 = add_code(Glue, S1),
 
2029
    Test = new_label(),
 
2030
    S3 = boolean(B, True, Test, Ctxt, Env, S2),
 
2031
    add_code([icode_label(Test),
 
2032
              make_bool_test(V, True, False)],
 
2033
             S3).
 
2034
 
 
2035
strict_xor([A, B], True, False, Ctxt, Env, S) ->
 
2036
    V = make_var(),
 
2037
    {Glue, True1, False1} = make_bool_glue(V),
 
2038
    S1 = boolean(A, True1, False1, Ctxt, Env, S),
 
2039
    S2 = add_code(Glue, S1),
 
2040
    Test1 = new_label(),
 
2041
    Test2 = new_label(),
 
2042
    S3 = boolean(B, Test1, Test2, Ctxt, Env, S2),
 
2043
    add_code([icode_label(Test1),
 
2044
              make_bool_test(V, False, True),
 
2045
              icode_label(Test2),
 
2046
              make_bool_test(V, True, False)],
 
2047
             S3).
1645
2048
 
1646
2049
%% Primitive comparison operations are inline expanded as conditional
1647
2050
%% branches when part of a boolean expression, rather than made into
1648
 
%% primop or guardop calls. Without type information, however, we cannot
1649
 
%% reduce comparisons `Expr == true' to simply `Expr' (and `Expr ==
1650
 
%% false' to `not Expr'), because we are not sure that Expr will yield a
1651
 
%% boolean - and if it does not, the result should be `false', not a
1652
 
%% crash!
 
2051
%% primop or guardop calls. Note that Without type information, we
 
2052
%% cannot reduce equality tests like `Expr == true' to simply `Expr'
 
2053
%% (and `Expr == false' to `not Expr'), because we are not sure that
 
2054
%% Expr will yield a boolean - if it does not, the result of the
 
2055
%% comparison should be `false'.
1653
2056
 
1654
2057
comparison(Name, As, True, False, Ctxt, Env, S) ->
1655
2058
    {Vs, S1} = expr_list(As, Ctxt, Env, S),
1665
2068
comp_test(?PRIMOP_LE) -> ?TEST_LE;
1666
2069
comp_test(?PRIMOP_GE) -> ?TEST_GE.
1667
2070
 
 
2071
type_test(?PRIMOP_IS_RECORD, As, True, False, Ctxt, Env, S)
 
2072
  when length(As) =:= 3 ->
 
2073
    is_record_test(As, True, False, Ctxt, Env, S);
1668
2074
type_test(Name, [A], True, False, Ctxt, Env, S) ->
1669
2075
    V = make_var(),
1670
 
    S1 = expr(A, [V], Ctxt, Env, S),
 
2076
    S1 = expr(A, [V], Ctxt#ctxt{final = false, effect = false}, Env, S),
1671
2077
    Test = type_test(Name),
1672
 
    add_code([make_type(V, Test, True, False)], S1).
 
2078
    add_code([make_type([V], Test, True, False)], S1).
 
2079
 
 
2080
%% It turned out to be easiest to generate Icode directly for this. 
 
2081
is_record_test([T, A, N] = As, True, False, Ctxt, Env, S) ->
 
2082
    case cerl:is_c_atom(A) andalso cerl:is_c_int(N)
 
2083
        andalso (cerl:concrete(N) > 0) of
 
2084
        true ->
 
2085
            V = make_var(),
 
2086
            Ctxt1 = Ctxt#ctxt{final = false, effect = false},
 
2087
            S1 = expr(T, [V], Ctxt1, Env, S),
 
2088
            Atom = cerl:concrete(A),
 
2089
            Size = cerl:concrete(N),
 
2090
            add_code([make_type([V], ?TYPE_IS_RECORD(Atom, Size), True, False)],
 
2091
                     S1);
 
2092
        false ->
 
2093
            error_primop_badargs(?PRIMOP_IS_RECORD, As),
 
2094
            throw(error)
 
2095
    end.
1673
2096
 
1674
2097
type_test(?PRIMOP_IS_ATOM) -> ?TYPE_IS_ATOM;
1675
2098
type_test(?PRIMOP_IS_BIGNUM) -> ?TYPE_IS_BIGNUM;
1694
2117
is_comp_op(?PRIMOP_GT, 2) -> true;
1695
2118
is_comp_op(?PRIMOP_LE, 2) -> true;
1696
2119
is_comp_op(?PRIMOP_GE, 2) -> true;
1697
 
is_comp_op(_, _) -> false.
 
2120
is_comp_op(Op, A) when is_atom(Op), is_integer(A) -> false.
1698
2121
 
1699
2122
is_bool_op(?PRIMOP_AND, 2) -> true;
1700
2123
is_bool_op(?PRIMOP_OR, 2) -> true;
 
2124
is_bool_op(?PRIMOP_XOR, 2) -> true;
1701
2125
is_bool_op(?PRIMOP_NOT, 1) -> true;
1702
 
is_bool_op(_, _) -> false.
 
2126
is_bool_op(Op, A) when is_atom(Op), is_integer(A) -> false.
1703
2127
 
1704
2128
is_type_test(?PRIMOP_IS_ATOM, 1) -> true;
1705
2129
is_type_test(?PRIMOP_IS_BIGNUM, 1) -> true;
1715
2139
is_type_test(?PRIMOP_IS_PORT, 1) -> true;
1716
2140
is_type_test(?PRIMOP_IS_REFERENCE, 1) -> true;
1717
2141
is_type_test(?PRIMOP_IS_TUPLE, 1) -> true;
1718
 
is_type_test(_, _) -> false.
1719
 
 
1720
 
bind_var(V, X, Env) ->
1721
 
    env__bind(cerl:var_name(V), #var{id = X}, Env).
 
2142
is_type_test(?PRIMOP_IS_RECORD, 3) -> true;
 
2143
is_type_test(Op, A) when is_atom(Op), is_integer(A) -> false.
 
2144
 
 
2145
 
 
2146
%% ---------------------------------------------------------------------
 
2147
%% Utility functions
 
2148
 
 
2149
bind_var(V, Name, Env) ->
 
2150
    env__bind(cerl:var_name(V), #var{name = Name}, Env).
1722
2151
 
1723
2152
bind_vars([V | Vs], [X | Xs], Env) ->
1724
2153
    bind_vars(Vs, Xs, bind_var(V, X, Env));
1725
2154
bind_vars([], [], Env) ->
1726
2155
    Env.
1727
2156
 
 
2157
bind_fun(V, L, Vs, Env) ->
 
2158
    env__bind(cerl:var_name(V), #'fun'{label = L, vars = Vs}, Env).
 
2159
 
1728
2160
add_code(Code, S) ->
1729
2161
    s__add_code(Code, S).
1730
2162
 
1735
2167
    if V1 =:= V2 ->
1736
2168
            S;
1737
2169
       true ->
1738
 
            glue(Vs1, Vs2, add_code([icode_mov(V2, V1)], S))
 
2170
            glue(Vs1, Vs2, add_code([icode_move(V2, V1)], S))
1739
2171
    end;
1740
2172
glue([], [], S) ->
1741
2173
    S;
1747
2179
    throw(error).
1748
2180
 
1749
2181
make_moves([V1 | Vs1], [V2 | Vs2]) ->
1750
 
    [icode_mov(V1, V2) | make_moves(Vs1, Vs2)];
 
2182
    [icode_move(V1, V2) | make_moves(Vs1, Vs2)];
1751
2183
make_moves([], []) ->
1752
2184
    [].
1753
2185
 
1767
2199
 
1768
2200
new_continuation_label(Ctxt) ->
1769
2201
    case Ctxt#ctxt.final of
 
2202
        false ->
 
2203
            new_label();
1770
2204
        true ->
1771
 
            undefined;
1772
 
        false ->
1773
 
            new_label()
 
2205
            undefined
1774
2206
    end.
1775
2207
 
1776
2208
add_continuation_label(Label, Ctxt, S) ->
1777
2209
    case Ctxt#ctxt.final of
 
2210
        false ->
 
2211
            add_code([icode_label(Label)], S);
1778
2212
        true ->
1779
 
            S;
1780
 
        false ->
1781
 
            add_code([icode_label(Label)], S)
 
2213
            S
1782
2214
    end.
1783
2215
 
1784
2216
add_continuation_jump(Label, Ctxt, S) ->
1785
2217
    case Ctxt#ctxt.final of
1786
 
        true ->
1787
 
            S;
1788
 
        false ->
1789
 
            add_code([icode_goto(Label)], S)
1790
 
    end.
 
2218
        false ->
 
2219
            add_code([icode_goto(Label)], S);
 
2220
        true ->
 
2221
            S
 
2222
    end.
 
2223
 
 
2224
%% This is used to insert a new dummy label (if necessary) when
 
2225
%% a block is ended suddenly; cf. add_fail.
 
2226
add_new_continuation_label(Ctxt, S) ->
 
2227
    add_continuation_label(new_continuation_label(Ctxt), Ctxt, S).
 
2228
 
 
2229
add_local_call({Name, _Arity} = V, Vs, Ts, Ctxt, S, DstType) ->
 
2230
    Module = s__get_module(S),
 
2231
    case Ctxt#ctxt.final of
 
2232
        false ->
 
2233
            add_code([icode_call_local(Ts, Module, Name, Vs, DstType)],S);
 
2234
        true ->
 
2235
            Self = s__get_function(S),
 
2236
            if V =:= Self ->
 
2237
                    %% Self-recursive tail call:
 
2238
                    {Label, Vs1} = s__get_local_entry(S),
 
2239
                    add_code(make_moves(Vs1, Vs) ++ [icode_goto(Label)],
 
2240
                             S);
 
2241
               true ->
 
2242
                    add_code([icode_enter_local(Module, Name, Vs)], S)
 
2243
            end
 
2244
    end.
 
2245
 
 
2246
%% Note that this has the same "problem" as the fail instruction (see
 
2247
%% the 'add_fail' function), namely, that it unexpectedly ends a basic
 
2248
%% block. The solution is the same - add a dummy label if necessary.
 
2249
 
 
2250
add_letrec_call(Label, Vs1, Vs, Ctxt, S) ->
 
2251
    S1 = add_code(make_moves(Vs1, Vs) ++ [icode_goto(Label)], S),
 
2252
    add_new_continuation_label(Ctxt, S1).
1791
2253
 
1792
2254
add_exit(V, Ctxt, S) ->
1793
2255
    add_fail([V], exit, Ctxt, S).
1796
2258
    add_fail([V], throw, Ctxt, S).
1797
2259
 
1798
2260
add_error(V, Ctxt, S) ->
1799
 
    add_fail([V], fault, Ctxt, S).
 
2261
    add_fail([V], error, Ctxt, S).
1800
2262
 
1801
2263
add_error(V, F, Ctxt, S) ->
1802
 
    add_fail([V, F], fault2, Ctxt, S).
 
2264
    add_fail([V, F], error, Ctxt, S).
 
2265
 
 
2266
add_rethrow(E, V, Ctxt, S) ->
 
2267
    add_fail([E, V], rethrow, Ctxt, S).
1803
2268
 
1804
2269
%% Failing is special, because it can "suddenly" end the basic block,
1805
2270
%% even though the context was expecting the code to fall through, for
1806
 
%% instance when you have a call to 'exit(X)' that is not in a last call
 
2271
%% instance when you have a call to 'exit(X)' that is not in a tail call
1807
2272
%% context. In those cases a dummy label must therefore be added after
1808
2273
%% the fail instruction, to start a new (but unreachable) basic block.
1809
2274
 
1810
 
add_fail(Vs, Type, Ctxt, S0) ->
1811
 
    S1 = add_code([icode_fail(Vs, Type)], S0),
1812
 
    add_continuation_label(new_continuation_label(Ctxt), Ctxt, S1).
 
2275
add_fail(Vs, Class, Ctxt, S0) ->
 
2276
    S1 = add_code([icode_fail(Vs, Class)], S0),
 
2277
    add_new_continuation_label(Ctxt, S1).
1813
2278
 
1814
 
%% We must add a fail-label if we are in a guard context.
1815
 
%% Note that primops do not in general have an 'enter' form.
 
2279
%% We must add continuation- and fail-labels if we are in a guard context.
1816
2280
 
1817
2281
make_op(Name, Ts, As, Ctxt) ->
1818
 
    case Ctxt#ctxt.class of
1819
 
        guard ->
1820
 
            Next = new_label(),
1821
 
            [icode_guardop(Ts, Name, As, Next, Ctxt#ctxt.fail),
1822
 
             icode_label(Next)];
1823
 
        _ ->
1824
 
            [icode_call_primop(Ts, Name, As)]
 
2282
    case Ctxt#ctxt.final of
 
2283
        false ->
 
2284
            case Ctxt#ctxt.class of
 
2285
                guard ->
 
2286
                    Next = new_label(),
 
2287
                    [icode_guardop(Ts, Name, As, Next, Ctxt#ctxt.fail),
 
2288
                     icode_label(Next)];
 
2289
                _ ->
 
2290
                    [icode_call_primop(Ts, Name, As)]
 
2291
            end;        
 
2292
        true ->
 
2293
            [icode_enter_primop(Name, As)]
 
2294
    end.
 
2295
 
 
2296
make_call(M, F, Ts, As, Ctxt) ->
 
2297
    case Ctxt#ctxt.final of
 
2298
        false ->
 
2299
            case Ctxt#ctxt.class of
 
2300
                guard ->
 
2301
                    Next = new_label(),
 
2302
                    [icode_call_remote(Ts, M, F, As, Next,
 
2303
                                       Ctxt#ctxt.fail, true),
 
2304
                     icode_label(Next)];
 
2305
                _ ->
 
2306
                    [icode_call_remote(Ts, M, F, As)]
 
2307
            end;
 
2308
        true ->
 
2309
            %% A final call can't be in a guard anyway
 
2310
            [icode_enter_remote(M, F, As)]
1825
2311
    end.
1826
2312
 
1827
2313
%% Recognize useless tests that always go to the same label. This often
1834
2320
 
1835
2321
make_type(_, _, Label, Label) ->
1836
2322
    icode_goto(Label);
1837
 
make_type(V, Test, True, False) ->
1838
 
    icode_type(V, Test, True, False).
 
2323
make_type(Vs, Test, True, False) ->
 
2324
    icode_type(Vs, Test, True, False).
1839
2325
 
1840
2326
%% Creating glue code with true/false target labels for assigning a
1841
 
%% corresponding 'true'/'false' value to a specific variable.
 
2327
%% corresponding 'true'/'false' value to a specific variable. Used as
 
2328
%% glue between boolean jumping code and boolean values.
 
2329
 
 
2330
make_bool_glue(V) ->
 
2331
    make_bool_glue(V, true, false).
1842
2332
 
1843
2333
make_bool_glue(V, T, F) ->
1844
2334
    False = new_label(),
1845
2335
    True = new_label(),
1846
2336
    Next = new_label(),
1847
2337
    Code = [icode_label(False), 
1848
 
            icode_mov(V, icode_const(F)),
 
2338
            icode_move(V, icode_const(F)),
1849
2339
            icode_goto(Next),
1850
2340
            icode_label(True),
1851
 
            icode_mov(V, icode_const(T)),
 
2341
            icode_move(V, icode_const(T)),
1852
2342
            icode_label(Next)],
1853
2343
    {Code, True, False}.
1854
2344
 
1855
 
add_local_call({Name, _Arity} = Id, Vs, Ts, Ctxt, S, DstType) ->
1856
 
    Module = s__get_module(S),
1857
 
    case Ctxt#ctxt.final of
1858
 
        false ->
1859
 
            add_code([icode_call_local(Ts, Module, Name, Vs, DstType)],S);
1860
 
        true ->
1861
 
            Self = s__get_function(S),
1862
 
            if Id =:= Self ->
1863
 
                    %% Tail-recursive call to same function.
1864
 
                    {Label, Vs1} = s__get_local_entry(S),
1865
 
                    add_code(make_moves(Vs1, Vs) ++
1866
 
                             [icode_goto(Label)],
1867
 
                             S);
1868
 
               true ->
1869
 
                    add_code([icode_enter_local(Module, Name, Vs)], S)
1870
 
            end
1871
 
    end.
1872
 
 
1873
 
%% In order to expose otherwise hidden cases of final expressions
1874
 
%% (enabling last call optimization), and other cases when we want to
1875
 
%% examine the type of some subexpression, we first try to remove all
1876
 
%% trivial let-bindings (`let X = Y in X', `let X = Y in Y', `let X = Y
1877
 
%% in let ... in ...', `let X = let ... in ... in ...', etc.), We do
1878
 
%% not, however, try to recognize any other similar cases, even for
1879
 
%% simple `case'-expressions like `case E of X -> X end'. Nor do we try
1880
 
%% to optimize uses of multiple-value aggregates of other degree than 1.
1881
 
 
1882
 
reduce_expr(E) ->
1883
 
    case cerl:type(E) of
1884
 
        values ->
1885
 
            case cerl:values_es(E) of
1886
 
                [E1] ->
1887
 
                    reduce_expr(E1);
1888
 
                _ ->
1889
 
                    E
1890
 
            end;
1891
 
        'let' ->
1892
 
            %% We give up if the body does not reduce to a single
1893
 
            %% variable. This is not a generic copy propagation.
1894
 
            B = reduce_expr(cerl:let_body(E)),
1895
 
            Vs = cerl:let_vars(E),
1896
 
            case cerl:is_c_var(B) of
1897
 
                true when length(Vs) == 1 ->
1898
 
                    %% We have `let <V1> = <E> in <V2>':
1899
 
                    A = cerl:let_arg(E),
1900
 
                    [V] = Vs,
1901
 
                    case cerl:var_name(V) =:= cerl:var_name(B) of
1902
 
                        true ->
1903
 
                            %% `let X = <E> in X' equals `<E>'
1904
 
                            reduce_expr(A);
1905
 
                        false ->
1906
 
                            %% `let X = <E> in Y' is equivalent to `Y'
1907
 
                            %% if and only if `<E>' is "safe"; otherwise
1908
 
                            %% it is eqivalent to `do <E> Y'.
1909
 
                            case is_safe_expr(A) of
1910
 
                                true ->
1911
 
                                    B;
1912
 
                                false ->
1913
 
                                    cerl:update_c_seq(E, A, B)
1914
 
                            end
1915
 
                    end;
1916
 
                _ ->
1917
 
                    cerl:update_c_let(E, Vs, cerl:let_arg(E), B)
1918
 
            end;
1919
 
        _ ->
1920
 
            E
1921
 
    end.
1922
 
 
1923
 
%% Return `true' if `Node' represents a "safe" Core Erlang expression,
1924
 
%% otherwise `false'. An expression is safe if it always completes
1925
 
%% normally and does not modify the state (although the value it yields
1926
 
%% might depend on the state). Expressions of type `apply', `call',
1927
 
%% `case' and `receive' are always considered unsafe by this function.
1928
 
%% For `try' (and `catch'), it would really suffice to check if the
1929
 
%% guarded expression is a pure (albeit possibly unsafe) function to
1930
 
%% deduce whether it is safe, but then we'd have to write a separate
1931
 
%% function for that, so we don't bother to.
 
2345
make_bool_test(V, True, False) ->
 
2346
    make_type([V], ?TYPE_ATOM(true), True, False).
 
2347
 
 
2348
%% Checking if an expression is safe
1932
2349
 
1933
2350
is_safe_expr(E) ->
1934
 
    case cerl:type(E) of
1935
 
        var ->
1936
 
            true;
1937
 
        literal ->
1938
 
            true;
1939
 
        'fun' ->
1940
 
            true;
1941
 
        values ->
1942
 
            is_safe_expr_list(cerl:values_es(E));
1943
 
        tuple ->
1944
 
            is_safe_expr_list(cerl:tuple_es(E));
1945
 
        cons ->
1946
 
            case is_safe_expr(cerl:cons_hd(E)) of
1947
 
                true ->
1948
 
                    is_safe_expr(cerl:cons_tl(E));
1949
 
                false ->
1950
 
                    false
1951
 
            end;
1952
 
        'let' ->
1953
 
            case is_safe_expr(cerl:let_arg(E)) of
1954
 
                true ->
1955
 
                    is_safe_expr(cerl:let_body(E));
1956
 
                false ->
1957
 
                    false
1958
 
            end;
1959
 
        seq ->
1960
 
            case is_safe_expr(cerl:seq_arg(E)) of
1961
 
                true ->
1962
 
                    is_safe_expr(cerl:seq_body(E));
1963
 
                false ->
1964
 
                    false
1965
 
            end;
1966
 
        'try' ->
1967
 
            %% If the guarded expression is safe, the try-handler
1968
 
            %% will never be evaluated, so we need not check it.
1969
 
            case is_safe_expr(cerl:try_arg(E)) of
1970
 
                true ->
1971
 
                    is_safe_expr(cerl:try_body(E));
1972
 
                false ->
1973
 
                    false
1974
 
            end;
1975
 
        'catch' ->
1976
 
            is_safe_expr(cerl:catch_body(E));
1977
 
        letrec ->
1978
 
            is_safe_expr(cerl:letrec_body(E));
1979
 
        primop ->
1980
 
            Name = cerl:atom_val(cerl:primop_name(E)),
1981
 
            As = cerl:primop_args(E),
1982
 
            case is_safe_op(Name, length(As)) of
1983
 
                true ->
1984
 
                    is_safe_expr_list(As);
1985
 
                false ->
1986
 
                    false
1987
 
            end;
1988
 
        _ ->
1989
 
            false
1990
 
    end.
 
2351
    cerl_lib:is_safe_expr(E, fun function_check/2).
1991
2352
 
1992
 
is_safe_expr_list([E | Es]) ->
1993
 
    case is_safe_expr(E) of
1994
 
        true ->
1995
 
            is_safe_expr_list(Es);
1996
 
        false ->
1997
 
            false
1998
 
    end;
1999
 
is_safe_expr_list([]) ->
2000
 
    true.
 
2353
function_check(safe, {Name, Arity}) ->
 
2354
    is_safe_op(Name, Arity);
 
2355
function_check(safe, {Module, Name, Arity}) ->
 
2356
    erl_bifs:is_safe(Module, Name, Arity);
 
2357
function_check(pure, {Name, Arity}) ->
 
2358
    is_pure_op(Name, Arity);
 
2359
function_check(pure, {Module, Name, Arity}) ->
 
2360
    erl_bifs:is_pure(Module, Name, Arity);
 
2361
function_check(_, _) ->
 
2362
    false.
2001
2363
 
2002
2364
%% There are very few really safe operations (sigh!). If we have type
2003
2365
%% information, several operations could be rewritten into specialized
2004
 
%% safe versions, such as '+'/2 -> add_integer/2 (which is safe).
 
2366
%% safe versions, such as '+'/2 -> add_integer/2.
2005
2367
 
2006
 
is_safe_op(?PRIMOP_IDENTITY, 1) -> true;
2007
2368
is_safe_op(N, A) ->
2008
2369
    case is_comp_op(N, A) of
2009
2370
        true -> true;
2011
2372
            is_type_test(N, A)
2012
2373
    end.
2013
2374
 
2014
 
translate_flags([A|Rest],Align) ->
2015
 
    case cerl:concrete(A) of
 
2375
is_pure_op(?PRIMOP_ELEMENT, 2) -> true;
 
2376
is_pure_op(?PRIMOP_MAKE_FUN, 6) -> true;
 
2377
is_pure_op(?PRIMOP_FUN_ELEMENT, 2) -> true;
 
2378
is_pure_op(?PRIMOP_ADD, 2) -> true;
 
2379
is_pure_op(?PRIMOP_SUB, 2) -> true;
 
2380
is_pure_op(?PRIMOP_NEG, 1) -> true;
 
2381
is_pure_op(?PRIMOP_MUL, 2) -> true;
 
2382
is_pure_op(?PRIMOP_DIV, 2) -> true;
 
2383
is_pure_op(?PRIMOP_INTDIV, 2) -> true;
 
2384
is_pure_op(?PRIMOP_REM, 2) -> true;
 
2385
is_pure_op(?PRIMOP_BAND, 2) -> true;
 
2386
is_pure_op(?PRIMOP_BOR, 2) -> true;
 
2387
is_pure_op(?PRIMOP_BXOR, 2) -> true;
 
2388
is_pure_op(?PRIMOP_BNOT, 1) -> true;
 
2389
is_pure_op(?PRIMOP_BSL, 2) -> true;
 
2390
is_pure_op(?PRIMOP_BSR, 2) -> true;
 
2391
is_pure_op(?PRIMOP_EXIT, 1) -> true;
 
2392
is_pure_op(?PRIMOP_THROW, 1) -> true;
 
2393
is_pure_op(?PRIMOP_ERROR, 1) -> true;
 
2394
is_pure_op(?PRIMOP_ERROR, 2) -> true;
 
2395
is_pure_op(?PRIMOP_RETHROW, 2) -> true;
 
2396
is_pure_op(N, A) ->
 
2397
    case is_bool_op(N, A) of
 
2398
        true -> true;
 
2399
        false ->
 
2400
            case is_comp_op(N, A) of
 
2401
                true -> true;
 
2402
                false -> is_type_test(N, A)
 
2403
            end
 
2404
    end.
 
2405
 
 
2406
translate_flags(Flags, Align) ->
 
2407
    translate_flags1(cerl:concrete(Flags), Align).
 
2408
 
 
2409
translate_flags1([A|Rest],Align) ->
 
2410
    case A of
2016
2411
        signed ->
2017
 
            4 + translate_flags(Rest, Align);
 
2412
            4 + translate_flags1(Rest, Align);
2018
2413
        little ->
2019
 
            2 + translate_flags(Rest, Align);
 
2414
            2 + translate_flags1(Rest, Align);
 
2415
        native ->
 
2416
            case hipe_rtl_arch:endianess() of
 
2417
                little ->
 
2418
                    2 + translate_flags1(Rest, Align);
 
2419
                big ->
 
2420
                    translate_flags1(Rest, Align)
 
2421
            end;
2020
2422
        _ ->
2021
 
            translate_flags(Rest, Align)
 
2423
            translate_flags1(Rest, Align)
2022
2424
    end;
2023
 
translate_flags([], Align) ->
 
2425
translate_flags1([], Align) ->
2024
2426
    case Align of
2025
2427
        0 ->
2026
2428
            1;
2093
2495
env__lookup(Key, Env) ->
2094
2496
    rec_env:lookup(Key, Env).
2095
2497
 
 
2498
env__get(Key, Env) ->
 
2499
    rec_env:get(Key, Env).
 
2500
 
2096
2501
%% env__new_integer_keys(N, Env) ->
2097
2502
%%     rec_env:new_keys(N, Env).
2098
2503
 
2100
2505
%% ---------------------------------------------------------------------
2101
2506
%% State (abstract datatype)
2102
2507
 
2103
 
-record(state, {module, function, local, code = []}).
 
2508
-record(state, {module, function, local, labels=gb_trees:empty(), code = [], pmatch=true}).
2104
2509
 
2105
2510
s__new(Module) ->
2106
2511
    #state{module = Module}.
2129
2534
    lists:reverse(S#state.code).
2130
2535
 
2131
2536
s__add_code(Code, S) ->
2132
 
    S#state{code = push_list(Code, S#state.code)}.
 
2537
    S#state{code = lists:reverse(Code, S#state.code)}.
 
2538
 
 
2539
s__get_label(Ref, S) ->
 
2540
    Labels = S#state.labels,
 
2541
    case gb_trees:lookup(Ref, Labels) of
 
2542
        none ->
 
2543
            Label = new_label(),
 
2544
            S1 = S#state{labels=gb_trees:enter(Ref, Label, Labels)},
 
2545
            {Label, S1};
 
2546
        {value, Label} -> 
 
2547
            {Label,S}
 
2548
    end.
 
2549
 
 
2550
s__set_pmatch(V, S) ->
 
2551
    S#state{pmatch = V}.
 
2552
 
 
2553
s__get_pmatch(S) ->
 
2554
    S#state.pmatch.
 
2555
 
 
2556
%% ---------------------------------------------------------------------
 
2557
%% Match label State
 
2558
 
 
2559
-record(mstate,{labels=gb_trees:empty()}).
 
2560
 
 
2561
get_correct_label(Alias, MState=#mstate{labels=Labels}) ->
 
2562
    case gb_trees:lookup(Alias, Labels) of
 
2563
    none ->
 
2564
      LabelName=new_label(),
 
2565
      {LabelName, MState#mstate{labels=gb_trees:insert(Alias, LabelName, Labels)}};
 
2566
    {value, LabelName} ->
 
2567
      {LabelName, MState}
 
2568
  end.
2133
2569
 
2134
2570
 
2135
2571
%% ---------------------------------------------------------------------
2136
2572
%% General utilities
2137
2573
 
2138
 
push_list([A | As], Bs) ->
2139
 
    push_list(As, [A | Bs]);
2140
 
push_list([], Bs) ->
2141
 
    Bs.
2142
 
 
2143
2574
reset_var_counter() ->
2144
2575
    hipe_gensym:set_var(0).
2145
2576
 
2166
2597
make_vars(0) ->
2167
2598
    [].
2168
2599
 
2169
 
get_type(List)->
2170
 
    Type = get_type0(List, []),
2171
 
    %%io:format("cerl_to_icode:get_type/1: Types: ~w\n", [Type]),
2172
 
    Type.
2173
 
 
2174
 
get_type0([H|T], Acc)->
2175
 
    %%io:format("cerl_to_icode:get_type/1: Annotations: ~w\n", [cerl:get_ann(H)]),
 
2600
make_reg() ->
 
2601
    icode_reg(new_var()).
 
2602
 
 
2603
get_arg_types(Fun) ->
 
2604
    Type = get_typesig(Fun),
 
2605
    case erl_types:t_is_fun(Type) of
 
2606
        true -> erl_types:t_fun_args(Type);
 
2607
        false -> 
 
2608
            TL = get_type(cerl:fun_vars(Fun)),
 
2609
            case lists:all(fun(X) -> X =:= placeholder end, TL) of
 
2610
                true -> none;
 
2611
                false -> lists:map(fun(placeholder) -> erl_types:t_any();
 
2612
                                      (X) -> X
 
2613
                                   end, TL)
 
2614
            end
 
2615
    end.
 
2616
 
 
2617
get_typesig(E) ->
 
2618
    case lists:keysearch(typesig, 1, cerl:get_ann(E)) of
 
2619
        {value, {typesig, Type}} -> Type;
 
2620
        false -> erl_types:t_any()
 
2621
    end.
 
2622
 
 
2623
get_type(List) when is_list(List) ->
 
2624
    get_type_list(List, []);
 
2625
get_type(E) ->
 
2626
    case lists:keysearch(type, 1, cerl:get_ann(E)) of
 
2627
        {value, {type, Type}} -> Type;
 
2628
        false -> erl_types:t_any()
 
2629
    end.
 
2630
 
 
2631
get_type_list([H|T], Acc)->
2176
2632
    case lists:keysearch(type, 1, cerl:get_ann(H)) of
2177
 
        {value, {type, Type}} -> get_type0(T, [Type|Acc]);
2178
 
        false -> get_type0(T, [erl_types:t_any()|Acc])
 
2633
        {value, {type, Type}} -> get_type_list(T, [Type|Acc]);
 
2634
        false -> get_type_list(T, [placeholder|Acc])
2179
2635
    end;
2180
 
get_type0([], Acc) ->
2181
 
    lists:reverse(Acc);
2182
 
get_type0(E, Acc) ->
2183
 
    get_type0([E], Acc).
 
2636
get_type_list([], Acc) ->
 
2637
    lists:reverse(Acc).
2184
2638
 
2185
2639
 
2186
2640
%% ---------------------------------------------------------------------
2187
2641
%% ICode interface
2188
2642
 
2189
 
icode_icode(F, Vs, Lambda, Leaf, C, V, L, T) ->
2190
 
    hipe_icode:mk_typed_icode(F, Vs, Lambda, Leaf, C, V, L, T).
 
2643
icode_icode(M, {F, A}, Vs, Closure, C, V, L, T) ->
 
2644
    MFA = {M, F, A},
 
2645
    if T =:= none ->
 
2646
            hipe_icode:mk_icode(MFA, Vs, Closure, false, C, V, L);
 
2647
       true ->
 
2648
            hipe_icode:mk_typed_icode(MFA, Vs, Closure, false, C, V, L, T)
 
2649
    end.
 
2650
 
 
2651
icode_icode_name(Icode) ->
 
2652
    hipe_icode:icode_fun(Icode).
 
2653
 
 
2654
icode_comment(S) -> hipe_icode:mk_comment(S).
2191
2655
 
2192
2656
icode_var(V) -> hipe_icode:mk_var(V).
2193
2657
 
 
2658
icode_reg(V) -> hipe_icode:mk_reg(V).
 
2659
 
2194
2660
icode_label(L) -> hipe_icode:mk_label(L).
2195
2661
 
2196
 
icode_mov(V, D) -> hipe_icode:mk_mov(V, D).
 
2662
icode_move(V, D) -> hipe_icode:mk_move(V, D).
2197
2663
 
2198
2664
icode_const(X) -> hipe_icode:mk_const(X).
2199
2665
 
2205
2671
icode_call_remote(Ts, M, N, Vs) ->
2206
2672
    hipe_icode:mk_call(Ts, M, N, Vs, remote).
2207
2673
 
 
2674
icode_call_remote(Ts, M, N, Vs, Cont, Fail, Guard) ->
 
2675
    hipe_icode:mk_call(Ts, M, N, Vs, remote, Cont, Fail, Guard).
 
2676
 
2208
2677
icode_enter_local(M, N, Vs) ->
2209
2678
    hipe_icode:mk_enter(M, N, Vs, local).
2210
2679
 
2217
2686
icode_enter_fun(Vs) ->
2218
2687
    icode_enter_primop(enter_fun, Vs).
2219
2688
 
2220
 
icode_pushcatch(L,Cont) -> hipe_icode:mk_pushcatch(L,Cont).
2221
 
 
2222
 
icode_remove_catch(L) -> hipe_icode:mk_remove_catch(L).
2223
 
 
2224
 
icode_restore_catch(T, L) -> hipe_icode:mk_restore_catch(T, L).
 
2689
icode_begin_try(L,Cont) -> hipe_icode:mk_begin_try(L,Cont).
 
2690
 
 
2691
icode_end_try() -> hipe_icode:mk_end_try().
 
2692
 
 
2693
icode_begin_handler(Ts) -> hipe_icode:mk_begin_handler(Ts).
2225
2694
 
2226
2695
icode_goto(L) -> hipe_icode:mk_goto(L).
2227
2696
 
2228
2697
icode_return(Ts) -> hipe_icode:mk_return(Ts).
2229
2698
 
2230
 
icode_fail(V, T) -> hipe_icode:mk_fail(V, T).
 
2699
icode_fail(Vs, C) -> hipe_icode:mk_fail(Vs, C).
2231
2700
 
2232
2701
icode_guardop(Ts, Name, As, Succ, Fail) ->
2233
2702
    hipe_icode:mk_guardop(Ts, Name, As, Succ, Fail).
2234
2703
 
2235
2704
icode_call_primop(Ts, Name, As) -> hipe_icode:mk_primop(Ts, Name, As).
2236
2705
 
2237
 
%% enter_primop can only be used for the 'enter_fun' op.
 
2706
icode_call_primop(Ts, Name, As, Succ, Fail) ->
 
2707
    hipe_icode:mk_primop(Ts, Name, As, Succ, Fail).
 
2708
 
2238
2709
icode_enter_primop(Name, As) -> hipe_icode:mk_enter_primop(Name, As).
2239
2710
 
2240
2711
icode_if(Test, As, True, False) ->
2247
2718
    hipe_icode:mk_switch_val(Arg, Fail, Length, Cases).
2248
2719
 
2249
2720
icode_switch_tuple_arity(Arg, Fail, Length, Cases) ->
2250
 
    hipe_icode:mk_switch_tuple_arity(Arg, Fail, Length, Cases).
 
2721
    SortedCases = lists:keysort(1, Cases), %% immitate BEAM compiler - Kostis
 
2722
    hipe_icode:mk_switch_tuple_arity(Arg, Fail, Length, SortedCases).
2251
2723
 
2252
2724
 
2253
2725
%% ---------------------------------------------------------------------
2254
2726
%% Error reporting
2255
2727
 
2256
 
warning_not_in_receive(Name) ->
2257
 
    warning_msg("primitive operation `~w' has no effect "
2258
 
                "outside receive-clauses.", [Name]).
 
2728
error_not_in_receive(Name) ->
 
2729
    error_msg("primitive operation `~w' missing receive-context.",
 
2730
              [Name]).
2259
2731
 
2260
2732
low_degree() ->
2261
2733
    "degree of expression less than expected.".
2270
2742
    error_msg("degree of expression greater than expected.").
2271
2743
 
2272
2744
error_degree_mismatch(N, E) ->
2273
 
    error_msg("expression does not have expected degree "
2274
 
              "(~w): ~P.",
 
2745
    error_msg("expression does not have expected degree (~w): ~P.",
2275
2746
              [N, E, 10]).
2276
2747
 
2277
2748
error_nonlocal_application(Op) ->
2305
2776
 
2306
2777
info_msg(S, Vs) ->
2307
2778
    error_logger:info_msg(lists:concat([?MODULE, ": ", S, "\n"]), Vs).
 
2779
 
 
2780
 
 
2781
%% --------------------------------------------------------------------------
 
2782
%% Binary stuff
 
2783
 
 
2784
binary_match(BMatch, F, Vs, Next, Fail, Ctxt, Env, S) ->
 
2785
    MState=#mstate{},
 
2786
    Tree = cerl_binary_pattern_match:binary_match_clause_tree(BMatch),
 
2787
    MTag = cerl_binary_pattern_match:binary_match_max_tag(BMatch),
 
2788
    VarList = make_vars(MTag),
 
2789
    Orig = make_var(), 
 
2790
    OrigOffset = make_var(),
 
2791
    Size = make_var(),
 
2792
    L1 = new_label(),
 
2793
    S1 = add_code([icode_guardop([Orig], {hipe_bsi_primop, bs_get_orig}, Vs, L1, Fail),
 
2794
                   icode_label(L1),
 
2795
                   icode_call_primop([OrigOffset], {hipe_bsi_primop, bs_get_orig_offset}, Vs),
 
2796
                   icode_call_primop([Size], {hipe_bsi_primop, bs_get_size}, Vs)], S),
 
2797
    {S2, _MState0} = clause_tree(Tree, VarList, F, {Orig, OrigOffset, Size}, Next, Fail, MState, Ctxt, Env, S1),
 
2798
    S2.
 
2799
 
 
2800
clause_tree([], _VarList, _F, _State, _Next, Fail, MState, _Ctxt, _Env, S) ->
 
2801
    {add_code([icode_goto(Fail)], S), MState};
 
2802
clause_tree(CTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2803
    Instr = cerl_binary_pattern_match:clause_tree_instr(CTree),
 
2804
    NextTree = cerl_binary_pattern_match:clause_tree_success(CTree),
 
2805
    FailTree = cerl_binary_pattern_match:clause_tree_fail(CTree),
 
2806
    case cerl_binary_pattern_match:instr_type(Instr) of
 
2807
        read_seg ->
 
2808
            read_seg(Instr, NextTree,  VarList, F, State, Next, Fail, MState, Ctxt, Env, S);
 
2809
        bin_guard ->
 
2810
            bin_guard(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S);
 
2811
        size ->
 
2812
            do_size(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S);
 
2813
        match ->
 
2814
            do_match(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState,Ctxt, Env, S);
 
2815
        label ->
 
2816
            do_label(Instr, NextTree, VarList, F, State, Next, Fail, MState,Ctxt, Env, S);
 
2817
        goto ->
 
2818
            do_goto(Instr, MState, S);
 
2819
        match_group ->
 
2820
            do_match_group(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState,Ctxt, Env, S)
 
2821
    end.
 
2822
 
 
2823
read_seg(Instr, NextTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2824
    S1 = translate_binseg(Instr, VarList, State, Env, S),
 
2825
    clause_tree(NextTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S1).
 
2826
 
 
2827
bin_guard(Instr, Body, FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2828
    LabelPrimop = cerl_binary_pattern_match:bin_guard_label(Instr),
 
2829
    Ref = translate_label_primop(LabelPrimop),
 
2830
    {FL,S1} = s__get_label(Ref, S), 
 
2831
    {Env1, S2} = translate_bin_guard(Instr, VarList, Env, S1),
 
2832
    S3 = F(Body, Ctxt, Env1, S2),
 
2833
    S4 = add_continuation_jump(Next, Ctxt, S3),
 
2834
    S5 = add_code([icode_label(FL)], S4),
 
2835
    clause_tree(FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S5).
 
2836
 
 
2837
do_size(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2838
    SL = new_label(),
 
2839
    FL = new_label(),
 
2840
    S1 = translate_size_expr(Instr, State, VarList, SL, FL, Env, S),
 
2841
    S2 = add_code([icode_label(SL)], S1),
 
2842
    {S3, MState1} = clause_tree(NextTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S2),
 
2843
    S4 = add_code([icode_label(FL)], S3),
 
2844
    clause_tree(FailTree, VarList, F, State, Next, Fail, MState1, Ctxt, Env, S4).
 
2845
 
 
2846
do_match(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2847
    SL = new_label(),
 
2848
    FL = new_label(),
 
2849
    S1 = translate_match(Instr, VarList, SL, FL, S),
 
2850
    S2 = add_code([icode_label(SL)], S1),
 
2851
    {S3, MState1} = clause_tree(NextTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S2),
 
2852
    S4 = add_code([icode_label(FL)], S3),
 
2853
    clause_tree(FailTree, VarList, F, State, Next, Fail, MState1, Ctxt, Env, S4).
 
2854
 
 
2855
do_match_group(Instr, NextTree, FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2856
    ValList = cerl_binary_pattern_match:match_group_vals(Instr),
 
2857
    Tag = cerl_binary_pattern_match:match_group_tag(Instr),
 
2858
    FL = new_label(),
 
2859
    FullCases = [{Val,{translate_value(Val),new_label()}} || Val<-ValList, is_ok_val(Val)],
 
2860
    Length = length(FullCases),
 
2861
    Cases = [Case || {_, Case} <- FullCases],
 
2862
    ResVar = get_resvar(Tag, VarList),
 
2863
    S1 = add_code([icode_switch_val(ResVar,FL,Length,Cases)], S), 
 
2864
    do_cases(FullCases, NextTree, FailTree, FL, VarList, F, State, Next, Fail, MState, Ctxt, Env, S1).
 
2865
 
 
2866
do_cases([{Value,{_, Label}}|Rest], NextTree, FailTree, FL, VarList, F, State, 
 
2867
         Next, Fail, MState, Ctxt, Env, S) -> 
 
2868
    {value, ClauseTree} = gb_trees:lookup(Value, NextTree),
 
2869
    S1 = add_code([icode_label(Label)], S),
 
2870
    {S2, MState1} = clause_tree(ClauseTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S1),
 
2871
    do_cases(Rest, NextTree, FailTree, FL, VarList, F, State, Next, Fail, MState1, Ctxt, Env, S2); 
 
2872
do_cases([], _NextTree, FailTree, FL, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2873
    S1 = add_code([icode_label(FL)], S),
 
2874
    clause_tree(FailTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S1).
 
2875
 
 
2876
do_label(Instr, NextTree, VarList, F, State, Next, Fail, MState, Ctxt, Env, S) ->
 
2877
    LabelAlias = cerl_binary_pattern_match:label_name(Instr),
 
2878
    {Label, MState1} = get_correct_label(LabelAlias, MState),
 
2879
    S1 = add_code([icode_goto(Label),icode_label(Label)], S),
 
2880
    clause_tree(NextTree, VarList, F, State, Next, Fail, MState1, Ctxt, Env, S1).
 
2881
 
 
2882
do_goto(Instr, MState, S) ->    
 
2883
    LabelAlias = cerl_binary_pattern_match:goto_label(Instr),
 
2884
    {Label, MState1} = get_correct_label(LabelAlias, MState),
 
2885
    S1 = add_code([icode_goto(Label)], S),
 
2886
    {S1, MState1}.
 
2887
 
 
2888
translate_binseg(Instr, VarList, State, Env, S) ->
 
2889
    Size = cerl_binary_pattern_match:read_seg_size(Instr),
 
2890
    Offset = cerl_binary_pattern_match:read_seg_offset(Instr),
 
2891
    {LiteralType,LiteralFlags} = cerl_binary_pattern_match:read_seg_type(Instr),
 
2892
    V = cerl_binary_pattern_match:read_seg_tag(Instr),
 
2893
    ResVar = get_resvar(V, VarList),
 
2894
    Align = test_align(Offset),
 
2895
    Flags = translate_flags(LiteralFlags, Align),
 
2896
    Type = cerl:atom_val(LiteralType),
 
2897
    OffsetVar = make_var(),
 
2898
    OffsetConst = cerl_binary_pattern_match:size_const(Offset),
 
2899
    {S1, SizeExpr} =
 
2900
        case type_of_size(Size) of
 
2901
            const ->
 
2902
                {S, Size};
 
2903
            all ->
 
2904
                {S, Size};
 
2905
            var ->
 
2906
                SizeVar = make_var(),
 
2907
                S0 = add_size_code(Size, SizeVar, VarList, Env, S),
 
2908
                {S0, SizeVar}
 
2909
        end,
 
2910
    S2 = add_offset_code(Offset, OffsetVar, VarList, Env, S1),
 
2911
    add_final_code(Type, ResVar, SizeExpr, OffsetVar, OffsetConst, State, Flags, S2).
 
2912
 
 
2913
translate_value(Val) ->
 
2914
    icode_const(cerl:concrete(Val)).
 
2915
 
 
2916
is_ok_val(Val) ->
 
2917
    case cerl:concrete(Val) of
 
2918
        X when is_number(X) -> % is_integer(X) or is_number(X)
 
2919
            true;
 
2920
        _ ->
 
2921
            false
 
2922
    end.
 
2923
 
 
2924
translate_match(Instr, VarList, SL, FL, S) ->
 
2925
    Val = cerl_binary_pattern_match:match_val(Instr),
 
2926
    V = cerl_binary_pattern_match:match_tag(Instr),
 
2927
    ResVar = get_resvar(V, VarList),
 
2928
    case cerl:concrete(Val) of
 
2929
        X when is_integer(X) ->
 
2930
            add_code([make_type([ResVar], ?TYPE_INTEGER(X), SL, FL)], S);
 
2931
        X when is_float(X) ->
 
2932
            V1 = make_var(),
 
2933
            L = new_label(),
 
2934
            %% First doing an "is_float" test here might allow later
 
2935
            %% stages to use a specialized equality test.
 
2936
            add_code([make_type([ResVar], ?TYPE_IS_FLOAT, L, FL),
 
2937
                      icode_label(L),
 
2938
                      icode_move(V1, icode_const(X)),
 
2939
                      make_if(?TEST_EQ, [ResVar, V1], SL, FL)],
 
2940
                     S);
 
2941
        _X ->
 
2942
            %% If the constant is not a float nor an integer
 
2943
            %% The match can not succeed
 
2944
            add_code([icode_goto(FL)], S)
 
2945
    end.
 
2946
 
 
2947
translate_size_expr(Instr, {_,_,BinSize}, VarList, SL, FL, Env, S) ->
 
2948
    SizeVar = make_var(),
 
2949
    All = cerl_binary_pattern_match:size_all(Instr),
 
2950
    S1 = add_size_exp_code(Instr, SizeVar, VarList, FL, Env, S),
 
2951
    S2 = test_eight_div(SizeVar, FL, S1),
 
2952
    test_size(SizeVar, BinSize, All, SL, FL, S2).
 
2953
 
 
2954
add_final_code(integer, ResVar, SizeExpr, OffsetVar, OffsetConst,
 
2955
               {Orig, OrigOffset, _}, Flags, S) ->
 
2956
    Offset = cerl:int_val(OffsetConst),
 
2957
    case cerl:is_c_int(SizeExpr) of
 
2958
        true ->
 
2959
            Size = cerl:int_val(SizeExpr),
 
2960
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_integer, Size, Offset, Flags}}, 
 
2961
                                        [OffsetVar, Orig, OrigOffset])], S);
 
2962
        false ->
 
2963
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_integer, Offset, Flags}}, 
 
2964
                                        [SizeExpr, OffsetVar, Orig, OrigOffset])], S)
 
2965
    end;
 
2966
 
 
2967
add_final_code(float, ResVar, SizeExpr, OffsetVar, OffsetConst,
 
2968
               {Orig, OrigOffset, _}, Flags, S) ->
 
2969
    Offset = cerl:int_val(OffsetConst),
 
2970
    case cerl:is_c_int(SizeExpr) of
 
2971
        true ->
 
2972
            Size = cerl:int_val(SizeExpr),
 
2973
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_float, Size, Offset, Flags}}, 
 
2974
                                        [OffsetVar, Orig, OrigOffset])], S);
 
2975
        false ->
 
2976
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_float, Offset, Flags}}, 
 
2977
                                        [SizeExpr, OffsetVar, Orig, OrigOffset])], S)
 
2978
    end;
 
2979
 
 
2980
add_final_code(binary, ResVar, SizeExpr, OffsetVar, OffsetConst,
 
2981
               {Orig, OrigOffset, BinSize}, Flags, S) ->
 
2982
    Offset = cerl:int_val(OffsetConst),
 
2983
    case type_of_size(SizeExpr) of
 
2984
        const ->
 
2985
            Size = cerl:int_val(SizeExpr),
 
2986
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_binary, Size, Offset, Flags}}, 
 
2987
                                        [OffsetVar, Orig, OrigOffset])], S);
 
2988
        all ->
 
2989
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_binary_all, Offset, Flags}}, 
 
2990
                                        [OffsetVar, Orig, OrigOffset, BinSize])], S);
 
2991
        var ->
 
2992
            add_code([icode_call_primop([ResVar], {hipe_bsi_primop, {bs_get_binary, Offset, Flags}}, 
 
2993
                                        [SizeExpr, OffsetVar, Orig, OrigOffset])], S)
 
2994
    end.
 
2995
 
 
2996
 
 
2997
type_of_size(Size) ->
 
2998
    case cerl:is_c_int(Size) of
 
2999
        true ->
 
3000
            const;
 
3001
        false ->
 
3002
            {SizeExpr, _Unit} = Size,
 
3003
            case cerl:is_c_atom(SizeExpr) of
 
3004
                true ->
 
3005
                    all;
 
3006
                false ->
 
3007
                    var
 
3008
            end
 
3009
    end.
 
3010
 
 
3011
add_size_code({{tag,Tag}, Unit}, SizeVar, VarList, _Env, S) ->
 
3012
    UnitVal = cerl:int_val(Unit),
 
3013
    NewSize = get_resvar(Tag, VarList),
 
3014
    add_code([icode_call_primop([SizeVar],
 
3015
                                {hipe_bsi_primop, {bs_make_size, UnitVal}}, 
 
3016
                                [NewSize])], S);
 
3017
add_size_code({Size, Unit}, SizeVar, _VarList, Env, S) ->
 
3018
    NewSize = make_var(),
 
3019
    UnitVal = cerl:int_val(Unit),
 
3020
    S1 = expr(Size, [NewSize], #ctxt{final=false}, Env, S), 
 
3021
    add_code([icode_call_primop([SizeVar],
 
3022
                                {hipe_bsi_primop, {bs_make_size, UnitVal}}, 
 
3023
                                [NewSize])], S1).
 
3024
add_offset_code([{{tag,Tag}, Unit}|Rest], OffsetVar, VarList, Env, S) ->
 
3025
    Temp = make_var(),
 
3026
    NewSize = get_resvar(Tag, VarList),
 
3027
    UnitVal = cerl:int_val(Unit), 
 
3028
    Code = [icode_call_primop([Temp],
 
3029
                              {hipe_bsi_primop, {bs_make_size, UnitVal}}, 
 
3030
                              [NewSize]),
 
3031
            icode_call_primop([OffsetVar], '+', [OffsetVar, Temp])],
 
3032
    add_offset_code(Rest, OffsetVar, VarList, Env, add_code(Code, S));
 
3033
add_offset_code([{Size, Unit}|Rest], OffsetVar, VarList, Env, S) ->
 
3034
    Temp = make_var(),
 
3035
    NewSize = make_var(),
 
3036
    UnitVal = cerl:int_val(Unit),
 
3037
    S1 = expr(Size, [NewSize], #ctxt{final=false}, Env, S), 
 
3038
    Code = [icode_call_primop([Temp],
 
3039
                              {hipe_bsi_primop, {bs_make_size, UnitVal}}, 
 
3040
                              [NewSize]),
 
3041
            icode_call_primop([OffsetVar], {hipe_bsi_primop, bs_add},
 
3042
                              [OffsetVar, Temp])],
 
3043
    add_offset_code(Rest, OffsetVar, VarList, Env, add_code(Code, S1));
 
3044
add_offset_code([], _OffsetVar, _VarList, _Env, S) ->
 
3045
    S;
 
3046
add_offset_code(Size, OffsetVar, VarList, Env, S) ->
 
3047
    Vars = cerl_binary_pattern_match:size_vars(Size),
 
3048
    DefVars = cerl_binary_pattern_match:size_def_vars(Size),
 
3049
    Code = [icode_move(OffsetVar, icode_const(0))],
 
3050
    add_offset_code(DefVars++Vars, OffsetVar, VarList, Env, add_code(Code, S)).
 
3051
 
 
3052
add_size_exp_code(Size, SizeVar, VarList, FL, Env, S) ->
 
3053
    Vars = cerl_binary_pattern_match:size_vars(Size),
 
3054
    DefVars = cerl_binary_pattern_match:size_def_vars(Size),
 
3055
    Const = cerl_binary_pattern_match:size_const(Size),
 
3056
    Code = [icode_move(SizeVar, icode_const(0))],
 
3057
    add_size_exp_code(DefVars++Vars, Const, SizeVar, VarList, FL, Env, add_code(Code, S)).
 
3058
 
 
3059
add_size_exp_code([{{tag, Tag}, Unit}|Rest], Const, SizeVar, VarList, FL, Env, S) ->
 
3060
    Temp = make_var(),
 
3061
    NewSize = get_resvar(Tag, VarList),
 
3062
    TL = new_label(),
 
3063
    UnitVal = cerl:int_val(Unit),
 
3064
    Code = [icode_guardop([Temp], {hipe_bsi_primop, {bs_make_size, UnitVal}}, 
 
3065
                          [NewSize],TL,FL),
 
3066
            icode_label(TL),
 
3067
            icode_call_primop([SizeVar], '+',[SizeVar, Temp])],
 
3068
    add_size_exp_code(Rest, Const, SizeVar, VarList, FL, Env, add_code(Code, S));
 
3069
add_size_exp_code([{Size, Unit}|Rest], Const, SizeVar, VarList, FL, Env, S) ->
 
3070
    Temp = make_var(),
 
3071
    TL = new_label(),
 
3072
    NewSize = make_var(),
 
3073
    UnitVal = cerl:int_val(Unit),
 
3074
    S1 = expr(Size, [NewSize], #ctxt{final=false}, Env, S),
 
3075
    Code = [icode_guardop([Temp], {hipe_bsi_primop, {bs_make_size, UnitVal}}, 
 
3076
                          [NewSize],TL,FL),
 
3077
            icode_label(TL),
 
3078
            icode_call_primop([SizeVar], {hipe_bsi_primop, bs_add},
 
3079
                              [SizeVar, Temp])],
 
3080
    add_size_exp_code(Rest, Const, SizeVar, VarList, FL, Env, add_code(Code, S1));
 
3081
add_size_exp_code([], Const, SizeVar, _VarList, _FL, _Env, S) ->
 
3082
    CC = icode_const(cerl:int_val(Const)),
 
3083
    Temp = make_var(),
 
3084
    Code = [icode_move(Temp, CC),
 
3085
            icode_call_primop([SizeVar], {hipe_bsi_primop, bs_add},
 
3086
                              [SizeVar, Temp])],
 
3087
    add_code(Code, S).
 
3088
 
 
3089
test_eight_div(SizeVar, FL, S) ->
 
3090
    TL = new_label(),
 
3091
    add_code([icode_guardop([], {hipe_bsi_primop, bs_div_test},
 
3092
                            [SizeVar], TL, FL),
 
3093
              icode_label(TL)], S).
 
3094
 
 
3095
test_size(SizeVar, BinSize, All, SL, FL, S) ->
 
3096
    case cerl:atom_val(All) of
 
3097
        all ->
 
3098
            add_code([icode_guardop([], {hipe_bsi_primop, bs_size_test_all},
 
3099
                                    [SizeVar, BinSize], SL, FL)], S);
 
3100
        _ ->
 
3101
            add_code([icode_guardop([], {hipe_bsi_primop, bs_size_test},
 
3102
                                    [SizeVar, BinSize], SL, FL)], S)
 
3103
    end.
 
3104
 
 
3105
test_align([{_Size, Unit}|Rest]) ->
 
3106
    case cerl:int_val(Unit) band 7 of
 
3107
        0 ->
 
3108
            test_align(Rest);
 
3109
        _ ->
 
3110
            1
 
3111
    end;
 
3112
test_align([]) ->
 
3113
    0;
 
3114
test_align(Size) -> 
 
3115
    Vars = cerl_binary_pattern_match:size_vars(Size),
 
3116
    test_align(Vars).
 
3117
 
 
3118
get_resvar(N, VarList) ->
 
3119
    lists:nth(N+1, VarList).
 
3120
 
 
3121
translate_bin_guard(BinGuard, VarList, Env, S) ->
 
3122
    Matches = cerl_binary_pattern_match:bin_guard_matches(BinGuard),
 
3123
    Env1 = bind_matches(Matches, VarList, Env),
 
3124
    {Env1,S}.
 
3125
 
 
3126
bind_matches([Match|Rest], VarList, Env) ->      
 
3127
    Tag = cerl_binary_pattern_match:match_tag(Match),
 
3128
    Val = cerl_binary_pattern_match:match_val(Match),
 
3129
    T = get_resvar(Tag, VarList),
 
3130
    bind_matches(Rest, VarList, bind_var(Val, T, Env));
 
3131
bind_matches([], _VarList, Env) ->
 
3132
    Env. 
 
3133
 
 
3134
translate_label_primop(LabelPrimop) ->
 
3135
    ?PRIMOP_SET_LABEL = cerl:atom_val(cerl:primop_name(LabelPrimop)),
 
3136
    [Ref] = cerl:primop_args(LabelPrimop),
 
3137
    Ref.