📄 hipe_rtl_to_ppc.erl
字号:
conv_enter(I, Map, Data) -> {Args, Map0} = conv_src_list(hipe_rtl:enter_arglist(I), Map), {Fun, Map1} = conv_fun(hipe_rtl:enter_fun(I), Map0), I2 = mk_enter(Fun, Args, hipe_rtl:enter_type(I)), {I2, Map1, Data}.mk_enter(Fun, Args, Linkage) -> {FixFunC,FunC} = fix_func(Fun), Arity = length(Args), {RegArgs,StkArgs} = split_args(Args), FixFunC ++ move_actuals(RegArgs, [hipe_ppc:mk_pseudo_tailcall_prepare(), hipe_ppc:mk_pseudo_tailcall(FunC, Arity, StkArgs, Linkage)]).conv_goto(I, Map, Data) -> I2 = [hipe_ppc:mk_b_label(hipe_rtl:goto_label(I))], {I2, Map, Data}.conv_label(I, Map, Data) -> I2 = [hipe_ppc:mk_label(hipe_rtl:label_name(I))], {I2, Map, Data}.conv_load(I, Map, Data) -> {Dst, Map0} = conv_dst(hipe_rtl:load_dst(I), Map), {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) -> Rest = case LoadSize of byte -> case LoadSign of signed -> [hipe_ppc:mk_unary('extsb', Dst, Dst)]; _ -> [] end; _ -> [] end, LdOp = case LoadSize of byte -> 'lbz'; int32 -> 'lwz'; word -> 'lwz'; int16 -> case LoadSign of signed -> 'lha'; unsigned -> 'lhz' end end, case hipe_ppc:is_temp(Base1) of true -> case hipe_ppc:is_temp(Base2) of true -> mk_load_rr(Dst, Base1, Base2, LdOp, Rest); _ -> mk_load_ri(Dst, Base1, Base2, LdOp, Rest) end; _ -> case hipe_ppc:is_temp(Base2) of true -> mk_load_ri(Dst, Base2, Base1, LdOp, Rest); _ -> mk_load_ii(Dst, Base1, Base2, LdOp, Rest) end end.mk_load_ii(Dst, Base1, Base2, LdOp, Rest) -> 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, Rest)). mk_load_ri(Dst, Base, Disp, LdOp, Rest) -> hipe_ppc:mk_load(LdOp, Dst, Disp, Base, 'new', Rest).mk_load_rr(Dst, Base1, Base2, LdOp, Rest) -> LdxOp = hipe_ppc:ldop_to_ldxop(LdOp), [hipe_ppc:mk_loadx(LdxOp, Dst, Base1, Base2) | Rest].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_ppc: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_ppc: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_ppc:is_temp(Src) of true -> [hipe_ppc: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_ppc:mk_blr()]), {I2, Map0, Data}.conv_store(I, Map, Data) -> {Base1, Map0} = conv_dst(hipe_rtl:store_base(I), Map), {Src, Map1} = conv_src(hipe_rtl:store_src(I), Map0), {Base2, Map2} = conv_src(hipe_rtl:store_offset(I), Map1), StoreSize = hipe_rtl:store_size(I), I2 = mk_store(Src, Base1, Base2, StoreSize), {I2, Map2, Data}.mk_store(Src, Base1, Base2, StoreSize) -> StOp = case StoreSize of byte -> 'stb'; int16 -> 'sth'; int32 -> 'stw'; word -> 'stw' end, case hipe_ppc:is_temp(Src) of true -> mk_store2(Src, Base1, Base2, StOp); _ -> Tmp = new_untagged_temp(), mk_li(Tmp, Src, mk_store2(Tmp, Base1, Base2, StOp)) end.mk_store2(Src, Base1, Base2, StOp) -> case hipe_ppc:is_temp(Base2) of true -> mk_store_rr(Src, Base1, Base2, StOp); _ -> mk_store_ri(Src, Base1, Base2, StOp) end. mk_store_ri(Src, Base, Disp, StOp) -> hipe_ppc:mk_store(StOp, Src, Disp, Base, 'new', []).mk_store_rr(Src, Base1, Base2, StOp) -> StxOp = hipe_ppc:stop_to_stxop(StOp), [hipe_ppc:mk_storex(StxOp, Src, Base1, Base2)].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(), OffsetR = new_untagged_temp(), DestR = new_untagged_temp(), I2 = [hipe_ppc:mk_pseudo_li(JTabR, {JTabLab,constant}), hipe_ppc:mk_alu('slwi', OffsetR, IndexR, hipe_ppc:mk_uimm16(2)), hipe_ppc:mk_loadx('lwzx', DestR, JTabR, OffsetR), hipe_ppc:mk_mtspr('ctr', DestR), hipe_ppc:mk_bctr(Labels)], {I2, Map1, NewData}.%%% Create a conditional branch.%%% If the condition tests CR0[SO], rewrite the path%%% corresponding to SO being set to clear XER[SO].mk_pseudo_bc(BCond, TrueLabel, FalseLabel, Pred) -> case BCond of 'so' -> NewTrueLabel = hipe_gensym:get_next_label(ppc), [hipe_ppc:mk_pseudo_bc(BCond, NewTrueLabel, FalseLabel, Pred), hipe_ppc:mk_label(NewTrueLabel), hipe_ppc:mk_mcrxr(), hipe_ppc:mk_b_label(TrueLabel)]; 'ns' -> NewFalseLabel = hipe_gensym:get_next_label(ppc), [hipe_ppc:mk_pseudo_bc(BCond, TrueLabel, NewFalseLabel, Pred), hipe_ppc:mk_label(NewFalseLabel), hipe_ppc:mk_mcrxr(), hipe_ppc:mk_b_label(FalseLabel)]; _ -> [hipe_ppc:mk_pseudo_bc(BCond, TrueLabel, FalseLabel, Pred)] end.%%% Load an integer constant into a register.mk_li(Dst, Value) -> mk_li(Dst, Value, []).mk_li(Dst, Value, Tail) -> hipe_ppc:mk_li(Dst, Value, Tail).%%% Check if an RTL ALU or ALUB operator commutes.rtl_aluop_commutes(RtlAluOp) -> case RtlAluOp of 'add' -> true; 'mul' -> true; 'or' -> true; 'and' -> true; 'xor' -> true; _ -> false 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_ppc_registers:nr_args(), Args, []).split_args(I, N, [Arg|Args], RegArgs) when I < N -> Reg = hipe_ppc_registers:arg(I), Temp = hipe_ppc: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_ppc: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_ppc: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_ppc: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_fpreg(Opnd, Map) -> case hipe_rtl:is_fpreg(Opnd) of true -> conv_dst(Opnd, Map) end.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' -> hipe_ppc_registers:is_precoloured_fpr(Name); _ -> hipe_ppc_registers:is_precoloured_gpr(Name) end, case IsPrecoloured of true -> {hipe_ppc:mk_temp(Name, Type), Map}; false -> case vmap_lookup(Map, Opnd) of {value, NewTemp} -> {NewTemp, Map}; _ -> NewTemp = hipe_ppc: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_ppc_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_ppc:mk_new_temp(Type); % allocatable true -> hipe_ppc: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_ppc:mk_temp(hipe_ppc_registers:stack_pointer(), 'untagged').%%% Create a temp representing the return value register.mk_rv() -> hipe_ppc:mk_temp(hipe_ppc_registers:return_value(), 'tagged').%%% new_untagged_temp -- conjure up an untagged scratch regnew_untagged_temp() -> hipe_ppc:mk_new_temp('untagged').%%% new_tagged_temp -- conjure up a tagged scratch regnew_tagged_temp() -> hipe_ppc: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() -> hipe_rtl_arch:word_size().
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -