1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2012-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% Purpose: Run directly after code generation to do any normalization 21%% or preparation to simplify the optimization passes. 22%% (Mandatory.) 23 24-module(beam_a). 25 26-export([module/2]). 27 28-spec module(beam_asm:module_code(), [compile:option()]) -> 29 {'ok',beam_utils:module_code()}. 30 31module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> 32 Fs = [function(F) || F <- Fs0], 33 {ok,{Mod,Exp,Attr,Fs,Lc}}. 34 35function({function,Name,Arity,CLabel,Is0}) -> 36 try 37 %% Rename certain operations to simplify the optimization passes. 38 Is1 = rename_instrs(Is0), 39 40 %% Remove unusued labels for cleanliness and to help 41 %% optimization passes and HiPE. 42 Is = beam_jump:remove_unused_labels(Is1), 43 {function,Name,Arity,CLabel,Is} 44 catch 45 Class:Error:Stack -> 46 io:fwrite("Function: ~w/~w\n", [Name,Arity]), 47 erlang:raise(Class, Error, Stack) 48 end. 49 50rename_instrs([{apply_last,A,N}|Is]) -> 51 [{apply,A},{deallocate,N},return|rename_instrs(Is)]; 52rename_instrs([{call_last,A,F,N}|Is]) -> 53 [{call,A,F},{deallocate,N},return|rename_instrs(Is)]; 54rename_instrs([{call_ext_last,A,F,N}|Is]) -> 55 [{call_ext,A,F},{deallocate,N},return|rename_instrs(Is)]; 56rename_instrs([{call_only,A,F}|Is]) -> 57 [{call,A,F},return|rename_instrs(Is)]; 58rename_instrs([{call_ext_only,A,F}|Is]) -> 59 [{call_ext,A,F},return|rename_instrs(Is)]; 60rename_instrs([{'%live',_}|Is]) -> 61 %% Ignore old type of live annotation. Only happens when compiling 62 %% from very old .S files. 63 rename_instrs(Is); 64rename_instrs([{get_list,S,D1,D2}|Is]) -> 65 %% Only happens when compiling from old .S files. 66 if 67 D1 =:= S -> 68 [{get_tl,S,D2},{get_hd,S,D1}|rename_instrs(Is)]; 69 true -> 70 [{get_hd,S,D1},{get_tl,S,D2}|rename_instrs(Is)] 71 end; 72rename_instrs([I|Is]) -> 73 [rename_instr(I)|rename_instrs(Is)]; 74rename_instrs([]) -> []. 75 76rename_instr({bs_put_binary=I,F,Sz,U,Fl,Src}) -> 77 {bs_put,F,{I,U,Fl},[Sz,Src]}; 78rename_instr({bs_put_float=I,F,Sz,U,Fl,Src}) -> 79 {bs_put,F,{I,U,Fl},[Sz,Src]}; 80rename_instr({bs_put_integer=I,F,Sz,U,Fl,Src}) -> 81 {bs_put,F,{I,U,Fl},[Sz,Src]}; 82rename_instr({bs_put_utf8=I,F,Fl,Src}) -> 83 {bs_put,F,{I,Fl},[Src]}; 84rename_instr({bs_put_utf16=I,F,Fl,Src}) -> 85 {bs_put,F,{I,Fl},[Src]}; 86rename_instr({bs_put_utf32=I,F,Fl,Src}) -> 87 {bs_put,F,{I,Fl},[Src]}; 88rename_instr({bs_put_string,_,_}=I) -> 89 {bs_put,{f,0},I,[]}; 90rename_instr({bs_add=I,F,[Src1,Src2,U],Dst}) when is_integer(U) -> 91 {bif,I,F,[Src1,Src2,{integer,U}],Dst}; 92rename_instr({bs_utf8_size=I,F,Src,Dst}) -> 93 {bif,I,F,[Src],Dst}; 94rename_instr({bs_utf16_size=I,F,Src,Dst}) -> 95 {bif,I,F,[Src],Dst}; 96rename_instr({bs_init2=I,F,Sz,Extra,Live,Flags,Dst}) -> 97 {bs_init,F,{I,Extra,Flags},Live,[Sz],Dst}; 98rename_instr({bs_init_bits=I,F,Sz,Extra,Live,Flags,Dst}) -> 99 {bs_init,F,{I,Extra,Flags},Live,[Sz],Dst}; 100rename_instr({bs_append=I,F,Sz,Extra,Live,U,Src,Flags,Dst}) -> 101 {bs_init,F,{I,Extra,U,Flags},Live,[Sz,Src],Dst}; 102rename_instr({bs_private_append=I,F,Sz,U,Src,Flags,Dst}) -> 103 {bs_init,F,{I,U,Flags},none,[Sz,Src],Dst}; 104rename_instr(bs_init_writable=I) -> 105 {bs_init,{f,0},I,1,[{x,0}],{x,0}}; 106rename_instr({test,Op,F,[Ctx,Bits,{string,Str}]}) -> 107 %% When compiling from a .S file. 108 <<Bs:Bits/bits,_/bits>> = list_to_binary(Str), 109 {test,Op,F,[Ctx,Bs]}; 110rename_instr({put_map_assoc,Fail,S,D,R,L}) -> 111 {put_map,Fail,assoc,S,D,R,L}; 112rename_instr({put_map_exact,Fail,S,D,R,L}) -> 113 {put_map,Fail,exact,S,D,R,L}; 114rename_instr({test,has_map_fields,Fail,Src,{list,List}}) -> 115 {test,has_map_fields,Fail,[Src|List]}; 116rename_instr({select_val=I,Reg,Fail,{list,List}}) -> 117 {select,I,Reg,Fail,List}; 118rename_instr({select_tuple_arity=I,Reg,Fail,{list,List}}) -> 119 {select,I,Reg,Fail,List}; 120rename_instr(send) -> 121 {call_ext,2,send}; 122rename_instr(I) -> I. 123