1
1
%% -*- erlang-indent-level: 2 -*-
2
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
3
%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved
4
%% Time-stamp: <2003-04-02 18:06:28 richardc>
5
4
%% ====================================================================
5
%% Filename : hipe_rtl_primops.erl
10
8
%% History : * 2001-03-15 Erik Johansson (happi@csd.uu.se):
14
%% $Date: 2003/05/07 17:44:23 $
16
%% ====================================================================
19
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
21
14
-module(hipe_rtl_primops).
22
-export([gen_primop/3,gen_enter_fun/2]).
23
-export([gen_mk_tuple/3]).
26
%%------------------------------------------------------------------------
16
-export([gen_primop/4, gen_enter_primop/4, gen_call_builtin/6,
17
gen_enter_builtin/2]).
19
%% --------------------------------------------------------------------
28
21
-include("../main/hipe.hrl").
29
-include("hipe_icode2rtl.hrl").
22
-include("hipe_rtl.hrl").
30
23
-include("hipe_literals.hrl").
32
%%------------------------------------------------------------------------
35
%% ____________________________________________________________________
25
%% --------------------------------------------------------------------
26
%% Handling of known MFA builtins that are inline expanded
28
gen_call_builtin(Fun, Dst, Args, IsGuard, Cont, Fail) ->
31
gen_apply(Dst, Args, Cont, Fail);
34
gen_element(Dst, Args, IsGuard, Cont, Fail);
39
{hipe_bifs,in_native,0} ->
42
[] -> %% The result is not used.
43
hipe_rtl:mk_new_var();
46
[hipe_rtl:mk_load_atom(Dst1, true), hipe_rtl:mk_goto(Cont)];
48
_ -> [] % not a builtin
51
%% (Recall that enters cannot occur within a catch-region in the same
52
%% function, so we don't need to consider fail-continuations here.)
53
%% TODO: should we inline expand more functions here? Cf. above.
54
gen_enter_builtin(Fun, Args) ->
57
gen_enter_apply(Args);
60
%% {erlang,element,2} ->
61
%% gen_enter_element(Args, IsGuard);
67
{hipe_bifs,in_native,0} ->
68
Dst = hipe_rtl:mk_new_var(),
69
[hipe_rtl:mk_load_atom(Dst, true), hipe_rtl:mk_return([Dst])];
71
_ -> [] % not a builtin
74
%% --------------------------------------------------------------------
75
%% Generate code to jump to in case the inlined function fails.
77
gen_fail_code(Fail, Type) ->
78
gen_fail_code(Fail, Type, false).
80
gen_fail_code(Fail, Type, IsGuard) ->
82
true when Fail =/= [] ->
83
{Fail, []}; % go directly to target
85
NewLabel = hipe_rtl:mk_new_label(),
86
NewLabelName = hipe_rtl:label_name(NewLabel),
87
{NewLabelName, [NewLabel | fail_code(Fail, Type)]}
90
fail_code(Fail, Type) when is_atom(Type) ->
91
Var = hipe_rtl:mk_new_var(),
92
[hipe_rtl:mk_load_atom(Var, Type),
93
hipe_rtl_exceptions:gen_fail(error, [Var], Fail)];
94
fail_code(Fail, {Type, Value}) when is_atom(Type) ->
95
Var = hipe_rtl:mk_new_var(),
96
[hipe_rtl:mk_load_atom(Var, Type),
97
hipe_rtl:mk_gctest(3), % room for a 2-tuple
98
gen_mk_tuple(Var,[Var,Value]),
99
hipe_rtl_exceptions:gen_fail(error, [Var], Fail)].
101
fp_fail_code(TmpFailLbl, FailLbl) ->
103
hipe_rtl_arch:handle_fp_exception() ++
104
[fail_code(FailLbl, badarith)]].
106
%% --------------------------------------------------------------------
38
%% Generate code for primops. This is mostly a dispatch function
40
gen_primop({Op, Dst, Args, Cont, Fail, Annot},
42
{Options, ExitInfo}) ->
110
%% Generates RTL code for primops. This is mostly a dispatch function.
111
%% Tail calls to primops (enter_fun, apply, etc.) are not handled here!
114
gen_primop({Op,Dst,Args,Cont,Fail}, IsGuard, ConstTab, Options) ->
43
115
GotoCont = hipe_rtl:mk_goto(Cont),
46
%% ------------------------------------------------
49
120
{hipe_bs_primop, BsOP} ->
51
FailLabel = hipe_rtl:mk_new_label(),
52
case get(hipe_inline_bs) of
121
{FailLabelName, FailCode} =
122
gen_fail_code(Fail, badarg, IsGuard),
123
case proplists:get_bool(inline_bs, Options) of
55
126
hipe_rtl_inline_bs_ops:gen_rtl(BsOP, Args, Dst, Cont,
56
hipe_rtl:label_name(FailLabel),
127
FailLabelName, ConstTab);
60
130
hipe_rtl_bs_ops:gen_rtl(BsOP, Args, Dst, Cont,
61
hipe_rtl:label_name(FailLabel),
131
FailLabelName, ConstTab)
69
hipe_rtl_exceptions:gen_exit_atom(badarg, ExitInfo);
71
hipe_rtl_exceptions:gen_fail_code(Fail,hipe_rtl:mk_new_var(),
74
{[Code1,FailLabel,FailCode], VarMap, NewTab};
133
{[Code1,FailCode], NewTab};
134
{hipe_bs_primop2, BsOP} ->
135
{FailLabelName, FailCode} =
136
gen_fail_code(Fail, badarg, IsGuard),
138
hipe_rtl_binary:gen_rtl(BsOP, Dst, Args, Cont, FailLabelName),
139
{[Code1,FailCode], ConstTab};
141
{hipe_bsi_primop, BsOP} ->
142
{FailLabelName, FailCode} =
143
gen_fail_code(Fail, badarg, IsGuard),
144
Code1 = hipe_rtl_cerl_bs_ops:gen_rtl(BsOP, Args, Dst, Cont,
146
{[Code1,FailCode], ConstTab};
81
gen_add_sub_2(Dst, Args, Cont, Fail, Annot, Op, add, ExitInfo);
156
%gen_extra_unsafe_add_2(Dst, Args, Cont);
157
gen_add_sub_2(Dst, Args, Cont, Fail, Op, add);
83
gen_add_sub_2(Dst, Args, Cont, Fail, Annot, Op, sub, ExitInfo);
159
gen_add_sub_2(Dst, Args, Cont, Fail, Op, sub);
161
%% BIF call: am_Times -> nbif_mul_2 -> erts_mixed_times
162
[hipe_rtl:mk_call(Dst, '*', Args, Cont, Fail, not_remote)];
164
%% BIF call: am_Div -> nbif_div_2 -> erts_mixed_div
165
[hipe_rtl:mk_call(Dst, '/', Args, Cont, Fail, not_remote)];
167
%gen_extra_unsafe_add_2(Dst, Args, Cont);
168
gen_unsafe_add_sub_2(Dst, Args, Cont, Fail, '+', add);
169
'extra_unsafe_add' ->
170
gen_extra_unsafe_add_2(Dst, Args, Cont);
172
gen_unsafe_add_sub_2(Dst, Args, Cont, Fail, '-', sub);
173
'extra_unsafe_sub' ->
174
gen_extra_unsafe_sub_2(Dst, Args, Cont);
176
% gen_unsafe_mul_2(Dst, Args, Cont, Fail, '*');
178
%% BIF call: am_div -> nbif_intdiv_2 -> intdiv_2
179
[hipe_rtl:mk_call(Dst, 'div', Args, Cont, Fail, not_remote)];
181
%% BIF call: am_rem -> nbif_rem_2 -> rem_2
182
[hipe_rtl:mk_call(Dst, 'rem', Args, Cont, Fail, not_remote)];
87
[] -> %% The result is not used.
88
[hipe_rtl:mk_new_var()];
91
gen_bitop_2(Dst1, Args, Cont, Fail, Annot, Op, 'and', ExitInfo);
184
gen_bitop_2(Dst, Args, Cont, Fail, Op, 'and');
95
[] -> %% The result is not used.
96
[hipe_rtl:mk_new_var()];
99
gen_bitop_2(Dst1, Args, Cont, Fail, Annot, Op, 'or', ExitInfo);
186
gen_bitop_2(Dst, Args, Cont, Fail, Op, 'or');
103
[] -> %% The result is not used.
104
[hipe_rtl:mk_new_var()];
107
gen_bitop_2(Dst1, Args, Cont, Fail, Annot, Op, 'xor', ExitInfo);
188
gen_bitop_2(Dst, Args, Cont, Fail, Op, 'xor');
111
[] -> %% The result is not used.
112
[hipe_rtl:mk_new_var()];
115
gen_bnot_2(Dst1, Args, Cont, Fail, Annot, Op, ExitInfo);
118
%% These are just calls to the bifs...
120
% gen_call_bif(Dst, Args, Cont, Fail, Op, badarith, ExitInfo);
122
% gen_call_bif(Dst, Args, Cont, Fail, Op, badarith, ExitInfo);
124
% gen_call_bif(Dst, Args, Cont, Fail, Op, badarith, ExitInfo);
126
% gen_call_bif(Dst, Args, Cont, Fail, Op, badarith, ExitInfo);
128
% gen_call_bif(Dst, Args, Cont, Fail, Op, badarith, ExitInfo);
130
% gen_call_bif(Dst, Args, Cont, Fail, Op, badarith, ExitInfo);
190
gen_bnot_2(Dst, Args, Cont, Fail, Op);
192
%% BIF call: am_bsr -> nbif_bsr_2 -> bsr_2
193
gen_bsr_2(Dst, Args, Cont, Fail, Op);
194
%[hipe_rtl:mk_call(Dst, 'bsr', Args, Cont, Fail, not_remote)];
196
%% BIF call: am_bsl -> nbif_bsl_2 -> bsl_2
197
[hipe_rtl:mk_call(Dst, 'bsl', Args, Cont, Fail, not_remote)];
199
gen_unsafe_bitop_2(Dst, Args, Cont, 'and');
201
gen_unsafe_bitop_2(Dst, Args, Cont, 'or');
203
gen_unsafe_bitop_2(Dst, Args, Cont, 'xor');
205
gen_unsafe_bnot_2(Dst, Args, Cont);
207
gen_unsafe_bsr_2(Dst, Args, Cont);
209
gen_unsafe_bsl_2(Dst, Args, Cont);
135
213
[] -> %% The result is not used.
138
[gen_cons(Dst1, Args, Options),GotoCont]
216
[gen_cons(Dst1, Args), GotoCont]
142
220
[] -> %% The result is not used.
145
[gen_unsafe_hd(Dst1, Args),GotoCont]
223
[gen_unsafe_hd(Dst1, Args), GotoCont]
204
262
[TupleInfo, IndexInfo] = TypeInfo,
205
263
[Index, Tuple] = Args,
206
[gen_element_2(Dst1, Fail, Index, Tuple,
207
Cont, Annot, ExitInfo, TupleInfo, IndexInfo)];
208
% element -> %% Obsolete.
209
% [Dst1, _Flag] = Dst,
210
% [Index, Tuple] = Args,
211
% [gen_element_2(Dst1, Fail, Index, Tuple,
212
% Cont, Annot, ExitInfo)];
264
[gen_element_1(Dst1, Index, Tuple, IsGuard, Cont, Fail,
265
TupleInfo, IndexInfo)];
269
gen_apply_N(Dst, Arity, Args, Cont, Fail);
216
273
[hipe_rtl:mk_gctest(Need),GotoCont];
218
275
%% Process handling.
221
[] -> %% The result is not used.
224
[load_p_field(Dst1, ?P_ID),
228
277
[gen_redtest(1),GotoCont];
231
hipe_rtl_arch:call_bif(Dst, get_msg, [], Cont, Fail);
281
gen_check_get_msg(Dst, GotoCont, Fail);
233
hipe_rtl_arch:call_bif(Dst, next_msg, [], Cont, Fail);
283
gen_next_msg(Dst, GotoCont);
235
hipe_rtl_arch:call_bif(Dst, select_msg, [], Cont, Fail);
285
gen_select_msg(Dst, Cont);
238
hipe_rtl:mk_call(Dst, Op, NewArgs, c, Cont, Fail);
287
gen_clear_timeout(Dst, GotoCont);
289
%% BIF call: am_set_timeout -> nbif_set_timeout -> hipe_set_timeout
290
[hipe_rtl:mk_call(Dst, set_timeout, Args, Cont, Fail, not_remote)];
240
hipe_rtl:mk_call(Dst, Op, Args, c, Cont, Fail);
292
gen_suspend_msg(Dst, Cont);
245
gen_call_fun(Dst, Args, Cont, Fail, ExitInfo);
296
gen_call_fun(Dst, Args, Cont, Fail);
246
297
{mkfun,MFA,MagicNum,Index} ->
248
299
[] -> %% The result is not used.
251
[gen_mkfun(Dst, MFA, MagicNum, Index, Args, Fail),GotoCont]
302
[gen_mkfun(Dst, MFA, MagicNum, Index, Args), GotoCont]
254
{closure_element, N} ->
304
{closure_element,N} ->
256
306
[] -> %% The result is not used.
349
373
hipe_tagscheme:unsafe_untag_float(Dst1, Arg)
352
375
unsafe_tag_float ->
356
hipe_tagscheme:unsafe_tag_float(hipe_rtl:mk_new_var(),
379
hipe_tagscheme:unsafe_tag_float(hipe_rtl:mk_new_var(), Arg);
359
hipe_tagscheme:unsafe_tag_float(Dst1, Arg, Options)
381
hipe_tagscheme:unsafe_tag_float(Dst1, Arg)
384
%% Only names listed above are accepted! MFA:s are not primops!
363
generic_primop(Dst, Op, Args, Cont, Fail, ExitInfo)
386
erlang:error({bad_primop, Op})
365
{Code, VarMap, ConstTab}
369
%% ____________________________________________________________________
372
%% Generate code for a generic call to a bif.
373
generic_primop(Dsts, Op, Args, Continuation, Fail, ExitInfo) ->
374
%% Get arity and name
377
{_Mod,BifName,A} -> %% An ordinary MFA
379
_ -> %% Some internal primop with just a name.
383
%% Test if the bif can fail
384
Fails = hipe_bif:fails(Arity,Name),
385
if Fails =:= false ->
386
%% The bif can't fail just call it.
387
[hipe_rtl:mk_call(Dsts, Op , Args, c, Continuation, [])];
389
%% The bif can fail, call it and test.
390
failing_primop(Dsts, Op, Args, Continuation, Fail, ExitInfo)
393
%% Generate code for a bif that can fail.
394
failing_primop(Dsts, Op, Args, Continuation, Fail, _ExitInfo) ->
395
[hipe_rtl:mk_call(Dsts, Op, Args, c, Continuation, Fail)].
398
%% Generate code for a bif that can fail.
399
gen_call_bif(Res, Args, Cont, Fail, Op, _ExitReason, _ExitInfo) ->
400
[hipe_rtl:mk_call(Res, Op, Args, c, Cont, Fail)].
404
%% ____________________________________________________________________
407
%% ____________________________________________________________________
391
gen_enter_primop({Op, Args}, IsGuard, ConstTab, Options) ->
394
%% Tail-call to a closure must preserve tail-callness!
395
%% (Passing Continuation = [] to gen_call_fun/5 does this.)
396
Code = gen_call_fun([], Args, [], []),
400
%% Tail-call to a closure must preserve tail-callness!
401
%% (Passing Continuation = [] to gen_apply_N/5 does this.)
402
Code = gen_apply_N([], Arity, Args, [], []),
406
%% All other primop tail calls are converted to call + return.
407
Dst = [hipe_rtl:mk_new_var()],
408
OkLab = hipe_rtl:mk_new_label(),
410
gen_primop({Op,Dst,Args,hipe_rtl:label_name(OkLab),[]},
411
IsGuard, ConstTab, Options),
412
{Code ++ [OkLab, hipe_rtl:mk_return(Dst)], ConstTab1}
416
%% --------------------------------------------------------------------
412
421
%% Inline addition & subtraction
415
gen_add_sub_2(Dst, Args, Cont, Fail, _Annot, Op, AluOp, ExitInfo) ->
424
gen_add_sub_2(Dst, Args, Cont, Fail, Op, AluOp) ->
416
425
[Arg1, Arg2] = Args,
417
426
GenCaseLabel = hipe_rtl:mk_new_label(),
420
gen_op_general_case(hipe_rtl:mk_new_var(),
421
Op, Args, Cont, Fail, GenCaseLabel, ExitInfo);
429
[hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
430
hipe_rtl:label_name(GenCaseLabel))|
431
gen_op_general_case(hipe_rtl:mk_new_var(),
432
Op, Args, Cont, Fail, GenCaseLabel)];
423
434
[hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
424
435
hipe_rtl:label_name(GenCaseLabel)),
425
436
hipe_tagscheme:fixnum_addsub(AluOp, Arg1, Arg2, Res, GenCaseLabel)|
426
gen_op_general_case(Res,Op, Args, Cont, Fail, GenCaseLabel, ExitInfo)]
430
gen_op_general_case(Res, Op, Args, Cont, Fail, GenCaseLabel, ExitInfo) ->
437
gen_op_general_case(Res,Op, Args, Cont, Fail, GenCaseLabel)]
440
gen_unsafe_add_sub_2(Dst, Args, Cont, Fail, Op, AluOp) ->
444
[hipe_rtl:mk_goto(Cont)];
448
GenCaseLabel = hipe_rtl:mk_new_label(),
449
[hipe_tagscheme:fixnum_addsub(AluOp, Arg1, Arg2, Res, GenCaseLabel)|
450
gen_op_general_case(Res,Op, Args, Cont, Fail, GenCaseLabel)];
452
[hipe_tagscheme:fixnum_addsub(AluOp, Arg1, Arg2, Res,
453
hipe_rtl:mk_label(Fail))]
457
gen_extra_unsafe_add_2(Dst, Args, Cont) ->
461
[hipe_rtl:mk_goto(Cont)];
463
hipe_tagscheme:unsafe_fixnum_add(Arg1, Arg2, Res)
466
gen_extra_unsafe_sub_2(Dst, Args, Cont) ->
470
[hipe_rtl:mk_goto(Cont)];
472
hipe_tagscheme:unsafe_fixnum_sub(Arg1, Arg2, Res)
475
gen_op_general_case(Res, Op, Args, Cont, Fail, GenCaseLabel) ->
431
476
[hipe_rtl:mk_goto(Cont),
433
gen_call_bif([Res], Args, Cont, Fail, Op, badarith, ExitInfo)].
478
hipe_rtl:mk_call([Res], Op, Args, Cont, Fail, not_remote)].
436
481
%% We don't inline multiplication at the moment
439
%%gen_mul_2([Res], Args, Cont, Fail, Annot, Op, ExitInfo) ->
440
%% [Arg1, Arg2] = Args,
441
%% GenCaseLabel = hipe_rtl:mk_new_label(),
442
%% [hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
443
%% hipe_rtl:label_name(GenCaseLabel)),
444
%% hipe_tagscheme:fixnum_mul(Arg1, Arg2, Res, GenCaseLabel)|
445
%% gen_op_general_case(Res, Op, Args, Cont, Fail, GenCaseLabel, ExitInfo)].
484
%% gen_unsafe_mul_2([Res], Args, Cont, Fail, Op) ->
485
%% [Arg1, Arg2] = Args,
486
%% GenCaseLabel = hipe_rtl:mk_new_label(),
487
%% [hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
488
%% hipe_rtl:label_name(GenCaseLabel)),
489
%% hipe_tagscheme:fixnum_mul(Arg1, Arg2, Res, GenCaseLabel)|
490
%% gen_op_general_case(Res, Op, Args, Cont, Fail, GenCaseLabel)].
448
493
%% Inline bitoperations.
450
495
%% The shift operations are too expensive to inline.
453
gen_bitop_2([Res], Args, Cont, Fail, _Annot, Op, BitOp, ExitInfo) ->
455
GenCaseLabel = hipe_rtl:mk_new_label(),
457
[hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
458
hipe_rtl:label_name(GenCaseLabel)),
459
hipe_tagscheme:fixnum_andorxor(BitOp, Arg1, Arg2, Res)|
460
gen_op_general_case(Res, Op, Args, Cont, Fail, GenCaseLabel, ExitInfo)].
498
gen_bitop_2(Res, Args, Cont, Fail, Op, BitOp) ->
500
GenCaseLabel = hipe_rtl:mk_new_label(),
502
[] -> %% The result is not used.
503
[hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
504
hipe_rtl:label_name(GenCaseLabel))|
505
gen_op_general_case(hipe_rtl:mk_new_var(),
506
Op, Args, Cont, Fail, GenCaseLabel)];
508
[hipe_tagscheme:test_two_fixnums(Arg1, Arg2,
509
hipe_rtl:label_name(GenCaseLabel)),
510
hipe_tagscheme:fixnum_andorxor(BitOp, Arg1, Arg2, Res0)|
511
gen_op_general_case(Res0, Op, Args, Cont, Fail, GenCaseLabel)]
514
gen_unsafe_bitop_2(Res, Args, Cont, BitOp) ->
516
[] -> %% The result is not used.
517
[hipe_rtl:mk_goto(Cont)];
520
[hipe_tagscheme:fixnum_andorxor(BitOp, Arg1, Arg2, Res0),
521
hipe_rtl:mk_goto(Cont)]
524
gen_bsr_2(Res, Args, Cont, Fail, Op) ->
526
GenCaseLabel = hipe_rtl:mk_new_label(),
527
case hipe_rtl:is_imm(Arg2) of
529
Val = hipe_tagscheme:fixnum_val(hipe_rtl:imm_value(Arg2)),
530
Limit = ?bytes_to_bits(hipe_rtl_arch:word_size()),
532
Val < Limit, Val >= 0 ->
535
[hipe_tagscheme:test_fixnum(Arg1,
536
hipe_rtl:label_name(Cont),
537
hipe_rtl:label_name(GenCaseLabel),
539
gen_op_general_case(hipe_rtl:mk_new_var(), Op, Args, Cont, Fail,
542
FixLabel = hipe_rtl:mk_new_label(),
543
[hipe_tagscheme:test_fixnum(Arg1,
544
hipe_rtl:label_name(FixLabel),
545
hipe_rtl:label_name(GenCaseLabel),
548
hipe_tagscheme:fixnum_bsr(Arg1, Arg2, Res0),
549
gen_op_general_case(Res0, Op, Args, Cont, Fail, GenCaseLabel)]
552
[hipe_rtl:mk_call(Res, 'bsr', Args, Cont, Fail, not_remote)]
555
[hipe_rtl:mk_call(Res, 'bsr', Args, Cont, Fail, not_remote)]
558
gen_unsafe_bsr_2(Res, Args, Cont) ->
560
[] -> %% The result is not used.
561
[hipe_rtl:mk_goto(Cont)];
564
[hipe_tagscheme:fixnum_bsr(Arg1, Arg2, Res0),
565
hipe_rtl:mk_goto(Cont)]
568
gen_unsafe_bsl_2(Res, Args, Cont) ->
570
[] -> %% The result is not used.
571
[hipe_rtl:mk_goto(Cont)];
574
[hipe_tagscheme:fixnum_bsl(Arg1, Arg2, Res0),
575
hipe_rtl:mk_goto(Cont)]
466
gen_bnot_2([Res], Args, Cont, Fail, _Annot, Op, ExitInfo) ->
582
gen_bnot_2(Res, Args, Cont, Fail, Op) ->
468
FixLabel = hipe_rtl:mk_new_label(),
469
OtherLabel = hipe_rtl:mk_new_label(),
471
[hipe_tagscheme:test_fixnum(Arg, hipe_rtl:label_name(FixLabel),
472
hipe_rtl:label_name(OtherLabel), 0.99),
474
hipe_tagscheme:fixnum_not(Arg, Res),
475
gen_op_general_case(Res, Op, Args, Cont, Fail, OtherLabel, ExitInfo)
479
%% ____________________________________________________________________
584
GenCaseLabel = hipe_rtl:mk_new_label(),
586
[] -> %% The result is not used.
587
[hipe_tagscheme:test_fixnum(Arg, hipe_rtl:label_name(Cont),
588
hipe_rtl:label_name(GenCaseLabel), 0.99),
589
gen_op_general_case(hipe_rtl:mk_new_var(), Op, Args, Cont, Fail,
593
FixLabel = hipe_rtl:mk_new_label(),
594
[hipe_tagscheme:test_fixnum(Arg, hipe_rtl:label_name(FixLabel),
595
hipe_rtl:label_name(GenCaseLabel), 0.99),
597
hipe_tagscheme:fixnum_not(Arg, Res0),
598
gen_op_general_case(Res0, Op, Args, Cont, Fail, GenCaseLabel)]
601
gen_unsafe_bnot_2(Res, Args, Cont) ->
603
[] -> %% The result is not used.
604
[hipe_rtl:mk_goto(Cont)];
607
[hipe_tagscheme:fixnum_not(Arg1, Res0),
608
hipe_rtl:mk_goto(Cont)]
612
%% --------------------------------------------------------------------
486
gen_cons(Dst, [Arg1, Arg2], Options) ->
619
gen_cons(Dst, [Arg1, Arg2]) ->
487
620
Tmp = hipe_rtl:mk_new_reg(),
488
621
{GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(),
492
hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(0), Arg1),
493
hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(4), Arg2),
494
hipe_rtl:mk_move(Tmp, HP),
495
hipe_tagscheme:tag_cons(Dst, Tmp),
496
hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(8)),
498
case ?AddGC(Options) of
499
true -> [hipe_rtl:mk_gctest(2)|Code];
622
WordSize = hipe_rtl_arch:word_size(),
623
HeapNeed = 2*WordSize,
625
hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(0), Arg1),
626
hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(WordSize), Arg2),
627
hipe_rtl:mk_move(Tmp, HP),
628
hipe_tagscheme:tag_cons(Dst, Tmp),
629
hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(HeapNeed)),
503
632
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504
%% ____________________________________________________________________
633
%% --------------------------------------------------------------------
506
634
%% Handling of closures...
507
%% ____________________________________________________________________
635
%% --------------------------------------------------------------------
509
%% ____________________________________________________________________
637
%% --------------------------------------------------------------------
512
640
%% The gc_test should have expanded to
513
641
%% unsigned needed = ERL_FUN_SIZE + num_free;
514
642
%% ErlFunThing* funp = (ErlFunThing *) HAlloc(p, needed);
516
%% The code generated should do the eq of:
644
%% The code generated should do the equivalent of:
517
645
%% Copy arguments to the fun thing
518
646
%% Eterm* hp = funp->env;
519
647
%% for (i = 0; i < num_free; i++) {
598
725
store_struct_field(FunP, ?EFT_ARITY, hipe_rtl:mk_imm(Arity-NumFree)),
600
load_struct_field(RefcVar, FeVar, ?EFE_REFC),
601
hipe_rtl:mk_alu(RefcVar, RefcVar, add, hipe_rtl:mk_imm(1)),
602
store_struct_field(FeVar, ?EFE_REFC, RefcVar),
727
gen_inc_refc(FeVar, ?EFE_REFC),
604
729
store_struct_field(FunP, ?EFT_NUM_FREE, hipe_rtl:mk_imm(NumFree)),
605
730
load_p_field(PidVar, ?P_ID),
606
731
store_struct_field(FunP, ?EFT_CREATOR, PidVar),
607
store_struct_field(FunP, ?EFT_THING,
608
hipe_tagscheme:mk_fun_header())].
611
-ifdef(HEAP_ARCH_PRIVATE).
732
store_struct_field(FunP, ?EFT_THING, hipe_tagscheme:mk_fun_header())].
734
gen_inc_refc(Ptr, Offset) ->
736
0 -> gen_inc_refc_notsmp(Ptr, Offset);
737
1 -> gen_inc_refc_smp(Ptr, Offset)
740
gen_inc_refc_notsmp(Ptr, Offset) ->
741
Refc = hipe_rtl:mk_new_reg(),
742
[load_struct_field(Refc, Ptr, Offset, int32),
743
hipe_rtl:mk_alu(Refc, Refc, add, hipe_rtl:mk_imm(1)),
744
store_struct_field(Ptr, Offset, Refc, int32)].
746
gen_inc_refc_smp(Ptr, Offset) ->
747
Refc = hipe_rtl:mk_new_reg(),
748
[hipe_rtl:mk_alu(Refc, Ptr, 'add', hipe_rtl:mk_imm(Offset)),
749
hipe_rtl:mk_call([], 'atomic_inc', [Refc], [], [], not_remote)].
612
751
gen_link_closure(FUNP) ->
752
case ?P_OFF_HEAP_FUNS of
753
[] -> gen_link_closure_non_private(FUNP);
754
_ -> gen_link_closure_private(FUNP)
757
gen_link_closure_private(FUNP) ->
613
758
%% Link to the process off_heap.funs list
614
759
%% funp->next = p->off_heap.funs;
615
760
%% p->off_heap.funs = funp;
635
777
load_struct_field(Dest, StructP, Offset) ->
636
778
hipe_rtl:mk_load(Dest, StructP, hipe_rtl:mk_imm(Offset)).
780
store_struct_field(StructP, Offset, Src, int32) ->
781
hipe_rtl:mk_store(StructP, hipe_rtl:mk_imm(Offset), Src, int32).
783
load_struct_field(Dest, StructP, Offset, int32) ->
784
hipe_rtl:mk_load(Dest, StructP, hipe_rtl:mk_imm(Offset), int32, signed).
638
786
gen_free_vars(Vars, HPReg) ->
639
HPVar = hipe_rtl:mk_new_var(),
787
HPVar = hipe_rtl:mk_new_var(),
788
WordSize�= hipe_rtl_arch:word_size(),
640
789
[hipe_rtl:mk_alu(HPVar, HPReg, add, hipe_rtl:mk_imm(?EFT_ENV)) |
641
gen_free_vars(Vars, HPVar, 0, [])].
790
gen_free_vars(Vars, HPVar, 0, WordSize, [])].
643
gen_free_vars([Var|Vars], EnvPVar, Offset, AccCode) ->
792
gen_free_vars([Var|Vars], EnvPVar, Offset, WordSize, AccCode) ->
644
793
Code = hipe_rtl:mk_store(EnvPVar, hipe_rtl:mk_imm(Offset), Var),
645
gen_free_vars(Vars, EnvPVar, Offset + 4, [Code|AccCode]);
646
gen_free_vars([], _, _, AccCode) -> AccCode.
794
gen_free_vars(Vars, EnvPVar, Offset + WordSize, WordSize,
796
gen_free_vars([], _, _, _, AccCode) -> AccCode.
648
798
%% ------------------------------------------------------------------
650
%% enter_fun and call_fun
652
gen_enter_fun(Args, ExitInfo) ->
653
gen_call_fun([], Args, [], [], ExitInfo).
800
%% call_fun (also handles enter_fun when Continuation = [])
655
gen_call_fun(Dst, ArgsAndFun, Continuation, Fail, ExitInfo) ->
802
gen_call_fun(Dst, ArgsAndFun, Continuation, Fail) ->
656
803
NAddressReg = hipe_rtl:mk_new_reg(),
657
ArityReg = hipe_rtl:mk_new_reg(),
658
BadFunLab = hipe_rtl:mk_new_label(),
659
BadArityLab = hipe_rtl:mk_new_label(),
660
[Fun|Args] = lists:reverse(ArgsAndFun),
662
FailCode = hipe_rtl_exceptions:gen_funcall_fail(Fail, Fun, BadFunLab,
663
BadArityLab, ExitInfo),
804
ArityReg = hipe_rtl:mk_new_reg_gcsafe(),
805
[Fun|RevArgs] = lists:reverse(ArgsAndFun),
807
%% {BadFunLabName, BadFunCode} = gen_fail_code(Fail, {badfun, Fun}),
808
Args = lists:reverse(RevArgs),
809
NonClosureLabel = hipe_rtl:mk_new_label(),
810
CallNonClosureLabel = hipe_rtl:mk_new_label(),
811
BadFunLabName = hipe_rtl:label_name(NonClosureLabel),
814
hipe_rtl:mk_call([NAddressReg],
815
'nonclosure_address',
816
[Fun, hipe_rtl:mk_imm(length(Args))],
817
hipe_rtl:label_name(CallNonClosureLabel),
823
hipe_rtl:mk_enter(NAddressReg, Args, not_remote);
825
hipe_rtl:mk_call(Dst, NAddressReg, Args, Continuation, Fail, not_remote)
828
{BadArityLabName, BadArityCode} = gen_fail_code(Fail, {badarity, Fun}),
666
hipe_tagscheme:if_fun_get_arity_and_address(ArityReg,
668
hipe_rtl:label_name(BadFunLab),
831
hipe_tagscheme:if_fun_get_arity_and_address(ArityReg, NAddressReg,
670
CheckArityCode = check_arity(ArityReg, length(Args),
671
hipe_rtl:label_name(BadArityLab)),
834
CheckArityCode = check_arity(ArityReg, length(RevArgs),
674
837
case Continuation of
675
838
[] -> %% This is a tailcall
676
[hipe_rtl:mk_enter(NAddressReg,
839
[hipe_rtl:mk_enter(NAddressReg, ArgsAndFun, not_remote)];
679
840
_ -> %% Ordinary call
680
[hipe_rtl:mk_call(Dst, NAddressReg,
841
[hipe_rtl:mk_call(Dst, NAddressReg, ArgsAndFun,
842
Continuation, Fail, not_remote)]
685
[CheckGetCode,CheckArityCode, CallCode, FailCode].
844
[CheckGetCode, CheckArityCode, CallCode, BadFunCode, BadArityCode].
688
846
check_arity(ArityReg, Arity, BadArityLab) ->
689
847
TrueLab1 = hipe_rtl:mk_new_label(),
691
[hipe_rtl:mk_branch(ArityReg, eq, hipe_rtl:mk_imm(Arity),
692
hipe_rtl:label_name(TrueLab1), BadArityLab,
696
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848
[hipe_rtl:mk_branch(ArityReg, eq, hipe_rtl:mk_imm(Arity),
849
hipe_rtl:label_name(TrueLab1), BadArityLab, 0.9),
701
852
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707
%%gen_apply(Dst, Args, Cont, Fail, ExitInfo) ->
708
%% Lab1 = hipe_rtl:mk_new_label(),
709
%% Lab2 = hipe_rtl:mk_new_label(),
710
%% CallEmuLab = hipe_rtl:mk_new_label(),
711
%% CallDirectLab = hipe_rtl:mk_new_label(),
712
%% ArityR = hipe_rtl:mk_new_reg(),
713
%% MFAReg = hipe_rtl:mk_new_reg(),
714
%% AtomNoReg = hipe_rtl:mk_new_reg(),
715
%% RequestReg = hipe_rtl:mk_new_reg(),
716
%% AddressReg = hipe_rtl:mk_new_reg(),
718
%% [M,F,AppArgs] = Args,
720
%% [hipe_rtl:mk_call(ArityR, {erlang,length,1} , [AppArgs], c,
721
%% hipe_rtl:label_name(Lab1), Fail),
723
%% hipe_rtl:mk_move(AtomNoReg, hipe_rtl:mk_imm(native_address))] ++
724
%% gen_mk_tuple(MFAReg, [M,F,ArityR], []) ++
725
%% gen_mk_tuple(RequestReg, [MFAReg,AtomNoReg], []) ++
727
%% hipe_rtl:mk_call(AddressReg,
728
%% {hipe_bifs,get_funinfo,1} , [RequestReg], c,
729
%% hipe_rtl:label_name(Lab2), Fail),
731
%% hipe_rtl:mk_branch(AddressReg, eq,
732
%% hipe_rtl:mk_imm(hipe_tagscheme:mk_nil()),
733
%% hipe_rtl:label_name(CallEmuLab),
734
%% hipe_rtl:label_name(CallDirectLab), 0.01),
736
%% generic_primop(Dst, {hipe_internal, apply, 3},
737
%% Args, Cont, Fail, ExitInfo),
739
%% hipe_rtl:mk_call(Dst, AddressReg,
856
%% The tail call case is not handled here.
858
gen_apply(Dst, Args=[_M,_F,_AppArgs], Cont, Fail) ->
859
%% Dst can be [Res] or [].
860
[hipe_rtl:mk_call(Dst, hipe_apply, Args, Cont, Fail, not_remote)].
862
gen_enter_apply(Args=[_M,_F,_AppArgs]) ->
863
%% 'apply' in tail-call context
864
[hipe_rtl:mk_enter(hipe_apply, Args, not_remote)].
868
%% also handles tailcall case (Cont=[])
871
gen_apply_N(Dst, Arity, [M,F|CallArgs], Cont, Fail) ->
872
CallLabel = hipe_rtl:mk_new_label(),
873
CodeAddress = hipe_rtl:mk_new_reg(),
874
[hipe_rtl:mk_call([CodeAddress], find_na_or_make_stub,
875
[M,F,hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(Arity))],
876
hipe_rtl:label_name(CallLabel),
881
hipe_rtl:mk_enter(CodeAddress, CallArgs, not_remote);
882
_ -> % recursive call
883
hipe_rtl:mk_call(Dst, CodeAddress, CallArgs, Cont, Fail, not_remote)
747
887
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752
gen_mk_tuple(Dst, Elements, Options) ->
892
gen_mk_tuple(Dst, Elements) ->
753
893
{GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(),
754
894
Arity = length(Elements),
758
gen_tuple_header(HP, Arity),
759
set_tuple_elements(HP, 4, Elements, []),
760
hipe_tagscheme:tag_tuple(Dst, HP),
761
hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm((Arity+1)*4)),
763
case ?AddGC(Options) of
764
true -> [hipe_rtl:mk_gctest(Arity + 1)|Code];
768
set_tuple_elements(HP, Offset, [Element|Elements], Stores) ->
895
WordSize = hipe_rtl_arch:word_size(),
896
HeapNeed = (Arity+1)*WordSize,
898
gen_tuple_header(HP, Arity),
899
set_tuple_elements(HP, WordSize, WordSize, Elements, []),
900
hipe_tagscheme:tag_tuple(Dst, HP),
901
hipe_rtl:mk_alu(HP, HP, add, hipe_rtl:mk_imm(HeapNeed)),
904
set_tuple_elements(HP, Offset, WordSize, [Element|Elements], Stores) ->
769
905
Store = hipe_rtl:mk_store(HP, hipe_rtl:mk_imm(Offset), Element),
770
set_tuple_elements(HP, Offset + 4, Elements, [Store | Stores]);
771
set_tuple_elements(_, _, [], Stores) ->
906
set_tuple_elements(HP, Offset+WordSize, WordSize, Elements, [Store|Stores]);
907
set_tuple_elements(_, _, _, [], Stores) ->
772
908
lists:reverse(Stores).
911
%% @doc Generate RTL code for the reduction test.
777
913
gen_redtest(Amount) ->
778
Reds = hipe_rtl:mk_reg(hipe_rtl_arch:fcalls_reg()),
914
{GetFCallsInsn, FCalls, PutFCallsInsn} = hipe_rtl_arch:fcalls(),
779
915
SuspendLabel = hipe_rtl:mk_new_label(),
780
916
StayLabel = hipe_rtl:mk_new_label(),
781
[hipe_rtl:mk_alub(Reds, Reds, 'sub', hipe_rtl:mk_imm(Amount), 'lt',
917
ContinueLabel = hipe_rtl:mk_new_label(),
919
hipe_rtl:mk_alub(FCalls, FCalls, 'sub', hipe_rtl:mk_imm(Amount), 'lt',
782
920
hipe_rtl:label_name(SuspendLabel),
783
921
hipe_rtl:label_name(StayLabel), 0.01),
785
hipe_rtl:mk_call([], suspend_0, [], c, hipe_rtl:label_name(StayLabel), []),
923
%% The suspend path should not execute PutFCallsInsn.
924
hipe_rtl:mk_call([], suspend_0, [], hipe_rtl:label_name(ContinueLabel), [], not_remote),
929
gen_self(Dst, Cont) ->
931
[] -> %% The result is not used.
932
[hipe_rtl:mk_goto(Cont)];
934
[load_p_field(Dst1, ?P_ID),
935
hipe_rtl:mk_goto(Cont)]
789
939
%% Generate unsafe head
814
972
case hipe_rtl:is_imm(Index) of
815
973
true -> hipe_tagscheme:unsafe_constant_element(Dst, Index, Tuple);
816
974
false -> ?EXIT({illegal_index_to_unsafe_element,Index})
819
977
gen_unsafe_update_element(Tuple, Index, Value) ->
820
978
case hipe_rtl:is_imm(Index) of
822
980
hipe_tagscheme:unsafe_update_element(Tuple, Index, Value);
823
false -> ?EXIT({illegal_index_to_unsafe_update_element,Index})
982
?EXIT({illegal_index_to_unsafe_update_element,Index})
827
986
gen_closure_element(Dst, Index, Closure) ->
828
987
hipe_tagscheme:unsafe_closure_element(Dst, Index, Closure).
831
%% Generate code that writes a tuple header
990
%% @doc Generate RTL code that writes a tuple header.
833
992
gen_tuple_header(Ptr, Arity) ->
834
993
Header = hipe_tagscheme:mk_arityval(Arity),
835
994
hipe_rtl:mk_store(Ptr, hipe_rtl:mk_imm(0), hipe_rtl:mk_imm(Header)).
838
%% ____________________________________________________________________
996
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000
gen_check_get_msg(Dsts, GotoCont, Fail) ->
1001
case ?ERTS_IS_SMP of
1002
0 -> gen_check_get_msg_notsmp(Dsts, GotoCont, Fail);
1003
1 -> gen_check_get_msg_smp(Dsts, GotoCont, Fail)
1006
gen_clear_timeout([], GotoCont) ->
1007
case ?ERTS_IS_SMP of
1008
0 -> gen_clear_timeout_notsmp(GotoCont);
1009
1 -> gen_clear_timeout_smp(GotoCont)
1012
%%% check_get_msg is:
1013
%%% if (!PEEK_MESSAGE(p)) goto Fail;
1014
%%% Dst = ERL_MESSAGE_TERM(PEEK_MESSAGE(p));
1016
%%% ErlMessage **save = p->msg.save;
1017
%%% ErlMessage *msg = *save;
1018
%%% if (!msg) goto Fail;
1019
%%% Dst = msg->m[0];
1020
gen_check_get_msg_notsmp(Dsts, GotoCont, Fail) ->
1021
Save = hipe_rtl:mk_new_reg(),
1022
Msg = hipe_rtl:mk_new_reg(),
1023
TrueLbl = hipe_rtl:mk_new_label(),
1024
[load_p_field(Save, ?P_MSG_SAVE),
1025
load_struct_field(Msg, Save, 0),
1026
hipe_rtl:mk_branch(Msg, eq, hipe_rtl:mk_imm(0), Fail,
1027
hipe_rtl:label_name(TrueLbl), 0.1),
1031
[load_struct_field(Dst, Msg, ?MSG_MESSAGE),
1033
[] -> % receive which throws away the message
1038
%%% SAVE_MESSAGE(p);
1040
%%% ErlMessage **save = p->msg.save;
1041
%%% ErlMessage *msg = *save;
1042
%%% ErlMessage **next = &msg->next;
1043
%%% p->msg.save = next;
1044
gen_next_msg([], GotoCont) ->
1045
Save = hipe_rtl:mk_new_reg(),
1046
Msg = hipe_rtl:mk_new_reg(),
1052
%% offsetof(ErlMessage,next) is normally 0, so "&msg->next"
1053
%% becomes an add with 0. Unfortunately RTL doesn't optimise
1054
%% that away; hence this special case.
1055
[store_p_field(Msg, ?P_MSG_SAVE) |
1058
Next = hipe_rtl:mk_new_reg(),
1059
[hipe_rtl:mk_alu(Next, Msg, 'add', hipe_rtl:mk_imm(?MSG_NEXT)),
1060
store_p_field(Next, ?P_MSG_SAVE) |
1064
[load_p_field(Save, ?P_MSG_SAVE),
1065
load_struct_field(Msg, Save, 0) |
1068
%%% clear_timeout is:
1069
%%% p->flags &= ~F_TIMO; JOIN_MESSAGE(p);
1071
%%% p->flags &= ~F_TIMO;
1072
%%% p->msg.save = &p->msg.first;
1073
gen_clear_timeout_notsmp(GotoCont) ->
1074
Flags1 = hipe_rtl:mk_new_reg(),
1075
Flags2 = hipe_rtl:mk_new_reg_gcsafe(),
1076
First = hipe_rtl:mk_new_reg_gcsafe(),
1077
[load_p_field(Flags1, ?P_FLAGS),
1078
hipe_rtl:mk_alu(Flags2, Flags1, 'and', hipe_rtl:mk_imm(bnot(?F_TIMO))),
1079
store_p_field(Flags2, ?P_FLAGS),
1080
hipe_rtl_arch:pcb_address(First, ?P_MSG_FIRST),
1081
store_p_field(First, ?P_MSG_SAVE),
1084
gen_check_get_msg_smp(Dsts, GotoCont, Fail) ->
1085
RetLbl = hipe_rtl:mk_new_label(),
1086
TrueLbl = hipe_rtl:mk_new_label(),
1087
Tmp = hipe_rtl:mk_new_reg(),
1088
TheNonValue = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()),
1089
[hipe_rtl_arch:call_bif([Tmp], check_get_msg, [],
1090
hipe_rtl:label_name(RetLbl), []),
1092
hipe_rtl:mk_branch(Tmp, eq, TheNonValue, Fail,
1093
hipe_rtl:label_name(TrueLbl), 0.1),
1097
[hipe_rtl:mk_move(Dst, Tmp),
1099
[] -> % receive which throws away the message
1103
gen_clear_timeout_smp(GotoCont) ->
1104
RetLbl = hipe_rtl:mk_new_label(),
1105
[hipe_rtl_arch:call_bif([], clear_timeout, [],
1106
hipe_rtl:label_name(RetLbl), []),
1110
gen_select_msg([], Cont) ->
1111
[hipe_rtl_arch:call_bif([], select_msg, [], Cont, [])].
1113
gen_suspend_msg([], Cont) ->
1114
[hipe_rtl:mk_call([], suspend_msg, [], Cont, [], not_remote)].
1116
%% --------------------------------------------------------------------
840
1118
%% Floating point handling
843
1121
gen_fclearerror() ->
844
Addr = hipe_rtl:mk_new_reg(),
845
[hipe_rtl:mk_load_address(Addr, erl_fp_exception, c_const),
846
hipe_rtl:mk_store(Addr, hipe_rtl:mk_imm(0), hipe_rtl:mk_imm(0))].
1122
case ?P_FP_EXCEPTION of
1126
[hipe_rtl_arch:pcb_store(Offset, hipe_rtl:mk_imm(0), int32)]
848
gen_fcheckerror(ContLbl, FailLbl, ExitInfo)->
1129
gen_fcheckerror(ContLbl, FailLbl)->
849
1130
Tmp = hipe_rtl:mk_new_reg(),
850
1131
TmpFailLbl0 = hipe_rtl:mk_new_label(),
851
TmpFailLbl1 = hipe_rtl:mk_new_label(),
852
Result = hipe_rtl:mk_new_var(),
854
Addr = hipe_rtl:mk_new_reg(),
856
FailCode = fp_fail_code(TmpFailLbl0, TmpFailLbl1,
857
FailLbl, Result, ExitInfo),
859
case get(hipe_target_arch) of
860
x86 -> erl_fp_check_exception;
861
ultrasparc -> erl_fp_exception
864
[hipe_rtl:mk_load_address(Addr, ExceptionAtom, c_const),
865
hipe_rtl:mk_load(Tmp, Addr, hipe_rtl:mk_imm(0)),
866
hipe_rtl:mk_branch(Tmp, eq, hipe_rtl:mk_imm(0),
867
ContLbl, hipe_rtl:label_name(TmpFailLbl0))]++
1132
FailCode = fp_fail_code(TmpFailLbl0, FailLbl),
1133
hipe_rtl_arch:fwait() ++
1134
case ?P_FP_EXCEPTION of
1138
[hipe_rtl_arch:pcb_load(Tmp, Offset, int32)]
1140
[hipe_rtl:mk_branch(Tmp, eq, hipe_rtl:mk_imm(0),
1141
ContLbl, hipe_rtl:label_name(TmpFailLbl0), 0.9)] ++
870
gen_conv_to_float(Dst, [Src], ContLbl, FailLbl, ExitInfo) ->
1144
gen_conv_to_float(Dst, [Src], ContLbl, FailLbl) ->
871
1145
case hipe_rtl:is_var(Src) of
873
1147
Tmp = hipe_rtl:mk_new_var(),
874
TmpReg = hipe_rtl:mk_new_reg(),
1148
TmpReg = hipe_rtl:mk_new_reg_gcsafe(),
875
1149
TrueFixNum = hipe_rtl:mk_new_label(),
876
1150
ContFixNum = hipe_rtl:mk_new_label(),
877
1151
TrueFp = hipe_rtl:mk_new_label(),
878
1152
ContFp = hipe_rtl:mk_new_label(),
879
1153
ContBigNum = hipe_rtl:mk_new_label(),
880
TestFixNum = hipe_tagscheme:test_fixnum(Src, hipe_rtl:label_name(TrueFixNum),
881
hipe_rtl:label_name(ContFixNum), 0.5),
1154
TestFixNum = hipe_tagscheme:test_fixnum(Src,
1155
hipe_rtl:label_name(TrueFixNum),
1156
hipe_rtl:label_name(ContFixNum),
882
1158
TestFp = hipe_tagscheme:test_flonum(Src, hipe_rtl:label_name(TrueFp),
883
1159
hipe_rtl:label_name(ContFp), 0.5),
884
1160
GotoCont = hipe_rtl:mk_goto(ContLbl),
885
1161
TmpFailLbl0 = hipe_rtl:mk_new_label(),
886
TmpFailLbl1 = hipe_rtl:mk_new_label(),
887
Result = hipe_rtl:mk_new_var(),
888
FailCode = fp_fail_code(TmpFailLbl0, TmpFailLbl1,
889
FailLbl, Result, ExitInfo),
1162
FailCode = fp_fail_code(TmpFailLbl0, FailLbl),
899
1172
hipe_tagscheme:unsafe_untag_float(Dst, Src),
902
[hipe_rtl:mk_call([Tmp],conv_big_to_float,[Src], c,
1175
[hipe_rtl:mk_call([Tmp],conv_big_to_float,[Src],
903
1176
hipe_rtl:label_name(ContBigNum),
904
hipe_rtl:label_name(TmpFailLbl0))]++
1177
hipe_rtl:label_name(TmpFailLbl0), not_remote)]++
907
1180
hipe_tagscheme:unsafe_untag_float(Dst, Tmp)];
909
1182
%% This must be an attempt to convert an illegal term.
910
Result = hipe_rtl:mk_new_var(),
911
[hipe_rtl_exceptions:gen_fail_code(FailLbl, Result, badarith, ExitInfo)]
914
fp_fail_code(TmpFailLbl0, TmpFailLbl1, FailLbl, Result, ExitInfo)->
915
case get(hipe_target_arch) of
918
hipe_rtl:mk_call([], handle_fp_exception, [], c,
919
hipe_rtl:label_name(TmpFailLbl1), []),
921
hipe_rtl_exceptions:gen_fail_code(FailLbl, Result,
922
badarith, ExitInfo)];
925
hipe_rtl_exceptions:gen_fail_code
926
(FailLbl, Result, badarith, ExitInfo)]
929
%% ____________________________________________________________________
935
erl_bif_types:type(erlang, '+', 2, Args);
937
erl_bif_types:type(erlang, '-', 2, Args);
938
type(cons, [HeadType, TailType])->
939
erl_types:t_cons(HeadType, TailType);
940
type(unsafe_tl, [Type]) ->
941
case erl_types:t_is_cons(Type) of
942
true -> erl_types:t_cons_tl(Type);
943
_ -> erl_types:t_undefined()
945
type(unsafe_hd, [Type]) ->
946
case erl_types:t_is_cons(Type) of
947
true -> erl_types:t_cons_hd(Type);
948
_ -> erl_types:t_undefined()
950
type(mktuple, TypeList) ->
951
erl_types:t_tuple(TypeList);
952
type(unsafe_element, [IndexType, TupleType]) ->
953
case erl_types:t_number_vals(IndexType) of
954
[N] when is_integer(N)->
955
type({unsafe_element, N}, TupleType);
957
case erl_types:t_is_tuple(TupleType) of
961
case erl_types:t_tuple_args(TupleType) of
962
[H|T] = List when is_list(List) ->
963
case lists:all(fun(X)->X=:=H end, T) of
965
_ -> erl_types:t_any()
972
type({unsafe_element, N}, [Type]) ->
973
case erl_types:t_is_tuple(Type) of
977
case erl_types:t_tuple_args(Type) of
978
ArgTypes when is_list(ArgTypes) ->
979
lists:nth(N, ArgTypes);
983
type(unsafe_tag_float, _) ->
986
erl_bif_types:type(erlang, 'bor', 2, Args);
988
erl_bif_types:type(erlang, 'band', 2, Args);
990
erl_bif_types:type(erlang, 'bxor', 2, Args);
992
erl_bif_types:type(erlang, 'bnot', 2, Args);
993
type({hipe_bs_primop, {bs_get_integer, _, _}}, _) ->
994
%%TODO: Here we could find out if this is a fixnum.
995
erl_types:t_integer();
996
type({hipe_bs_primop, {bs_get_float, _, _}}, _) ->
998
type({hipe_bs_primop, {bs_get_binary, _, _}}, _) ->
999
erl_types:t_binary();
1000
type({hipe_bs_primop, {bs_get_binary_all, _}}, _) ->
1001
erl_types:t_binary();
1002
type({hipe_bs_primop, bs_final}, _) ->
1003
erl_types:t_binary();
1005
%%io:format("Don't have any information for ~w\n", [Op]),
1183
[gen_fail_code(FailLbl, badarith)]