1
%%% -*- erlang-indent-level: 2 -*-
4
-module(hipe_rtl_to_arm).
5
-export([translate/1]).
7
-include("../rtl/hipe_rtl.hrl").
10
hipe_gensym:init(arm),
11
hipe_gensym:set_var(arm, hipe_arm_registers:first_virtual()),
12
hipe_gensym:set_label(arm, hipe_gensym:get_label(rtl)),
14
{Formals, Map1} = conv_formals(hipe_rtl:rtl_params(RTL), Map0),
15
OldData = hipe_rtl:rtl_data(RTL),
16
{Code0, NewData} = conv_insn_list(hipe_rtl:rtl_code(RTL), Map1, OldData),
17
{RegFormals,_} = split_args(Formals),
21
_ -> [hipe_arm:mk_label(hipe_gensym:get_next_label(arm)) |
22
move_formals(RegFormals, Code0)]
24
IsClosure = hipe_rtl:rtl_is_closure(RTL),
25
IsLeaf = hipe_rtl:rtl_is_leaf(RTL),
26
hipe_arm:mk_defun(conv_mfa(hipe_rtl:rtl_fun(RTL)),
35
conv_insn_list([H|T], Map, Data) ->
36
{NewH, NewMap, NewData1} = conv_insn(H, Map, Data),
37
%% io:format("~w \n ==>\n ~w\n- - - - - - - - -\n",[H,NewH]),
38
{NewT, NewData2} = conv_insn_list(T, NewMap, NewData1),
39
{NewH ++ NewT, NewData2};
40
conv_insn_list([], _, Data) ->
43
conv_insn(I, Map, Data) ->
45
#alu{} -> conv_alu(I, Map, Data);
46
#alub{} -> conv_alub(I, Map, Data);
47
#branch{} -> conv_branch(I, Map, Data);
48
#call{} -> conv_call(I, Map, Data);
49
#comment{} -> conv_comment(I, Map, Data);
50
#enter{} -> conv_enter(I, Map, Data);
51
#goto{} -> conv_goto(I, Map, Data);
52
#label{} -> conv_label(I, Map, Data);
53
#load{} -> conv_load(I, Map, Data);
54
#load_address{} -> conv_load_address(I, Map, Data);
55
#load_atom{} -> conv_load_atom(I, Map, Data);
56
#move{} -> conv_move(I, Map, Data);
57
#return{} -> conv_return(I, Map, Data);
58
#store{} -> conv_store(I, Map, Data);
59
#switch{} -> conv_switch(I, Map, Data);
60
_ -> exit({?MODULE,conv_insn,I})
63
conv_alu(I, Map, Data) ->
64
%% dst = src1 aluop src2
65
{Dst, Map0} = conv_dst(hipe_rtl:alu_dst(I), Map),
66
{Src1, Map1} = conv_src(hipe_rtl:alu_src1(I), Map0),
67
{Src2, Map2} = conv_src(hipe_rtl:alu_src2(I), Map1),
68
RtlAluOp = hipe_rtl:alu_op(I),
70
I2 = mk_alu(S, Dst, Src1, RtlAluOp, Src2),
73
conv_shift(RtlShiftOp) ->
80
conv_arith(RtlAluOp) -> % RtlAluOp \ RtlShiftOp -> ArmArithOp
89
commute_arithop(ArithOp) ->
95
mk_alu(S, Dst, Src1, RtlAluOp, Src2) ->
96
case hipe_rtl:is_shift_op(RtlAluOp) of
98
mk_shift(S, Dst, Src1, conv_shift(RtlAluOp), Src2);
100
mk_arith(S, Dst, Src1, conv_arith(RtlAluOp), Src2)
103
mk_shift(S, Dst, Src1, ShiftOp, Src2) ->
104
case hipe_arm:is_temp(Src1) of
106
case hipe_arm:is_temp(Src2) of
108
mk_shift_rr(S, Dst, Src1, ShiftOp, Src2);
110
mk_shift_ri(S, Dst, Src1, ShiftOp, Src2)
113
case hipe_arm:is_temp(Src2) of
115
mk_shift_ir(S, Dst, Src1, ShiftOp, Src2);
117
mk_shift_ii(S, Dst, Src1, ShiftOp, Src2)
121
mk_shift_ii(S, Dst, Src1, ShiftOp, Src2) ->
122
io:format("~w: RTL alu with two immediates\n", [?MODULE]),
123
Tmp = new_untagged_temp(),
125
mk_shift_ri(S, Dst, Tmp, ShiftOp, Src2)).
127
mk_shift_ir(S, Dst, Src1, ShiftOp, Src2) ->
128
Tmp = new_untagged_temp(),
130
mk_shift_rr(S, Dst, Tmp, ShiftOp, Src2)).
132
mk_shift_ri(S, Dst, Src1, ShiftOp, Src2) ->
133
if Src2 >= 0, Src2 < 32 -> [];
134
true -> io:format("~w: excessive immediate shift ~w\n", [?MODULE,Src2])
136
Am1 = {Src1,ShiftOp,Src2},
137
[hipe_arm:mk_move(S, Dst, Am1)].
139
mk_shift_rr(S, Dst, Src1, ShiftOp, Src2) ->
140
Am1 = {Src1,ShiftOp,Src2},
141
[hipe_arm:mk_move(S, Dst, Am1)].
143
mk_arith(S, Dst, Src1, ArithOp, Src2) ->
144
case hipe_arm:is_temp(Src1) of
146
case hipe_arm:is_temp(Src2) of
148
mk_arith_rr(S, Dst, Src1, ArithOp, Src2);
150
mk_arith_ri(S, Dst, Src1, ArithOp, Src2)
153
case hipe_arm:is_temp(Src2) of
155
mk_arith_ir(S, Dst, Src1, ArithOp, Src2);
157
mk_arith_ii(S, Dst, Src1, ArithOp, Src2)
161
mk_arith_ii(S, Dst, Src1, ArithOp, Src2) ->
162
io:format("~w: RTL alu with two immediates\n", [?MODULE]),
163
Tmp = new_untagged_temp(),
165
mk_arith_ri(S, Dst, Tmp, ArithOp, Src2)).
167
mk_arith_ir(S, Dst, Src1, ArithOp, Src2) ->
168
mk_arith_ri(S, Dst, Src2, commute_arithop(ArithOp), Src1).
170
mk_arith_ri(S, Dst, Src1, ArithOp, Src2) ->
171
{FixAm1,NewArithOp,Am1} = fix_aluop_imm(ArithOp, Src2),
172
FixAm1 ++ [hipe_arm:mk_alu(NewArithOp, S, Dst, Src1, Am1)].
174
mk_arith_rr(S, Dst, Src1, ArithOp, Src2) ->
175
[hipe_arm:mk_alu(ArithOp, S, Dst, Src1, Src2)].
177
fix_aluop_imm(AluOp, Imm) -> % {FixAm1,NewAluOp,Am1}
178
case hipe_arm:try_aluop_imm(AluOp, Imm) of
179
{NewAluOp,Am1} -> {[], NewAluOp, Am1};
181
Tmp = new_untagged_temp(),
182
{mk_li(Tmp, Imm), AluOp, Tmp}
185
conv_alub(I, Map, Data) ->
186
%% dst = src1 aluop src2; if COND goto label
187
{Dst, Map0} = conv_dst(hipe_rtl:alub_dst(I), Map),
188
{Src1, Map1} = conv_src(hipe_rtl:alub_src1(I), Map0),
189
{Src2, Map2} = conv_src(hipe_rtl:alub_src2(I), Map1),
190
Cond = conv_alub_cond(hipe_rtl:alub_cond(I)),
193
hipe_rtl:alub_true_label(I),
194
hipe_rtl:alub_false_label(I),
195
hipe_rtl:alub_pred(I)),
196
RtlAluOp = hipe_rtl:alub_op(I),
198
I1 = mk_alu(S, Dst, Src1, RtlAluOp, Src2),
199
{I1 ++ I2, Map2, Data}.
201
conv_branch(I, Map, Data) ->
202
%% <unused> = src1 - src2; if COND goto label
203
{Src1, Map0} = conv_src(hipe_rtl:branch_src1(I), Map),
204
{Src2, Map1} = conv_src(hipe_rtl:branch_src2(I), Map0),
205
Cond = conv_branch_cond(hipe_rtl:branch_cond(I)),
206
I2 = mk_branch(Src1, Cond, Src2,
207
hipe_rtl:branch_true_label(I),
208
hipe_rtl:branch_false_label(I),
209
hipe_rtl:branch_pred(I)),
212
mk_branch(Src1, Cond, Src2, TrueLab, FalseLab, Pred) ->
213
case hipe_arm:is_temp(Src1) of
215
case hipe_arm:is_temp(Src2) of
217
mk_branch_rr(Src1, Src2, Cond, TrueLab, FalseLab, Pred);
219
mk_branch_ri(Src1, Cond, Src2, TrueLab, FalseLab, Pred)
222
case hipe_arm:is_temp(Src2) of
224
NewCond = commute_cond(Cond),
225
mk_branch_ri(Src2, NewCond, Src1, TrueLab, FalseLab, Pred);
227
mk_branch_ii(Src1, Cond, Src2, TrueLab, FalseLab, Pred)
231
mk_branch_ii(Imm1, Cond, Imm2, TrueLab, FalseLab, Pred) ->
232
io:format("~w: RTL branch with two immediates\n", [?MODULE]),
233
Tmp = new_untagged_temp(),
235
mk_branch_ri(Tmp, Cond, Imm2,
236
TrueLab, FalseLab, Pred)).
238
mk_branch_ri(Src, Cond, Imm, TrueLab, FalseLab, Pred) ->
239
{FixAm1,NewCmpOp,Am1} = fix_aluop_imm('cmp', Imm),
240
FixAm1 ++ mk_cmp_bc(NewCmpOp, Src, Am1, Cond, TrueLab, FalseLab, Pred).
242
mk_branch_rr(Src1, Src2, Cond, TrueLab, FalseLab, Pred) ->
243
mk_cmp_bc('cmp', Src1, Src2, Cond, TrueLab, FalseLab, Pred).
245
mk_cmp_bc(CmpOp, Src, Am1, Cond, TrueLab, FalseLab, Pred) ->
246
[hipe_arm:mk_cmp(CmpOp, Src, Am1) |
247
mk_pseudo_bc(Cond, TrueLab, FalseLab, Pred)].
249
conv_call(I, Map, Data) ->
250
{Args, Map0} = conv_src_list(hipe_rtl:call_arglist(I), Map),
251
{Dsts, Map1} = conv_dst_list(hipe_rtl:call_dstlist(I), Map0),
252
{Fun, Map2} = conv_fun(hipe_rtl:call_fun(I), Map1),
253
ContLab = hipe_rtl:call_continuation(I),
254
ExnLab = hipe_rtl:call_fail(I),
255
Linkage = hipe_rtl:call_type(I),
256
I2 = mk_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage),
259
mk_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage) ->
260
case hipe_arm:is_prim(Fun) of
262
mk_primop_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage);
264
mk_general_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage)
267
mk_primop_call(Dsts, Prim, Args, ContLab, ExnLab, Linkage) ->
268
case hipe_arm:prim_prim(Prim) of
269
%% no ARM-specific primops defined yet
271
mk_general_call(Dsts, Prim, Args, ContLab, ExnLab, Linkage)
274
mk_general_call(Dsts, Fun, Args, ContLab, ExnLab, Linkage) ->
275
%% The backend does not support pseudo_calls without a
276
%% continuation label, so we make sure each call has one.
277
{RealContLab, Tail} =
278
case mk_call_results(Dsts) of
280
%% Avoid consing up a dummy basic block if the moves list
281
%% is empty, as is typical for calls to suspend/0.
282
%% This should be subsumed by a general "optimise the CFG"
283
%% module, and could probably be removed.
286
NewContLab = hipe_gensym:get_next_label(arm),
287
{NewContLab, [hipe_arm:mk_label(NewContLab)]};
292
%% Change the call to continue at a new basic block.
293
%% In this block move the result registers to the Dsts,
294
%% then continue at the call's original continuation.
295
NewContLab = hipe_gensym:get_next_label(arm),
298
%% This is just a fallthrough
299
%% No jump back after the moves.
301
[hipe_arm:mk_label(NewContLab) |
304
%% The call has a continuation. Jump to it.
306
[hipe_arm:mk_label(NewContLab) |
308
[hipe_arm:mk_b_label(ContLab)]]}
311
SDesc = hipe_arm:mk_sdesc(ExnLab, 0, length(Args), {}),
312
CallInsn = hipe_arm:mk_pseudo_call(Fun, SDesc, RealContLab, Linkage),
313
{RegArgs,StkArgs} = split_args(Args),
314
mk_push_args(StkArgs, move_actuals(RegArgs, [CallInsn | Tail])).
316
mk_call_results([]) ->
318
mk_call_results([Dst]) ->
319
RV = hipe_arm:mk_temp(hipe_arm_registers:return_value(), 'tagged'),
320
[hipe_arm:mk_pseudo_move(Dst, RV)];
321
mk_call_results(Dsts) ->
322
exit({?MODULE,mk_call_results,Dsts}).
324
mk_push_args(StkArgs, Tail) ->
325
case length(StkArgs) of
329
[hipe_arm:mk_pseudo_call_prepare(NrStkArgs) |
330
mk_store_args(StkArgs, NrStkArgs * word_size(), Tail)]
333
mk_store_args([Arg|Args], PrevOffset, Tail) ->
334
Offset = PrevOffset - word_size(),
336
case hipe_arm:is_temp(Arg) of
340
Tmp = new_tagged_temp(),
341
{Tmp, mk_li(Tmp, Arg)}
343
NewTail = hipe_arm:mk_store('str', Src, mk_sp(), Offset, 'new', Tail),
344
mk_store_args(Args, Offset, FixSrc ++ NewTail);
345
mk_store_args([], _, Tail) ->
348
conv_comment(I, Map, Data) ->
349
I2 = [hipe_arm:mk_comment(hipe_rtl:comment_text(I))],
352
conv_enter(I, Map, Data) ->
353
{Args, Map0} = conv_src_list(hipe_rtl:enter_arglist(I), Map),
354
{Fun, Map1} = conv_fun(hipe_rtl:enter_fun(I), Map0),
355
I2 = mk_enter(Fun, Args, hipe_rtl:enter_type(I)),
358
mk_enter(Fun, Args, Linkage) ->
359
Arity = length(Args),
360
{RegArgs,StkArgs} = split_args(Args),
361
move_actuals(RegArgs,
362
[hipe_arm:mk_pseudo_tailcall_prepare(),
363
hipe_arm:mk_pseudo_tailcall(Fun, Arity, StkArgs, Linkage)]).
365
conv_goto(I, Map, Data) ->
366
I2 = [hipe_arm:mk_b_label(hipe_rtl:goto_label(I))],
369
conv_label(I, Map, Data) ->
370
I2 = [hipe_arm:mk_label(hipe_rtl:label_name(I))],
373
conv_load(I, Map, Data) ->
374
{Dst, Map0} = conv_dst(hipe_rtl:load_dst(I), Map),
375
{Base1, Map1} = conv_src(hipe_rtl:load_src(I), Map0),
376
{Base2, Map2} = conv_src(hipe_rtl:load_offset(I), Map1),
377
LoadSize = hipe_rtl:load_size(I),
378
LoadSign = hipe_rtl:load_sign(I),
379
I2 = mk_load(Dst, Base1, Base2, LoadSize, LoadSign),
382
mk_load(Dst, Base1, Base2, LoadSize, LoadSign) ->
383
case {LoadSize,LoadSign} of
385
case hipe_arm:is_temp(Base1) of
387
case hipe_arm:is_temp(Base2) of
389
mk_ldrsb_rr(Dst, Base1, Base2);
391
mk_ldrsb_ri(Dst, Base1, Base2)
394
case hipe_arm:is_temp(Base2) of
396
mk_ldrsb_ri(Dst, Base2, Base1);
398
mk_ldrsb_ii(Dst, Base1, Base2)
408
case hipe_arm:is_temp(Base1) of
410
case hipe_arm:is_temp(Base2) of
412
mk_load_rr(Dst, Base1, Base2, LdOp);
414
mk_load_ri(Dst, Base1, Base2, LdOp)
417
case hipe_arm:is_temp(Base2) of
419
mk_load_ri(Dst, Base2, Base1, LdOp);
421
mk_load_ii(Dst, Base1, Base2, LdOp)
426
mk_load_ii(Dst, Base1, Base2, LdOp) ->
427
io:format("~w: RTL load with two immediates\n", [?MODULE]),
428
Tmp = new_untagged_temp(),
430
mk_load_ri(Dst, Tmp, Base2, LdOp)).
432
mk_load_ri(Dst, Base, Offset, LdOp) ->
433
hipe_arm:mk_load(LdOp, Dst, Base, Offset, 'new', []).
435
mk_load_rr(Dst, Base1, Base2, LdOp) ->
436
Am2 = hipe_arm:mk_am2(Base1, '+', Base2),
437
[hipe_arm:mk_load(LdOp, Dst, Am2)].
439
mk_ldrsb_ii(Dst, Base1, Base2) ->
440
io:format("~w: RTL load signed byte with two immediates\n", [?MODULE]),
441
Tmp = new_untagged_temp(),
443
mk_ldrsb_ri(Dst, Tmp, Base2)).
445
mk_ldrsb_ri(Dst, Base, Offset) ->
447
if Offset < 0 -> {'-', -Offset};
448
true -> {'+', Offset}
450
if AbsOffset =< 255 ->
451
Am3 = hipe_arm:mk_am3(Base, Sign, AbsOffset),
452
[hipe_arm:mk_ldrsb(Dst, Am3)];
454
Index = new_untagged_temp(),
455
Am3 = hipe_arm:mk_am3(Base, Sign, Index),
456
[mk_li(Index, AbsOffset),
457
hipe_arm:mk_ldrsb(Dst, Am3)]
460
mk_ldrsb_rr(Dst, Base1, Base2) ->
461
Am3 = hipe_arm:mk_am3(Base1, '+', Base2),
462
[hipe_arm:mk_ldrsb(Dst, Am3)].
464
conv_load_address(I, Map, Data) ->
465
{Dst, Map0} = conv_dst(hipe_rtl:load_address_dst(I), Map),
466
Addr = hipe_rtl:load_address_address(I),
467
Type = hipe_rtl:load_address_type(I),
469
I2 = [hipe_arm:mk_pseudo_li(Dst, Src)],
472
conv_load_atom(I, Map, Data) ->
473
{Dst, Map0} = conv_dst(hipe_rtl:load_atom_dst(I), Map),
474
Src = hipe_rtl:load_atom_atom(I),
475
I2 = [hipe_arm:mk_pseudo_li(Dst, Src)],
478
conv_move(I, Map, Data) ->
479
{Dst, Map0} = conv_dst(hipe_rtl:move_dst(I), Map),
480
{Src, Map1} = conv_src(hipe_rtl:move_src(I), Map0),
481
I2 = mk_move(Dst, Src, []),
484
mk_move(Dst, Src, Tail) ->
485
case hipe_arm:is_temp(Src) of
486
true -> [hipe_arm:mk_pseudo_move(Dst, Src) | Tail];
487
_ -> mk_li(Dst, Src, Tail)
490
conv_return(I, Map, Data) ->
491
%% TODO: multiple-value returns
492
{[Arg], Map0} = conv_src_list(hipe_rtl:return_varlist(I), Map),
493
I2 = mk_move(mk_rv(), Arg,
494
[hipe_arm:mk_pseudo_blr()]),
497
conv_store(I, Map, Data) ->
498
{Base, Map0} = conv_dst(hipe_rtl:store_base(I), Map),
499
{Src, Map1} = conv_src(hipe_rtl:store_src(I), Map0),
500
{Offset, Map2} = conv_src(hipe_rtl:store_offset(I), Map1),
501
StoreSize = hipe_rtl:store_size(I),
502
I2 = mk_store(Src, Base, Offset, StoreSize),
505
mk_store(Src, Base, Offset, StoreSize) ->
512
case hipe_arm:is_temp(Src) of
514
mk_store2(Src, Base, Offset, StOp);
516
Tmp = new_untagged_temp(),
518
mk_store2(Tmp, Base, Offset, StOp))
521
mk_store2(Src, Base, Offset, StOp) ->
522
case hipe_arm:is_temp(Offset) of
524
mk_store_rr(Src, Base, Offset, StOp);
526
mk_store_ri(Src, Base, Offset, StOp)
529
mk_store_ri(Src, Base, Offset, StOp) ->
530
hipe_arm:mk_store(StOp, Src, Base, Offset, 'new', []).
532
mk_store_rr(Src, Base, Index, StOp) ->
533
Am2 = hipe_arm:mk_am2(Base, '+', Index),
534
[hipe_arm:mk_store(StOp, Src, Am2)].
536
conv_switch(I, Map, Data) ->
537
Labels = hipe_rtl:switch_labels(I),
538
LMap = [{label,L} || L <- Labels],
540
case hipe_rtl:switch_sort_order(I) of
542
hipe_consttab:insert_block(Data, word, LMap);
544
hipe_consttab:insert_sorted_block(
545
Data, word, LMap, SortOrder)
547
%% no immediates allowed here
548
{IndexR, Map1} = conv_dst(hipe_rtl:switch_src(I), Map),
549
JTabR = new_untagged_temp(),
551
[hipe_arm:mk_pseudo_li(JTabR, {JTabLab,constant}),
552
hipe_arm:mk_pseudo_switch(JTabR, IndexR, Labels)],
555
%%% Create a conditional branch.
557
mk_pseudo_bc(Cond, TrueLabel, FalseLabel, Pred) ->
558
[hipe_arm:mk_pseudo_bc(Cond, TrueLabel, FalseLabel, Pred)].
560
%%% Load an integer constant into a register.
562
mk_li(Dst, Value) -> mk_li(Dst, Value, []).
564
mk_li(Dst, Value, Tail) ->
565
hipe_arm:mk_li(Dst, Value, Tail).
567
%%% Convert an RTL condition code.
569
conv_alub_cond(Cond) -> % only signed
578
not_overflow -> 'vc';
579
_ -> exit({?MODULE,conv_alub_cond,Cond})
582
conv_branch_cond(Cond) -> % may be unsigned
588
_ -> conv_alub_cond(Cond)
591
%%% Commute an ARM condition code.
593
commute_cond(Cond) -> % if x Cond y, then y commute_cond(Cond) x
595
'eq' -> 'eq'; % ==, ==
596
'ne' -> 'ne'; % !=, !=
598
'ge' -> 'le'; % >=, <=
600
'le' -> 'ge'; % <=, >=
601
'hi' -> 'lo'; % >u, <u
602
'hs' -> 'ls'; % >=u, <=u
603
'lo' -> 'hi'; % <u, >u
604
'ls' -> 'hs'; % <=u, >=u
606
_ -> exit({?MODULE,commute_cond,Cond})
609
%%% Split a list of formal or actual parameters into the
610
%%% part passed in registers and the part passed on the stack.
611
%%% The parameters passed in registers are also tagged with
612
%%% the corresponding registers.
615
split_args(0, hipe_arm_registers:nr_args(), Args, []).
617
split_args(I, N, [Arg|Args], RegArgs) when I < N ->
618
Reg = hipe_arm_registers:arg(I),
619
Temp = hipe_arm:mk_temp(Reg, 'tagged'),
620
split_args(I+1, N, Args, [{Arg,Temp}|RegArgs]);
621
split_args(_, _, StkArgs, RegArgs) ->
624
%%% Convert a list of actual parameters passed in
625
%%% registers (from split_args/1) to a list of moves.
627
move_actuals([{Src,Dst}|Actuals], Rest) ->
628
move_actuals(Actuals, mk_move(Dst, Src, Rest));
629
move_actuals([], Rest) ->
632
%%% Convert a list of formal parameters passed in
633
%%% registers (from split_args/1) to a list of moves.
635
move_formals([{Dst,Src}|Formals], Rest) ->
636
move_formals(Formals, [hipe_arm:mk_pseudo_move(Dst, Src) | Rest]);
637
move_formals([], Rest) ->
640
%%% Convert a 'fun' operand (MFA, prim, or temp)
642
conv_fun(Fun, Map) ->
643
case hipe_rtl:is_var(Fun) of
647
case hipe_rtl:is_reg(Fun) of
652
{hipe_arm:mk_prim(Fun), Map};
659
%%% Convert an MFA operand.
661
conv_mfa({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->
662
hipe_arm:mk_mfa(M, F, A).
664
%%% Convert an RTL source operand (imm/var/reg).
665
%%% Returns a temp or a naked integer.
667
conv_src(Opnd, Map) ->
668
case hipe_rtl:is_imm(Opnd) of
670
Value = hipe_rtl:imm_value(Opnd),
671
if is_integer(Value) ->
678
conv_src_list([O|Os], Map) ->
679
{V, Map1} = conv_src(O, Map),
680
{Vs, Map2} = conv_src_list(Os, Map1),
682
conv_src_list([], Map) ->
685
%%% Convert an RTL destination operand (var/reg).
687
conv_dst(Opnd, Map) ->
689
case hipe_rtl:is_var(Opnd) of
691
{hipe_rtl:var_index(Opnd), 'tagged'};
693
case hipe_rtl:is_fpreg(Opnd) of
695
{hipe_rtl:fpreg_index(Opnd), 'double'};
697
{hipe_rtl:reg_index(Opnd), 'untagged'}
702
'double' -> false; %hipe_arm_registers:is_precoloured_fpr(Name);
703
_ -> hipe_arm_registers:is_precoloured_gpr(Name)
705
case IsPrecoloured of
707
{hipe_arm:mk_temp(Name, Type), Map};
709
case vmap_lookup(Map, Opnd) of
713
NewTemp = hipe_arm:mk_new_temp(Type),
714
{NewTemp, vmap_bind(Map, Opnd, NewTemp)}
718
conv_dst_list([O|Os], Map) ->
719
{Dst, Map1} = conv_dst(O, Map),
720
{Dsts, Map2} = conv_dst_list(Os, Map1),
722
conv_dst_list([], Map) ->
725
conv_formals(Os, Map) ->
726
conv_formals(hipe_arm_registers:nr_args(), Os, Map, []).
728
conv_formals(N, [O|Os], Map, Res) ->
730
case hipe_rtl:is_var(O) of
735
if N > 0 -> hipe_arm:mk_new_temp(Type); % allocatable
736
true -> hipe_arm:mk_new_nonallocatable_temp(Type)
738
Map1 = vmap_bind(Map, O, Dst),
739
conv_formals(N-1, Os, Map1, [Dst|Res]);
740
conv_formals(_, [], Map, Res) ->
741
{lists:reverse(Res), Map}.
743
%%% Create a temp representing the stack pointer register.
746
hipe_arm:mk_temp(hipe_arm_registers:stack_pointer(), 'untagged').
748
%%% Create a temp representing the return value register.
751
hipe_arm:mk_temp(hipe_arm_registers:return_value(), 'tagged').
753
%%% new_untagged_temp -- conjure up an untagged scratch reg
755
new_untagged_temp() ->
756
hipe_arm:mk_new_temp('untagged').
758
%%% new_tagged_temp -- conjure up a tagged scratch reg
761
hipe_arm:mk_new_temp('tagged').
763
%%% Map from RTL var/reg operands to temps.
768
vmap_lookup(Map, Key) ->
769
gb_trees:lookup(Key, Map).
771
vmap_bind(Map, Key, Val) ->
772
gb_trees:insert(Key, Val, Map).