hipe_arm_frame.erl

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

ERL
630
字号
%%%%%% Contexts%%%-record(context, {liveness, framesize, arity, map, clobbers_lr, ref_maxstack}).mk_context(Liveness, Formals, Temps, ClobbersLR) ->  {Map, MinOff} = mk_temp_map(Formals, ClobbersLR, Temps),  FrameSize = (-MinOff),  RefMaxStack = hipe_bifs:ref(FrameSize),  Context = #context{liveness=Liveness,		     framesize=FrameSize, arity=length(Formals),		     map=Map, clobbers_lr=ClobbersLR, ref_maxstack=RefMaxStack},  Context.context_need_stack(#context{ref_maxstack=RM}, N) ->  M = hipe_bifs:ref_get(RM),  if N > M -> hipe_bifs:ref_set(RM, N);     true -> []  end.context_maxstack(#context{ref_maxstack=RM}) ->  hipe_bifs:ref_get(RM).context_arity(#context{arity=Arity}) ->  Arity.context_framesize(#context{framesize=FrameSize}) ->  FrameSize.context_liveness(#context{liveness=Liveness}) ->  Liveness.context_offset(#context{map=Map}, Temp) ->  tmap_lookup(Map, Temp).context_clobbers_lr(#context{clobbers_lr=ClobbersLR}) -> ClobbersLR.mk_temp_map(Formals, ClobbersLR, Temps) ->  {Map, 0} = enter_vars(Formals, word_size() * length(Formals),			tmap_empty()),  TempsList = tset_to_list(Temps),  AllTemps =    case ClobbersLR of      false -> TempsList;      true ->	RA = hipe_arm:mk_new_temp('untagged'),	[RA|TempsList]    end,  enter_vars(AllTemps, 0, Map).enter_vars([V|Vs], PrevOff, Map) ->  Off =    case hipe_arm:temp_type(V) of      'double' -> PrevOff - 2*word_size();      _ -> PrevOff - word_size()    end,  enter_vars(Vs, Off, tmap_bind(Map, V, Off));enter_vars([], Off, Map) ->  {Map, Off}.tmap_empty() ->  gb_trees:empty().tmap_bind(Map, Key, Val) ->  gb_trees:insert(Key, Val, Map).tmap_lookup(Map, Key) ->  gb_trees:get(Key, Map).%%%%%% do_prologue: prepend stack frame allocation code.%%%%%% NewStart:%%%	temp1 = *(P + P_SP_LIMIT)%%%	temp2 = SP - MaxStack%%%	cmp temp2, Temp1%%%	if (ltu) goto IncStack else goto AllocFrame%%% AllocFrame:%%%	SP -= FrameSize%%%	*(SP + FrameSize-WordSize) = LR		[if ClobbersLR]%%%	goto OldStart%%% OldStart:%%%	...%%% IncStack:%%%	temp1 = LR%%%	bl inc_stack%%%	LR = temp1%%%	goto NewStartdo_prologue(CFG, Context) ->  MaxStack = context_maxstack(Context),  if MaxStack > 0 ->      FrameSize = context_framesize(Context),      OldStartLab = hipe_arm_cfg:start_label(CFG),      NewStartLab = hipe_gensym:get_next_label(arm),      %%      P = hipe_arm:mk_temp(hipe_arm_registers:proc_pointer(), 'untagged'),      Temp1 = mk_temp1(),      SP = mk_sp(),      %%      LR = hipe_arm:mk_lr(),      ClobbersLR = context_clobbers_lr(Context),      GotoOldStartCode = [hipe_arm:mk_b_label(OldStartLab)],      AllocFrameCodeTail =	case ClobbersLR of	  false -> GotoOldStartCode;	  true -> mk_store('str', LR, FrameSize-word_size(), SP, GotoOldStartCode)	end,      %%      Arity = context_arity(Context),      Guaranteed = max(0, (?ARM_LEAF_WORDS - Arity) * word_size()),      %%      {CFG1,NewStartCode} =	if MaxStack =< Guaranteed ->	    %% io:format("~w: MaxStack ~w =< Guaranteed ~w :-)\n", [?MODULE,MaxStack,Guaranteed]),	    AllocFrameCode = adjust_sp(-FrameSize, AllocFrameCodeTail),	    NewStartCode0 = AllocFrameCode, % no mflr needed	    {CFG,NewStartCode0};	   true ->	    %% io:format("~w: MaxStack ~w > Guaranteed ~w :-(\n", [?MODULE,MaxStack,Guaranteed]),	    AllocFrameLab = hipe_gensym:get_next_label(arm),	    IncStackLab = hipe_gensym:get_next_label(arm),	    Temp2 = mk_temp2(),	    %%	    NewStartCodeTail2 =	      [hipe_arm:mk_pseudo_bc('lo', IncStackLab, AllocFrameLab, 0.01)],	    NewStartCodeTail1 = NewStartCodeTail2, % no mflr needed	    NewStartCode0 =	      mk_load('ldr', Temp1, ?P_NSP_LIMIT, P,		      hipe_arm:mk_addi(Temp2, SP, -MaxStack,				       [hipe_arm:mk_cmp('cmp', Temp2, Temp1) |					NewStartCodeTail1])),	    %%	    AllocFrameCode =	      if MaxStack =:= FrameSize ->		  %% io:format("~w: MaxStack =:= FrameSize =:= ~w :-)\n", [?MODULE,MaxStack]),		  [hipe_arm:mk_move(SP, Temp2) |		   AllocFrameCodeTail];		 true ->		  %% io:format("~w: MaxStack ~w =/= FrameSize ~w :-(\n", [?MODULE,MaxStack,FrameSize]),		  adjust_sp(-FrameSize, AllocFrameCodeTail)	      end,	    %%	    IncStackCodeTail =	      [hipe_arm:mk_bl(hipe_arm:mk_prim('inc_stack_0'),			      mk_minimal_sdesc(Context), not_remote),	       hipe_arm:mk_mtlr(Temp1),	       hipe_arm:mk_b_label(NewStartLab)],	    IncStackCode =	      [hipe_arm:mk_mflr(Temp1) | IncStackCodeTail], % mflr always needed	    %%	    CFG0a = hipe_arm_cfg:bb_add(CFG, AllocFrameLab,					hipe_bb:mk_bb(AllocFrameCode)),	    CFG0b = hipe_arm_cfg:bb_add(CFG0a, IncStackLab,					hipe_bb:mk_bb(IncStackCode)),	    %%	    {CFG0b,NewStartCode0}	end,      %%      CFG2 = hipe_arm_cfg:bb_add(CFG1, NewStartLab,                                 hipe_bb:mk_bb(NewStartCode)),      hipe_arm_cfg:start_label_update(CFG2, NewStartLab);     true ->      CFG  end.%%% Create a load instruction.%%% May clobber Dst early for large offsets. In principle we could%%% clobber TEMP2 if Dst =:= Base, but Dst =/= Base here in frame.mk_load(LdOp, Dst, Offset, Base, Rest) ->  hipe_arm:mk_load(LdOp, Dst, Base, Offset, 'error', Rest).%%% Create a store instruction.%%% May clobber TEMP2 for large offsets.mk_store(StOp, Src, Offset, Base, Rest) ->  hipe_arm:mk_store(StOp, Src, Base, Offset, 'temp2', Rest).%%% typeof_temp -- what's temp's type?typeof_temp(Temp) ->  hipe_arm:temp_type(Temp).%%% Cons up an 'SP' Temp.mk_sp() ->  hipe_arm:mk_temp(hipe_arm_registers:stack_pointer(), 'untagged').%%% Cons up a 'TEMP1' Temp.mk_temp1() ->  hipe_arm:mk_temp(hipe_arm_registers:temp1(), 'untagged').%%% Cons up a 'TEMP2' Temp.mk_temp2() ->  hipe_arm:mk_temp(hipe_arm_registers:temp2(), 'untagged').%%% Check if an operand is a pseudo-Temp.src_is_pseudo(Src) ->  case hipe_arm:is_temp(Src) of    true -> temp_is_pseudo(Src);    _ -> false  end.temp_is_pseudo(Temp) ->  not(hipe_arm:temp_is_precoloured(Temp)).%%%%%% Detect if a Defun's body clobbers LR.%%%clobbers_lr(Insns) ->  LRreg = hipe_arm_registers:lr(),  LRtagged = hipe_arm:mk_temp(LRreg, 'tagged'),  LRuntagged = hipe_arm:mk_temp(LRreg, 'untagged'),  clobbers_lr(Insns, LRtagged, LRuntagged).clobbers_lr([I|Insns], LRtagged, LRuntagged) ->  Defs = hipe_arm_defuse:insn_def_gpr(I),  case lists:member(LRtagged, Defs) of    true -> true;    false ->      case lists:member(LRuntagged, Defs) of	true -> true;	false -> clobbers_lr(Insns, LRtagged, LRuntagged)      end  end;clobbers_lr([], _LRtagged, _LRuntagged) -> false.%%%%%% Build the set of all temps used in a Defun's body.%%%all_temps(Code, Formals) ->  S0 = find_temps(Code, tset_empty()),  S1 = tset_del_list(S0, Formals),  S2 = tset_filter(S1, fun(T) -> temp_is_pseudo(T) end),  S2.find_temps([I|Insns], S0) ->  S1 = tset_add_list(S0, hipe_arm_defuse:insn_def_all(I)),  S2 = tset_add_list(S1, hipe_arm_defuse:insn_use_all(I)),  find_temps(Insns, S2);find_temps([], S) ->  S.tset_empty() ->  gb_sets:new().tset_size(S) ->  gb_sets:size(S).tset_insert(S, T) ->  gb_sets:add_element(T, S).tset_add_list(S, Ts) ->  gb_sets:union(S, gb_sets:from_list(Ts)).tset_del_list(S, Ts) ->  gb_sets:subtract(S, gb_sets:from_list(Ts)).tset_filter(S, F) ->  gb_sets:filter(F, S).tset_to_list(S) ->  gb_sets:to_list(S).%%%%%% Compute minimum permissible frame size, ignoring spilled temps.%%% This is done to ensure that we won't have to adjust the frame size%%% in the middle of a tailcall.%%%defun_minframe(Defun) ->  MaxTailArity = body_mta(hipe_arm:defun_code(Defun), 0),  MyArity = length(fix_formals(hipe_arm:defun_formals(Defun))),  max(MaxTailArity - MyArity, 0).body_mta([I|Code], MTA) ->  body_mta(Code, insn_mta(I, MTA));body_mta([], MTA) ->  MTA.insn_mta(I, MTA) ->  case I of    #pseudo_tailcall{arity=Arity} ->      max(MTA, Arity - hipe_arm_registers:nr_args());    _ -> MTA  end.max(X, Y) -> % why isn't max/2 a standard BIF?  if X > Y -> X; true -> Y end.%%%%%% Ensure that we have enough temps to satisfy the minimum frame size,%%% if necessary by prepending unused dummy temps.%%%ensure_minframe(MinFrame, Temps) ->  ensure_minframe(MinFrame, tset_size(Temps), Temps).ensure_minframe(MinFrame, Frame, Temps) ->  if MinFrame > Frame ->      Temp = hipe_arm:mk_new_temp('untagged'),      ensure_minframe(MinFrame, Frame+1, tset_insert(Temps, Temp));     true -> Temps  end.word_size() ->  4.

⌨️ 快捷键说明

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