86
104
module(BeamFuns, Options) ->
87
105
BeamCode0 = [beam_disasm:function__code(F) || F <- BeamFuns],
88
BeamCode1 = exclude_module_info_code(BeamCode0, []),
89
{ModCode, ClosureInfo} = preprocess_code(BeamCode1),
106
{ModCode, ClosureInfo} = preprocess_code(BeamCode0),
90
107
pp_beam(ModCode, Options),
91
108
[trans_beam_function_chunk(FunCode, ClosureInfo) || FunCode <- ModCode].
93
110
trans_beam_function_chunk(FunBeamCode, ClosureInfo) ->
94
{M,F,A} = find_mfa(FunBeamCode),
111
{M,F,A} = MFA = find_mfa(FunBeamCode),
95
112
Icode = trans_mfa_code(M,F,A, FunBeamCode, ClosureInfo),
98
%%-----------------------------------------------------------------------
99
%% The code chunks of module_info/[0,1] are excluded from the
100
%% compilation to native code, since they are just dummy stubs.
101
%% It is the BEAM loader that creates their real code, and HiPE relies
102
%% on it to generate proper code for module_info/[0,1].
103
%%-----------------------------------------------------------------------
105
exclude_module_info_code([FunCode|FunCodes], Acc) ->
107
[{label,L},{label,_},{func_info,M,F,A}|Insns] ->
108
NewFunCode = [{label,L},{func_info,M,F,A}|Insns],
109
exclude_module_info_code([NewFunCode|FunCodes], Acc);
110
[{label,_},{func_info,_,{atom,module_info},A}|_] when A =:= 0; A =:= 1->
111
exclude_module_info_code(FunCodes, Acc);
113
exclude_module_info_code(FunCodes, [FunCode|Acc])
115
exclude_module_info_code([], Acc) ->
118
115
%%-----------------------------------------------------------------------
194
190
true -> [mk_redtest()|Code3]
196
IsClosure = case get_closure_info({M,F,A}, ClosureInfo) of
197
not_a_closure -> false;
200
Code5 = hipe_icode:mk_icode({M,F,A}, FunArgs, IsClosure, IsLeaf,
192
IsClosure = get_closure_info(MFA, ClosureInfo) =/= not_a_closure,
193
Code5 = hipe_icode:mk_icode(MFA, FunArgs, IsClosure, IsLeaf,
201
194
remove_dead_code(Code4),
202
195
hipe_gensym:var_range(icode),
203
196
hipe_gensym:label_range(icode)),
204
197
Icode = %% If this function is the code for a closure ...
205
case get_closure_info({M,F,A}, ClosureInfo) of
198
case get_closure_info(MFA, ClosureInfo) of
206
199
not_a_closure -> Code5;
207
200
CI -> %% ... then patch the code to
208
201
%% get the free_vars from the closure
317
310
[mk_label(L) | trans_fun(Instructions, Env)];
318
311
%%--- int_code_end --- SHOULD NEVER OCCUR HERE
320
trans_fun([{call,_N,MFA={_M,_F,A}}|Instructions], Env) ->
313
trans_fun([{call,_N,{_M,_F,A}=MFA}|Instructions], Env) ->
321
314
Args = extract_fun_args(A),
322
315
Dst = [mk_var({r,0})],
323
I = trans_call(MFA,Dst,Args,local),
324
[I | trans_fun(Instructions,Env)];
316
I = trans_call(MFA, Dst, Args, local),
317
[I | trans_fun(Instructions, Env)];
325
318
%%--- call_last ---
326
319
%% Differs from call_only in that it deallocates the environment
327
trans_fun([{call_last,_N,MFA={M,F,A},_}|Instructions], Env) ->
320
trans_fun([{call_last,_N,{_M,_F,A}=MFA,_}|Instructions], Env) ->
328
321
%% IS IT OK TO IGNORE LAST ARG ??
329
322
?no_debug_msg(" translating call_last: ~p ...~n", [Env]),
330
323
case env__get_mfa(Env) of
332
325
%% Does this case really happen, or is it covered by call_only?
333
326
Entry = env__get_entry(Env),
334
327
[hipe_icode:mk_comment('tail_recursive'), % needed by leafness/2
335
328
hipe_icode:mk_goto(Entry) | trans_fun(Instructions,Env)];
337
330
Args = extract_fun_args(A),
338
I = trans_enter(MFA,Args,local),
339
[I | trans_fun(Instructions,Env)]
331
I = trans_enter(MFA, Args, local),
332
[I | trans_fun(Instructions, Env)]
341
334
%%--- call_only ---
342
335
%% Used when the body contains only one call in which case
343
336
%% an environment is not needed/created.
344
trans_fun([{call_only,_N,MFA={_M,_F,A}}|Instructions], Env) ->
337
trans_fun([{call_only,_N,{_M,_F,A}=MFA}|Instructions], Env) ->
345
338
?no_debug_msg(" translating call_only: ~p ...~n", [Env]),
346
339
case env__get_mfa(Env) of
523
516
{Code,Env1} = trans_type_test(cons,Lbl,Arg,Env),
524
517
[Code | trans_fun(Instructions,Env1)];
525
518
%%--- is_tuple ---
526
trans_fun([{test,is_tuple,{f,Lbl},[Xreg]},
527
{test,test_arity,{f,Lbl},[Xreg,_]=Args}|Instructions], Env) ->
528
trans_fun([{test,test_arity,{f,Lbl},Args}|Instructions],Env);
519
trans_fun([{test,is_tuple,{f,_Lbl}=FLbl,[Xreg]},
520
{test,test_arity,FLbl,[Xreg,_]=Args}|Instructions], Env) ->
521
trans_fun([{test,test_arity,FLbl,Args}|Instructions],Env);
529
522
trans_fun([{test,is_tuple,{_,Lbl},[Arg]}|Instructions], Env) ->
530
523
{Code,Env1} = trans_type_test(tuple,Lbl,Arg,Env),
531
524
[Code | trans_fun(Instructions,Env1)];
575
568
trans_fun([{try_end,_N}|Instructions], Env) ->
576
569
[hipe_icode:mk_end_try() | trans_fun(Instructions,Env)];
577
570
%%--- try_case --- ITS PROCESSING IS POSTPONED
578
trans_fun([{try_case,N}|Instructions], Env) ->
579
[{try_case,N} | trans_fun(Instructions,Env)];
571
trans_fun([{try_case,_N}=I|Instructions], Env) ->
572
[I | trans_fun(Instructions,Env)];
580
573
%%--- try_case_end ---
581
574
trans_fun([{try_case_end,Arg}|Instructions], Env) ->
582
575
BadArg = trans_arg(Arg),
583
576
ErrVar = mk_var(new),
585
578
Atom = hipe_icode:mk_move(ErrVar,hipe_icode:mk_const(try_clause)),
586
Tuple = hipe_icode:mk_primop([V],mktuple,[ErrVar,BadArg]),
587
Fail = hipe_icode:mk_fail([V],error),
579
Tuple = hipe_icode:mk_primop(Vs,mktuple,[ErrVar,BadArg]),
580
Fail = hipe_icode:mk_fail(Vs,error),
588
581
[Atom,Tuple,Fail | trans_fun(Instructions,Env)];
590
583
trans_fun([{raise,{f,0},[Reg1,Reg2],{x,0}}|Instructions], Env) ->
594
587
[Fail | trans_fun(Instructions,Env)];
595
588
%%--- get_list ---
596
589
trans_fun([{get_list,List,Head,Tail}|Instructions], Env) ->
597
I1 = hipe_icode:mk_primop([mk_var(Head)],unsafe_hd,[trans_arg(List)]),
598
I2 = hipe_icode:mk_primop([mk_var(Tail)],unsafe_tl,[trans_arg(List)]),
590
TransList = [trans_arg(List)],
591
I1 = hipe_icode:mk_primop([mk_var(Head)],unsafe_hd,TransList),
592
I2 = hipe_icode:mk_primop([mk_var(Tail)],unsafe_tl,TransList),
599
593
%% Handle the cases where the dest overwrites the src!!
602
596
[I1, I2 | trans_fun(Instructions,Env)];
604
598
[I2, I1 | trans_fun(Instructions,Env)];
606
600
%% XXX: We should take care of this case!!!!!
838
832
[IcodeDst,Base,Offset],
839
833
Base, Offset, Env, Instructions);
840
834
trans_fun([bs_init_writable|Instructions], Env) ->
841
Var = mk_var({x,0}), %{x,0} is implict arg and dst
842
[hipe_icode:mk_primop([Var],{hipe_bs_primop,bs_init_writable},[Var]),
835
Vars = [mk_var({x,0})], %{x,0} is implict arg and dst
836
[hipe_icode:mk_primop(Vars,{hipe_bs_primop,bs_init_writable},Vars),
843
837
trans_fun(Instructions, Env)];
844
trans_fun([{bs_save2,Ms,IndexName}| Instructions], Env) ->
838
trans_fun([{bs_save2,Ms,IndexName}|Instructions], Env) ->
846
840
case IndexName of
847
841
{atom, start} -> 0;
851
[hipe_icode:mk_primop([MsVar],{hipe_bs_primop,{bs_save,Index}},[MsVar]) |
844
MsVars = [mk_var(Ms)],
845
[hipe_icode:mk_primop(MsVars,{hipe_bs_primop,{bs_save,Index}},MsVars) |
852
846
trans_fun(Instructions, Env)];
853
847
trans_fun([{bs_restore2,Ms,IndexName}|Instructions], Env) ->
951
945
MultIs ++ IsPos ++ [AddI|trans_fun(Instructions, Env)];
952
946
%%--------------------------------------------------------------------
953
%% Bit syntax instructions added in R12B-5 (Fall 2008) - PER PLEASE FIX
947
%% Bit syntax instructions added in R12B-5 (Fall 2008)
954
948
%%--------------------------------------------------------------------
955
%%trans_fun([{test,bs_get_utf8,{f,Lbl},[A1,A2,FF,A4]}|Instructions], Env) ->
956
%%trans_fun([{test,bs_skip_utf8,{f,Lbl},[A1,A2,FF]}|Instructions], Env) ->
957
%%trans_fun([{test,bs_get_utf16,{f,Lbl},[A1,A2,FF,A4]}|Instructions], Env) ->
958
%%trans_fun([{test,bs_skip_utf16,{f,Lbl},[A1,A2,FF]}|Instructions], Env) ->
959
%%trans_fun([{test,bs_get_utf32,{f,Lbl},[A1,A2,FF,A4]}|Instructions], Env) ->
960
%%trans_fun([{test,bs_skip_utf32,{f,Lbl},[A1,A2,FF]}|Instructions], Env) ->
961
%%trans_fun([{bs_utf8_size,{f,Lbl},A2,A3}|Instructions], Env) ->
962
%%trans_fun([{bs_put_utf8,{f,Lbl},FF,A3}|Instructions], Env) ->
963
%%trans_fun([{bs_utf16_size,{f,Lbl},A2,A3}|Instructions], Env) ->
964
%%trans_fun([{bs_put_utf16,{f,Lbl},FF,A3}|Instructions], Env) ->
965
%%trans_fun([{bs_put_utf32,{f,Lbl},FF,A3}|Instructions], Env) ->
949
trans_fun([{bs_utf8_size,{f,Lbl},A2,A3}|Instructions], Env) ->
952
trans_op_call({hipe_bs_primop, bs_utf8_size}, Lbl, [Bin], [Dst], Env, Instructions);
953
trans_fun([{test,bs_get_utf8,{f,Lbl},[Ms,_Live,{field_flags,_Flags},X]} |
954
Instructions], Env) ->
955
trans_bs_get_or_skip_utf8(Lbl, Ms, X, Instructions, Env);
956
trans_fun([{test,bs_skip_utf8,{f,Lbl},[Ms,_Live,{field_flags,_Flags}]} |
957
Instructions], Env) ->
958
trans_bs_get_or_skip_utf8(Lbl, Ms, 'new', Instructions, Env);
959
trans_fun([{bs_utf16_size,{f,Lbl},A2,A3}|Instructions], Env) ->
962
trans_op_call({hipe_bs_primop, bs_utf16_size}, Lbl, [Bin], [Dst], Env, Instructions);
963
trans_fun([{test,bs_get_utf16,{f,Lbl},[Ms,_Live,{field_flags,Flags0},X]} |
964
Instructions], Env) ->
965
trans_bs_get_or_skip_utf16(Lbl, Ms, Flags0, X, Instructions, Env);
966
trans_fun([{test,bs_skip_utf16,{f,Lbl},[Ms,_Live,{field_flags,Flags0}]} |
967
Instructions], Env) ->
968
trans_bs_get_or_skip_utf16(Lbl, Ms, Flags0, 'new', Instructions, Env);
969
trans_fun([{test,bs_get_utf32,{f,Lbl},[Ms,_Live,{field_flags,Flags0},X]} | Instructions], Env) ->
970
trans_bs_get_or_skip_utf32(Lbl, Ms, Flags0, X, Instructions, Env);
971
trans_fun([{test,bs_skip_utf32,{f,Lbl},[Ms,_Live,{field_flags,Flags0}]} | Instructions], Env) ->
972
trans_bs_get_or_skip_utf32(Lbl, Ms, Flags0, 'new', Instructions, Env);
966
973
%%--------------------------------------------------------------------
967
974
%%--- Translation of floating point instructions ---
968
975
%%--------------------------------------------------------------------
1339
1346
SrcInstrs ++ trans_bin_call({hipe_bs_primop, Name},
1340
1347
Lbl, [Src|Args], [Offset], Base, Offset, Env2, Instructions);
1348
%%----------------------------------------------------------------
1349
%% New binary construction instructions added in R12B-5 (Fall 2008).
1350
%%----------------------------------------------------------------
1351
trans_bin([{bs_put_utf8,{f,Lbl},_FF,A3}|Instructions], Base, Offset, Env) ->
1352
Src = trans_arg(A3),
1353
Args = [Src, Base, Offset],
1354
trans_bin_call({hipe_bs_primop, bs_put_utf8}, Lbl, Args, [Offset], Base, Offset, Env, Instructions);
1355
trans_bin([{bs_put_utf16,{f,Lbl},{field_flags,Flags0},A3}|Instructions], Base, Offset, Env) ->
1356
Src = trans_arg(A3),
1357
Args = [Src, Base, Offset],
1358
Flags = resolve_native_endianess(Flags0),
1359
Name = {bs_put_utf16, Flags},
1360
trans_bin_call({hipe_bs_primop, Name}, Lbl, Args, [Offset], Base, Offset, Env, Instructions);
1361
trans_bin([{bs_put_utf32,F={f,Lbl},FF={field_flags,_Flags0},A3}|Instructions], Base, Offset, Env) ->
1362
Src = trans_arg(A3),
1363
trans_bin_call({hipe_bs_primop,bs_validate_unicode}, Lbl, [Src], [], Base, Offset, Env,
1364
[{bs_put_integer,F,{integer,32},1,FF,A3} | Instructions]);
1365
%%----------------------------------------------------------------
1366
%% Base cases for the end of a binary construction sequence.
1367
%%----------------------------------------------------------------
1341
1368
trans_bin([{bs_final2,Src,Dst}|Instructions], _Base, Offset, Env) ->
1342
1369
[hipe_icode:mk_primop([mk_var(Dst)], {hipe_bs_primop, bs_final},
1343
1370
[trans_arg(Src),Offset])
1345
1372
trans_bin(Instructions, _Base, _Offset, Env) ->
1346
1373
trans_fun(Instructions, Env).
1375
%% this translates bs_get_utf8 and bs_skip_utf8 (get with new unused dst)
1376
trans_bs_get_or_skip_utf8(Lbl, Ms, X, Instructions, Env) ->
1379
trans_op_call({hipe_bs_primop,bs_get_utf8}, Lbl, [MsVar], [Dst,MsVar], Env, Instructions).
1381
%% this translates bs_get_utf16 and bs_skip_utf16 (get with new unused dst)
1382
trans_bs_get_or_skip_utf16(Lbl, Ms, Flags0, X, Instructions, Env) ->
1385
Flags = resolve_native_endianess(Flags0),
1386
Name = {bs_get_utf16,Flags},
1387
trans_op_call({hipe_bs_primop,Name}, Lbl, [MsVar], [Dst,MsVar], Env, Instructions).
1389
%% this translates bs_get_utf32 and bs_skip_utf32 (get with new unused dst)
1390
trans_bs_get_or_skip_utf32(Lbl, Ms, Flags0, X, Instructions, Env) ->
1393
Flags = resolve_native_endianess(Flags0),
1394
{I1,Env1} = trans_one_op_call({hipe_bs_primop,{bs_get_integer,32,Flags}},
1395
Lbl, [MsVar], [Dst,MsVar], Env),
1396
I1 ++ trans_op_call({hipe_bs_primop,bs_validate_unicode_retract},
1397
Lbl, [Dst,MsVar], [MsVar], Env1, Instructions).
1349
1399
%%-----------------------------------------------------------------------
1350
1400
%% trans_arith(Op, SrcVars, Des, Lab, Env) -> { Icode, NewEnv }