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 + -
显示快捷键?