Переглянути джерело

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 -

sergei 12 роки тому
батько
коміт
1c652eb8f9
3 змінених файлів з 52 додано та 51 видалено
  1. 11 23
      compiler/mips/cgcpu.pas
  2. 1 1
      compiler/mips/cpupara.pas
  3. 40 27
      compiler/mips/cpupi.pas

+ 11 - 23
compiler/mips/cgcpu.pas

@@ -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

+ 1 - 1
compiler/mips/cpupara.pas

@@ -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;
 

+ 40 - 27
compiler/mips/cpupi.pas

@@ -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)
+
+        { 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
-          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;
+          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;