MIPS procinfo improvements:

- Removed TMIPSProcInfo.needs_frame_pointer, it duplicates pi_needs_stackframe flag.
- Don't save RA for leaf procedures.
* GP is caller-saved register, it does not need saving/restoring as nonvolatile registers. Handle its restore position as a "normal" temp, whose offset is known before secondpass. This allows to handle PIC calls without involving GAS macro processing.

git-svn-id: trunk@23885 -
This commit is contained in:
sergei 2013-03-17 08:43:39 +00:00
parent d5985b4f0e
commit 1c652eb8f9
3 changed files with 52 additions and 51 deletions

View File

@ -1203,7 +1203,7 @@ begin
if nostackframe then
exit;
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
if (pi_needs_stackframe in current_procinfo.flags) then
a_reg_alloc(list,NR_FRAME_POINTER_REG);
helplist:=TAsmList.Create;
@ -1236,15 +1236,12 @@ begin
mask:=0;
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
include(saveregs,RS_R31);
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
include(saveregs,RS_R31);
if (pi_needs_stackframe in current_procinfo.flags) then
include(saveregs,RS_FRAME_POINTER_REG);
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
include(saveregs,RS_GP);
lastintoffset:=LocalSize;
framesave:=nil;
gp_save:=nil;
ra_save:=nil;
for reg:=RS_R1 to RS_R31 do
@ -1258,10 +1255,6 @@ begin
framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
else if (reg=RS_R31) then
ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
else if (reg=RS_GP) and
(cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
gp_save:=taicpu.op_const(A_P_CPRESTORE,nextoffset)
else
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
inc(nextoffset,4);
@ -1311,10 +1304,11 @@ begin
even use AT register, which is why we use R9 instead of AT here for -LocalSize }
list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
end;
if assigned(gp_save) then
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
begin
list.concat(Taicpu.op_none(A_P_SET_MACRO));
list.concat(gp_save);
list.concat(Taicpu.op_const(A_P_CPRESTORE,TMIPSProcinfo(current_procinfo).save_gp_ref.offset));
list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
end;
@ -1338,11 +1332,6 @@ begin
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
end;
end;
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
begin
current_procinfo.got := NR_GP;
end;
list.concatList(helplist);
helplist.Free;
end;
@ -1382,12 +1371,11 @@ begin
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
include(saveregs,RS_R31);
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
include(saveregs,RS_R31);
if (pi_needs_stackframe in current_procinfo.flags) then
include(saveregs,RS_FRAME_POINTER_REG);
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
include(saveregs,RS_GP);
// GP does not need to be restored on exit
for reg:=RS_R1 to RS_R31 do
begin
if reg in saveregs then

View File

@ -450,7 +450,7 @@ implementation
begin
paraloc^.reference.index := NR_FRAME_POINTER_REG;
if assigned(current_procinfo) then
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
include(current_procinfo.flags,pi_needs_stackframe);
end;
paraloc^.reference.offset:=intparasize;

View File

@ -29,7 +29,7 @@ interface
cutils,
globtype,symdef,
procinfo,cpuinfo,cpupara,
psub;
psub,aasmdata,cgutils;
type
@ -40,17 +40,18 @@ interface
floatregstart : aint;
intregssave,
floatregssave : byte;
needs_frame_pointer: boolean;
register_used : tparasupregsused;
register_size : tparasupregsize;
register_name : tparasuprename;
register_offset : tparasupregsoffset;
computed_local_size : longint;
save_gp_ref: treference;
//intparareg,
//parasize : longint;
constructor create(aparent:tprocinfo);override;
function calc_stackframe_size:longint;override;
procedure set_first_temp_offset;override;
procedure allocate_got_register(list:tasmlist);override;
end;
{ Used by Stabs debug info generator }
@ -61,7 +62,7 @@ implementation
uses
systems,globals,verbose,
cpubase,cgbase,cgutils,cgobj,
cpubase,cgbase,cgobj,
tgobj,paramgr,symconst;
constructor TMIPSProcInfo.create(aparent: tprocinfo);
@ -69,9 +70,9 @@ implementation
i : longint;
begin
inherited create(aparent);
{ will call _mcount if profiling }
if cs_profile in current_settings.moduleswitches then
include(flags,pi_do_call);
{ if (cs_generate_stackframes in current_settings.localswitches) or
not (cs_opt_stackframe in current_settings.optimizerswitches) then }
include(flags,pi_needs_stackframe);
for i:=low(tparasupregs) to high(tparasupregs) do
begin
register_used[i]:=false;
@ -80,9 +81,7 @@ implementation
register_offset[i]:=-1;
end;
floatregssave:=12; { f20-f31 }
intregssave:=12; { r16-r23,r28-r31 }
{ for testing }
needs_frame_pointer := true;//false;
intregssave:=10; { r16-r23,r30,r31 }
computed_local_size:=-1;
{ pi_needs_got is not yet set correctly
so include it always if creating PIC code }
@ -98,28 +97,42 @@ implementation
procedure TMIPSProcInfo.set_first_temp_offset;
begin
{ MIPS stack frame is always "optimized" }
framepointer:=NR_STACK_POINTER_REG;
tg.direction:=1;
{ We allocate enough space to save all registers because we can't determine
the necessary space because the used registers aren't known before
secondpass is run. }
if tg.direction = -1 then
tg.setfirsttemp(0)
else
begin
{ Fixes the case when there are calls done by low-level means
(cg.a_call_name) but no child callnode. !!For assembler procedure
there is no clean way to determine what it calls, unless it is
also declared as nostackframe and everything is managed manually. }
if (pi_do_call in flags) or
((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
if not (po_nostackframe in procdef.procoptions) then
tg.setfirsttemp(Align(maxpushedparasize+
floatregssave*sizeof(aint)+intregssave*sizeof(aint)
,max(current_settings.alignment.localalignmin,8)))
else
tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8)));
end;
{ will call _mcount if profiling }
if (cs_profile in current_settings.moduleswitches) and
not (po_nostackframe in procdef.procoptions) then
include(flags,pi_do_call);
{ Fixes the case when there are calls done by low-level means
(cg.a_call_name) but no child callnode. !!For assembler procedure
there is no clean way to determine what it calls, unless it is
also declared as nostackframe and everything is managed manually. }
if (pi_do_call in flags) or
((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
if not (po_nostackframe in procdef.procoptions) then
tg.setfirsttemp(Align(maxpushedparasize+
floatregssave*sizeof(aint)+intregssave*sizeof(aint)
,max(current_settings.alignment.localalignmin,8)))
else
tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8)));
end;
procedure TMIPSProcInfo.allocate_got_register(list:tasmlist);
begin
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in flags) and
not (po_nostackframe in procdef.procoptions) then
tg.gettemp(list,sizeof(aint),sizeof(aint),tt_noreuse,save_gp_ref);
end;