hipe_rtl_to_arm.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 805 行 · 第 1/2 页

ERL
805
字号
  {Base1, Map1} = conv_src(hipe_rtl:load_src(I), Map0),  {Base2, Map2} = conv_src(hipe_rtl:load_offset(I), Map1),  LoadSize = hipe_rtl:load_size(I),  LoadSign = hipe_rtl:load_sign(I),  I2 = mk_load(Dst, Base1, Base2, LoadSize, LoadSign),  {I2, Map2, Data}.mk_load(Dst, Base1, Base2, LoadSize, LoadSign) ->  case {LoadSize,LoadSign} of    {byte,signed} ->      case hipe_arm:is_temp(Base1) of	true ->	  case hipe_arm:is_temp(Base2) of	    true ->	      mk_ldrsb_rr(Dst, Base1, Base2);	    _ ->	      mk_ldrsb_ri(Dst, Base1, Base2)	  end;	_ ->	  case hipe_arm:is_temp(Base2) of	    true ->	      mk_ldrsb_ri(Dst, Base2, Base1);	    _ ->	      mk_ldrsb_ii(Dst, Base1, Base2)	  end      end;    _ ->      LdOp =	case LoadSize of	  byte -> 'ldrb';	  int32 -> 'ldr';	  word -> 'ldr'	end,      case hipe_arm:is_temp(Base1) of	true ->	  case hipe_arm:is_temp(Base2) of	    true ->	      mk_load_rr(Dst, Base1, Base2, LdOp);	    _ ->	      mk_load_ri(Dst, Base1, Base2, LdOp)	  end;	_ ->	  case hipe_arm:is_temp(Base2) of	    true ->	      mk_load_ri(Dst, Base2, Base1, LdOp);	    _ ->	      mk_load_ii(Dst, Base1, Base2, LdOp)	  end      end  end.mk_load_ii(Dst, Base1, Base2, LdOp) ->  io:format("~w: RTL load with two immediates\n", [?MODULE]),  Tmp = new_untagged_temp(),  mk_li(Tmp, Base1,	mk_load_ri(Dst, Tmp, Base2, LdOp)).   mk_load_ri(Dst, Base, Offset, LdOp) ->  hipe_arm:mk_load(LdOp, Dst, Base, Offset, 'new', []).mk_load_rr(Dst, Base1, Base2, LdOp) ->  Am2 = hipe_arm:mk_am2(Base1, '+', Base2),  [hipe_arm:mk_load(LdOp, Dst, Am2)].mk_ldrsb_ii(Dst, Base1, Base2) ->  io:format("~w: RTL load signed byte with two immediates\n", [?MODULE]),  Tmp = new_untagged_temp(),  mk_li(Tmp, Base1,	mk_ldrsb_ri(Dst, Tmp, Base2)).   mk_ldrsb_ri(Dst, Base, Offset) when is_integer(Offset) ->  {Sign,AbsOffset} =    if Offset < 0 -> {'-', -Offset};       true -> {'+', Offset}    end,  if AbsOffset =< 255 ->      Am3 = hipe_arm:mk_am3(Base, Sign, AbsOffset),      [hipe_arm:mk_ldrsb(Dst, Am3)];     true ->      Index = new_untagged_temp(),      Am3 = hipe_arm:mk_am3(Base, Sign, Index),      mk_li(Index, AbsOffset,	    [hipe_arm:mk_ldrsb(Dst, Am3)])  end.mk_ldrsb_rr(Dst, Base1, Base2) ->  Am3 = hipe_arm:mk_am3(Base1, '+', Base2),  [hipe_arm:mk_ldrsb(Dst, Am3)].conv_load_address(I, Map, Data) ->  {Dst, Map0} = conv_dst(hipe_rtl:load_address_dst(I), Map),  Addr = hipe_rtl:load_address_address(I),  Type = hipe_rtl:load_address_type(I),  Src = {Addr,Type},  I2 = [hipe_arm:mk_pseudo_li(Dst, Src)],  {I2, Map0, Data}.conv_load_atom(I, Map, Data) ->  {Dst, Map0} = conv_dst(hipe_rtl:load_atom_dst(I), Map),  Src = hipe_rtl:load_atom_atom(I),  I2 = [hipe_arm:mk_pseudo_li(Dst, Src)],  {I2, Map0, Data}.conv_move(I, Map, Data) ->  {Dst, Map0} = conv_dst(hipe_rtl:move_dst(I), Map),  {Src, Map1} = conv_src(hipe_rtl:move_src(I), Map0),  I2 = mk_move(Dst, Src, []),  {I2, Map1, Data}.mk_move(Dst, Src, Tail) ->  case hipe_arm:is_temp(Src) of    true -> [hipe_arm:mk_pseudo_move(Dst, Src) | Tail];    _ -> mk_li(Dst, Src, Tail)  end.conv_return(I, Map, Data) ->  %% TODO: multiple-value returns  {[Arg], Map0} = conv_src_list(hipe_rtl:return_varlist(I), Map),  I2 = mk_move(mk_rv(), Arg,	       [hipe_arm:mk_pseudo_blr()]),  {I2, Map0, Data}.conv_store(I, Map, Data) ->  {Base, Map0} = conv_dst(hipe_rtl:store_base(I), Map),  {Src, Map1} = conv_src(hipe_rtl:store_src(I), Map0),  {Offset, Map2} = conv_src(hipe_rtl:store_offset(I), Map1),  StoreSize = hipe_rtl:store_size(I),  I2 = mk_store(Src, Base, Offset, StoreSize),  {I2, Map2, Data}.mk_store(Src, Base, Offset, StoreSize) ->  StOp =    case StoreSize of      byte -> 'strb';      int32 -> 'str';      word -> 'str'    end,  case hipe_arm:is_temp(Src) of    true ->      mk_store2(Src, Base, Offset, StOp);    _ ->      Tmp = new_untagged_temp(),      mk_li(Tmp, Src,	    mk_store2(Tmp, Base, Offset, StOp))  end.mk_store2(Src, Base, Offset, StOp) ->  case hipe_arm:is_temp(Offset) of    true ->      mk_store_rr(Src, Base, Offset, StOp);    _ ->      mk_store_ri(Src, Base, Offset, StOp)  end.  mk_store_ri(Src, Base, Offset, StOp) ->  hipe_arm:mk_store(StOp, Src, Base, Offset, 'new', []).   mk_store_rr(Src, Base, Index, StOp) ->  Am2 = hipe_arm:mk_am2(Base, '+', Index),  [hipe_arm:mk_store(StOp, Src, Am2)].conv_switch(I, Map, Data) ->  Labels = hipe_rtl:switch_labels(I),  LMap = [{label,L} || L <- Labels],  {NewData, JTabLab} =    case hipe_rtl:switch_sort_order(I) of      [] ->	hipe_consttab:insert_block(Data, word, LMap);      SortOrder ->	hipe_consttab:insert_sorted_block(	  Data, word, LMap, SortOrder)    end,  %% no immediates allowed here  {IndexR, Map1} = conv_dst(hipe_rtl:switch_src(I), Map),  JTabR = new_untagged_temp(),  I2 =    [hipe_arm:mk_pseudo_li(JTabR, {JTabLab,constant}),     hipe_arm:mk_pseudo_switch(JTabR, IndexR, Labels)],  {I2, Map1, NewData}.%%% Create a conditional branch.mk_pseudo_bc(Cond, TrueLabel, FalseLabel, Pred) ->  [hipe_arm:mk_pseudo_bc(Cond, TrueLabel, FalseLabel, Pred)].%%% Load an integer constant into a register.mk_li(Dst, Value) -> mk_li(Dst, Value, []).mk_li(Dst, Value, Tail) ->  hipe_arm:mk_li(Dst, Value, Tail).%%% Convert an RTL condition code.conv_alub_cond(Cond) ->	% only signed  case Cond of    eq	-> 'eq';    ne	-> 'ne';    gt	-> 'gt';    ge	-> 'ge';    lt	-> 'lt';    le	-> 'le';    overflow -> 'vs';    not_overflow -> 'vc';    _	-> exit({?MODULE,conv_alub_cond,Cond})  end.conv_branch_cond(Cond) -> % may be unsigned  case Cond of    gtu -> 'hi';    geu -> 'hs';    ltu -> 'lo';    leu -> 'ls';    _   -> conv_alub_cond(Cond)  end.    %%% Commute an ARM condition code.commute_cond(Cond) ->	% if x Cond y, then y commute_cond(Cond) x  case Cond of    'eq' -> 'eq';	% ==, ==    'ne' -> 'ne';	% !=, !=    'gt' -> 'lt';	% >, <    'ge' -> 'le';	% >=, <=    'lt' -> 'gt';	% <, >    'le' -> 'ge';	% <=, >=    'hi' -> 'lo';	% >u, <u    'hs' -> 'ls';	% >=u, <=u    'lo' -> 'hi';	% <u, >u    'ls' -> 'hs';	% <=u, >=u    %% vs/vc: n/a    _ -> exit({?MODULE,commute_cond,Cond})  end.%%% Split a list of formal or actual parameters into the%%% part passed in registers and the part passed on the stack.%%% The parameters passed in registers are also tagged with%%% the corresponding registers.split_args(Args) ->  split_args(0, hipe_arm_registers:nr_args(), Args, []).split_args(I, N, [Arg|Args], RegArgs) when I < N ->  Reg = hipe_arm_registers:arg(I),  Temp = hipe_arm:mk_temp(Reg, 'tagged'),  split_args(I+1, N, Args, [{Arg,Temp}|RegArgs]);split_args(_, _, StkArgs, RegArgs) ->  {RegArgs, StkArgs}.%%% Convert a list of actual parameters passed in%%% registers (from split_args/1) to a list of moves.move_actuals([{Src,Dst}|Actuals], Rest) ->  move_actuals(Actuals, mk_move(Dst, Src, Rest));move_actuals([], Rest) ->  Rest.%%% Convert a list of formal parameters passed in%%% registers (from split_args/1) to a list of moves.move_formals([{Dst,Src}|Formals], Rest) ->  move_formals(Formals, [hipe_arm:mk_pseudo_move(Dst, Src) | Rest]);move_formals([], Rest) ->  Rest.%%% Convert a 'fun' operand (MFA, prim, or temp)conv_fun(Fun, Map) ->  case hipe_rtl:is_var(Fun) of    true ->      conv_dst(Fun, Map);    false ->      case hipe_rtl:is_reg(Fun) of	true ->	  conv_dst(Fun, Map);	false ->	  if is_atom(Fun) ->	      {hipe_arm:mk_prim(Fun), Map};	     true ->	      {conv_mfa(Fun), Map}	  end      end  end.%%% Convert an MFA operand.conv_mfa({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->  hipe_arm:mk_mfa(M, F, A).%%% Convert an RTL source operand (imm/var/reg).%%% Returns a temp or a naked integer.conv_src(Opnd, Map) ->  case hipe_rtl:is_imm(Opnd) of    true ->      Value = hipe_rtl:imm_value(Opnd),      if is_integer(Value) ->	  {Value, Map}      end;    false ->      conv_dst(Opnd, Map)  end.conv_src_list([O|Os], Map) ->  {V, Map1} = conv_src(O, Map),  {Vs, Map2} = conv_src_list(Os, Map1),  {[V|Vs], Map2};conv_src_list([], Map) ->  {[], Map}.%%% Convert an RTL destination operand (var/reg).conv_dst(Opnd, Map) ->  {Name, Type} =    case hipe_rtl:is_var(Opnd) of      true ->	{hipe_rtl:var_index(Opnd), 'tagged'};      false ->	case hipe_rtl:is_fpreg(Opnd) of	  true ->	    {hipe_rtl:fpreg_index(Opnd), 'double'};	  false ->	    {hipe_rtl:reg_index(Opnd), 'untagged'}	end    end,  IsPrecoloured =    case Type of      'double' -> false; %hipe_arm_registers:is_precoloured_fpr(Name);      _ -> hipe_arm_registers:is_precoloured_gpr(Name)    end,  case IsPrecoloured of    true ->      {hipe_arm:mk_temp(Name, Type), Map};    false ->      case vmap_lookup(Map, Opnd) of	{value, NewTemp} ->	  {NewTemp, Map};	_ ->	  NewTemp = hipe_arm:mk_new_temp(Type),	  {NewTemp, vmap_bind(Map, Opnd, NewTemp)}      end  end.conv_dst_list([O|Os], Map) ->  {Dst, Map1} = conv_dst(O, Map),  {Dsts, Map2} = conv_dst_list(Os, Map1),  {[Dst|Dsts], Map2};conv_dst_list([], Map) ->  {[], Map}.conv_formals(Os, Map) ->  conv_formals(hipe_arm_registers:nr_args(), Os, Map, []).conv_formals(N, [O|Os], Map, Res) ->  Type =    case hipe_rtl:is_var(O) of      true -> 'tagged';      _ -> 'untagged'    end,  Dst =    if N > 0 -> hipe_arm:mk_new_temp(Type);	% allocatable       true -> hipe_arm:mk_new_nonallocatable_temp(Type)    end,  Map1 = vmap_bind(Map, O, Dst),  conv_formals(N-1, Os, Map1, [Dst|Res]);conv_formals(_, [], Map, Res) ->  {lists:reverse(Res), Map}.%%% Create a temp representing the stack pointer register.mk_sp() ->  hipe_arm:mk_temp(hipe_arm_registers:stack_pointer(), 'untagged').%%% Create a temp representing the return value register.mk_rv() ->  hipe_arm:mk_temp(hipe_arm_registers:return_value(), 'tagged').%%% new_untagged_temp -- conjure up an untagged scratch regnew_untagged_temp() ->  hipe_arm:mk_new_temp('untagged').%%% new_tagged_temp -- conjure up a tagged scratch regnew_tagged_temp() ->  hipe_arm:mk_new_temp('tagged').%%% Map from RTL var/reg operands to temps.vmap_empty() ->  gb_trees:empty().vmap_lookup(Map, Key) ->  gb_trees:lookup(Key, Map).vmap_bind(Map, Key, Val) ->  gb_trees:insert(Key, Val, Map).word_size() ->  4.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?