فهرست منبع

* assembler procedures now again get a stackframe if they have local
variables. No space is reserved for a function result however.
Also, the register parameters aren't automatically saved on the stack
anymore in assembler procedures.

Jonas Maebe 22 سال پیش
والد
کامیت
56132c1a9c
3فایلهای تغییر یافته به همراه206 افزوده شده و 165 حذف شده
  1. 71 52
      compiler/ncgutil.pas
  2. 119 110
      compiler/powerpc/cgcpu.pas
  3. 16 3
      compiler/psub.pas

+ 71 - 52
compiler/ncgutil.pas

@@ -1357,27 +1357,37 @@ function returns in a register and the caller receives it in an other one}
              { for now the pointer to the result can't be a register }
              if not(paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption)) then
                begin
-                  paraloc:=paramanager.getfuncretparaloc(aktprocdef);
-                  reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
-                  case paraloc.loc of
-                     LOC_CREGISTER,
-                     LOC_REGISTER:
-                       if not(paraloc.size in [OS_64,OS_S64]) then
-                         cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
-                       else
-                         cg64.a_load64_reg_ref(list,paraloc.register64,href);
-                     LOC_CFPUREGISTER,
-                     LOC_FPUREGISTER:
-                       cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
-                     LOC_CMMREGISTER,
-                     LOC_MMREGISTER:
-                       cg.a_loadmm_reg_ref(list,paraloc.register,href);
-                  end;
+{$ifdef powerpc}
+                  { no stack space is allocated in this case -> can't save the result reg on the stack }
+                  if not(po_assembler in aktprocdef.procoptions) then
+{$endif powerpc}
+                    begin
+                      paraloc:=paramanager.getfuncretparaloc(aktprocdef);
+                      reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
+                      case paraloc.loc of
+                        LOC_CREGISTER,
+                        LOC_REGISTER:
+                          if not(paraloc.size in [OS_64,OS_S64]) then
+                            cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
+                          else
+                            cg64.a_load64_reg_ref(list,paraloc.register64,href);
+                        LOC_CFPUREGISTER,
+                        LOC_FPUREGISTER:
+                          cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
+                        LOC_CMMREGISTER,
+                        LOC_MMREGISTER:
+                          cg.a_loadmm_reg_ref(list,paraloc.register,href);
+                      end;
+                    end;
                end;
 
              { initialize return value }
              if (aktprocdef.rettype.def.needs_inittable) then
                begin
+{$ifdef powerpc}
+                  if (po_assembler in aktprocdef.procoptions) then
+                    internalerror(200304161);
+{$endif powerpc}
                   if (cs_implicit_exceptions in aktmoduleswitches) then
                     procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
                   reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
@@ -1413,47 +1423,50 @@ function returns in a register and the caller receives it in an other one}
           begin
              aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
 
-             { move register parameters which aren't regable into memory                                          }
-             { we do this after init_paras because it saves some code in init_paras if parameters are in register }
-             { instead in memory                                                                                  }
-             hp:=tparaitem(procinfo.procdef.para.first);
-             while assigned(hp) do
+             if not (po_assembler in aktprocdef.procoptions) then
                begin
-                  if Tvarsym(hp.parasym).reg.enum>lastreg then
-                    internalerror(200301081);
-                  if (tvarsym(hp.parasym).reg.enum<>R_NO) then
-                    case hp.paraloc.loc of
-                       LOC_CREGISTER,
-                       LOC_REGISTER:
+                 { move register parameters which aren't regable into memory                                          }
+                 { we do this after init_paras because it saves some code in init_paras if parameters are in register }
+                 { instead in memory                                                                                  }
+                 hp:=tparaitem(procinfo.procdef.para.first);
+                 while assigned(hp) do
+                   begin
+                     if Tvarsym(hp.parasym).reg.enum>lastreg then
+                       internalerror(200301081);
+                     if (tvarsym(hp.parasym).reg.enum<>R_NO) then
+                       case hp.paraloc.loc of
+                         LOC_CREGISTER,
+                         LOC_REGISTER:
 //                         if not(hp.paraloc.size in [OS_S64,OS_64]) then
-                           cg.a_load_reg_reg(list,hp.paraloc.size,OS_32,hp.paraloc.register,tvarsym(hp.parasym).reg);
+                             cg.a_load_reg_reg(list,hp.paraloc.size,OS_32,hp.paraloc.register,tvarsym(hp.parasym).reg);
 //                         else
 //                           cg64.a_load64_reg_reg(list,hp.paraloc.register64,tvarsym(hp.parasym).reg);
-                       LOC_CFPUREGISTER,
-                       LOC_FPUREGISTER:
-                         cg.a_loadfpu_reg_reg(list,hp.paraloc.register,tvarsym(hp.parasym).reg);
-                    end
-                  else if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
-                    LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
-                    (tvarsym(hp.parasym).reg.enum=R_NO) then
-                    begin
-                       reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address+
-                         tvarsym(hp.parasym).owner.address_fixup);
-                       case hp.paraloc.loc of
-                          LOC_CREGISTER,
-                          LOC_REGISTER:
-                           if not(hp.paraloc.size in [OS_S64,OS_64]) then
-                              cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href)
+                         LOC_CFPUREGISTER,
+                         LOC_FPUREGISTER:
+                           cg.a_loadfpu_reg_reg(list,hp.paraloc.register,tvarsym(hp.parasym).reg);
+                       end
+                     else if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
+                      LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
+                      (tvarsym(hp.parasym).reg.enum=R_NO) then
+                       begin
+                         reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address+
+                           tvarsym(hp.parasym).owner.address_fixup);
+                         case hp.paraloc.loc of
+                           LOC_CREGISTER,
+                           LOC_REGISTER:
+                            if not(hp.paraloc.size in [OS_S64,OS_64]) then
+                               cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href)
+                            else
+                               cg64.a_load64_reg_ref(list,hp.paraloc.register64,href);
+                           LOC_FPUREGISTER,
+                           LOC_CFPUREGISTER:
+                             cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
                            else
-                              cg64.a_load64_reg_ref(list,hp.paraloc.register64,href);
-                          LOC_FPUREGISTER,
-                          LOC_CFPUREGISTER:
-                            cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
-                          else
-                            internalerror(2002081302);
+                             internalerror(2002081302);
+                         end;
                        end;
-                    end;
-                  hp:=tparaitem(hp.next);
+                     hp:=tparaitem(hp.next);
+                   end;
                end;
           end;
 
@@ -2005,7 +2018,13 @@ function returns in a register and the caller receives it in an other one}
 end.
 {
   $Log$
-  Revision 1.83  2003-04-06 21:11:23  olle
+  Revision 1.84  2003-04-16 09:26:55  jonas
+    * assembler procedures now again get a stackframe if they have local
+      variables. No space is reserved for a function result however.
+      Also, the register parameters aren't automatically saved on the stack
+      anymore in assembler procedures.
+
+  Revision 1.83  2003/04/06 21:11:23  olle
     * changed newasmsymbol to newasmsymboldata for data symbols
 
   Revision 1.82  2003/03/30 20:59:07  peter

+ 119 - 110
compiler/powerpc/cgcpu.pas

@@ -913,11 +913,6 @@ const
     procedure tcgppc.g_stackframe_entry(list : taasmoutput;localsize : longint);
 
       begin
-        { if you program in assembler, you have to take care of everything }
-        { yourself. Some things just don't work otherwise (e.g. the linux  }
-        { syscall code) (JM)                                               }
-        if (po_assembler in aktprocdef.procoptions) then
-          exit;
         case target_info.system of
           system_powerpc_macos:
             g_stackframe_entry_mac(list,localsize);
@@ -931,14 +926,6 @@ const
     procedure tcgppc.g_return_from_proc(list : taasmoutput;parasize : aword);
 
       begin
-        { if you program in assembler, you have to take care of everything }
-        { yourself. Some things just don't work otherwise (e.g. the linux  }
-        { syscall code) (JM)                                               }
-        if (po_assembler in aktprocdef.procoptions) then
-           begin
-             list.concat(taicpu.op_none(A_BLR));
-             exit;
-           end;
         case target_info.system of
           system_powerpc_macos:
             g_return_from_proc_mac(list,parasize);
@@ -985,38 +972,41 @@ const
           end;
 
         usesfpr:=false;
-        for regcounter.enum:=R_F14 to R_F31 do
-          if regcounter.enum in rg.usedbyproc then
-            begin
-               usesfpr:=true;
-               firstregfpu:=regcounter;
-               break;
-            end;
-
-        usesgpr:=false;
-        for regcounter2:=RS_R14 to RS_R31 do
-          begin
-            if regcounter2 in rg.usedintbyproc then
+        if not (po_assembler in aktprocdef.procoptions) then
+          for regcounter.enum:=R_F14 to R_F31 do
+            if regcounter.enum in rg.usedbyproc then
               begin
-                 usesgpr:=true;
-                 firstreggpr.enum := R_INTREGISTER;
-                 firstreggpr.number := regcounter2 shl 8;
-                 break;
+                usesfpr:= true;
+                firstregfpu:=regcounter;
+                break;
               end;
-         end;
+
+        usesgpr:=false;
+        if not (po_assembler in aktprocdef.procoptions) then
+          for regcounter2:=RS_R14 to RS_R31 do
+            begin
+              if regcounter2 in rg.usedintbyproc then
+                begin
+                   usesgpr:=true;
+                   firstreggpr.enum := R_INTREGISTER;
+                   firstreggpr.number := regcounter2 shl 8;
+                   break;
+                end;
+            end;
 
         { save link register? }
-        if (procinfo.flags and pi_do_call)<>0 then
-          begin
-             { save return address... }
-             r.enum:=R_INTREGISTER;
-             r.number:=NR_R0;
-             list.concat(taicpu.op_reg(A_MFLR,r));
-             { ... in caller's rframe }
-             reference_reset_base(href,rsp,4);
-             list.concat(taicpu.op_reg_ref(A_STW,r,href));
-             a_reg_dealloc(list,r);
-          end;
+        if not (po_assembler in aktprocdef.procoptions) then
+          if (procinfo.flags and pi_do_call)<>0 then
+            begin
+               { save return address... }
+               r.enum:=R_INTREGISTER;
+               r.number:=NR_R0;
+               list.concat(taicpu.op_reg(A_MFLR,r));
+               { ... in caller's rframe }
+               reference_reset_base(href,rsp,4);
+               list.concat(taicpu.op_reg_ref(A_STW,r,href));
+               a_reg_dealloc(list,r);
+            end;
 
         if usesfpr or usesgpr then
           begin
@@ -1042,10 +1032,13 @@ const
 
         tppcprocinfo(procinfo).localsize:=localsize;
 
-        r.enum:=R_INTREGISTER;
-        r.number:=NR_STACK_POINTER_REG;
-        reference_reset_base(href,r,-localsize);
-        a_load_store(list,A_STWU,r,href);
+        if (localsize <> 0) then
+          begin
+            r.enum:=R_INTREGISTER;
+            r.number:=NR_STACK_POINTER_REG;
+            reference_reset_base(href,r,-localsize);
+            a_load_store(list,A_STWU,r,href);
+          end;
 
         { no GOT pointer loaded yet }
         gotgot:=false;
@@ -1142,25 +1135,27 @@ const
         { AltiVec context restore, not yet implemented !!! }
 
         usesfpr:=false;
-        for regcounter.enum:=R_F14 to R_F31 do
-          if regcounter.enum in rg.usedbyproc then
-            begin
-               usesfpr:=true;
-               firstregfpu:=regcounter;
-               break;
-            end;
-
-        usesgpr:=false;
-        for regcounter2:=RS_R14 to RS_R30 do
-          begin
-            if regcounter2 in rg.usedintbyproc then
+        if not (po_assembler in aktprocdef.procoptions) then
+          for regcounter.enum:=R_F14 to R_F31 do
+            if regcounter.enum in rg.usedbyproc then
               begin
-                 usesgpr:=true;
-                 firstreggpr.enum:=R_INTREGISTER;
-                 firstreggpr.number:=regcounter2 shl 8;
+                 usesfpr:=true;
+                 firstregfpu:=regcounter;
                  break;
               end;
-          end;
+
+        usesgpr:=false;
+        if not (po_assembler in aktprocdef.procoptions) then
+          for regcounter2:=RS_R14 to RS_R30 do
+            begin
+              if regcounter2 in rg.usedintbyproc then
+                begin
+                  usesgpr:=true;
+                  firstreggpr.enum:=R_INTREGISTER;
+                  firstreggpr.number:=regcounter2 shl 8;
+                  break;
+                end;
+            end;
 
         { no return (blr) generated yet }
         genret:=true;
@@ -1211,16 +1206,17 @@ const
              r.number:=NR_R1;
              a_op_const_reg(list,OP_ADD,tppcprocinfo(procinfo).localsize,r);
              { load link register? }
-             if (procinfo.flags and pi_do_call)<>0 then
-               begin
-                  r.enum:=R_INTREGISTER;
-                  r.number:=NR_STACK_POINTER_REG;
-                  reference_reset_base(href,r,4);
-                  r.enum:=R_INTREGISTER;
-                  r.number:=NR_R0;
-                  list.concat(taicpu.op_reg_ref(A_LWZ,r,href));
-                  list.concat(taicpu.op_reg(A_MTLR,r));
-               end;
+             if not (po_assembler in aktprocdef.procoptions) then
+               if (procinfo.flags and pi_do_call)<>0 then
+                 begin
+                    r.enum:=R_INTREGISTER;
+                    r.number:=NR_STACK_POINTER_REG;
+                    reference_reset_base(href,r,4);
+                    r.enum:=R_INTREGISTER;
+                    r.number:=NR_R0;
+                    list.concat(taicpu.op_reg_ref(A_LWZ,r,href));
+                    list.concat(taicpu.op_reg(A_MTLR,r));
+                 end;
              list.concat(taicpu.op_none(A_BLR));
           end;
       end;
@@ -1239,25 +1235,27 @@ const
 
     begin
       usesfpr:=false;
-      for regcounter.enum:=R_F14 to R_F31 do
-        if regcounter.enum in rg.usedbyproc then
-          begin
-             usesfpr:=true;
-             firstregfpu:=regcounter;
-             break;
-          end;
-
-      usesgpr:=false;
-      for regcounter2:=RS_R13 to RS_R31 do
-        begin
-          if regcounter2 in rg.usedintbyproc then
+      if not (po_assembler in aktprocdef.procoptions) then
+        for regcounter.enum:=R_F14 to R_F31 do
+          if regcounter.enum in rg.usedbyproc then
             begin
-               usesgpr:=true;
-               firstreggpr.enum:=R_INTREGISTER;
-               firstreggpr.number:=regcounter2 shl 8;
+               usesfpr:=true;
+               firstregfpu:=regcounter;
                break;
             end;
-        end;
+
+      usesgpr:=false;
+      if not (po_assembler in aktprocdef.procoptions) then
+        for regcounter2:=RS_R13 to RS_R31 do
+          begin
+            if regcounter2 in rg.usedintbyproc then
+              begin
+                 usesgpr:=true;
+                 firstreggpr.enum:=R_INTREGISTER;
+                 firstreggpr.number:=regcounter2 shl 8;
+                 break;
+              end;
+          end;
       offset:= 0;
 
       { save floating-point registers }
@@ -1316,26 +1314,28 @@ const
 
     begin
       usesfpr:=false;
-      for regcounter.enum:=R_F14 to R_F31 do
-        if regcounter.enum in rg.usedbyproc then
-          begin
-             usesfpr:=true;
-             firstregfpu:=regcounter;
-             break;
-          end;
-
-      usesgpr:=false;
-      for regcounter2:=RS_R13 to RS_R31 do
-        begin
-          if regcounter2 in rg.usedintbyproc then
+      if not (po_assembler in aktprocdef.procoptions) then
+        for regcounter.enum:=R_F14 to R_F31 do
+          if regcounter.enum in rg.usedbyproc then
             begin
-               usesgpr:=true;
-               firstreggpr.enum:=R_INTREGISTER;
-               firstreggpr.number:=regcounter2 shl 8;
+               usesfpr:=true;
+               firstregfpu:=regcounter;
                break;
             end;
-          inc(r.number,NR_R1-NR_R0);
-        end;
+
+      usesgpr:=false;
+      if not (po_assembler in aktprocdef.procoptions) then
+        for regcounter2:=RS_R13 to RS_R31 do
+          begin
+            if regcounter2 in rg.usedintbyproc then
+              begin
+                 usesgpr:=true;
+                 firstreggpr.enum:=R_INTREGISTER;
+                 firstreggpr.number:=regcounter2 shl 8;
+                 break;
+              end;
+            inc(r.number,NR_R1-NR_R0);
+          end;
 
       offset:= 0;
 
@@ -1464,11 +1464,14 @@ const
         localsize:=align(localsize,16);
         tppcprocinfo(procinfo).localsize:=localsize;
 
-        r.enum:=R_INTREGISTER;
-        r.number:=NR_STACK_POINTER_REG;
-        reference_reset_base(href,r,-localsize);
-        a_load_store(list,A_STWU,r,href);
-          { this also stores the old stack pointer in the new stack frame }
+        if (localsize <> 0) then
+          begin
+            r.enum:=R_INTREGISTER;
+            r.number:=NR_STACK_POINTER_REG;
+            reference_reset_base(href,r,-localsize);
+            a_load_store(list,A_STWU,r,href);
+            { this also stores the old stack pointer in the new stack frame }
+          end;
       end;
 
     procedure tcgppc.g_return_from_proc_mac(list : taasmoutput;parasize : aword);
@@ -2212,7 +2215,13 @@ begin
 end.
 {
   $Log$
-  Revision 1.77  2003-04-06 16:39:11  jonas
+  Revision 1.78  2003-04-16 09:26:55  jonas
+    * assembler procedures now again get a stackframe if they have local
+      variables. No space is reserved for a function result however.
+      Also, the register parameters aren't automatically saved on the stack
+      anymore in assembler procedures.
+
+  Revision 1.77  2003/04/06 16:39:11  jonas
     * don't generate entry/exit code for assembler procedures
 
   Revision 1.76  2003/03/22 18:01:13  jonas

+ 16 - 3
compiler/psub.pas

@@ -113,8 +113,15 @@ implementation
               akttokenpos:=aktprocsym.fileinfo;
               aktprocdef.funcretsym:=tfuncretsym.create(aktprocsym.name,aktprocdef.rettype);
               { insert in local symtable }
-              symtablestack.insert(aktprocdef.funcretsym);
-              symtablestack.insertvardata(aktprocdef.funcretsym);
+{$ifdef powerpc}
+              { this requires us to setup a stack frame, which gives problem in the linux syscall helpers (JM) }
+              if not(po_assembler in aktprocdef.procoptions) or
+                 not(paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption)) then
+{$endif powerpc}
+                begin
+                  symtablestack.insert(aktprocdef.funcretsym);
+                  symtablestack.insertvardata(aktprocdef.funcretsym);
+                end;
               akttokenpos:=storepos;
 
 (*            already done by
@@ -857,7 +864,13 @@ implementation
 end.
 {
   $Log$
-  Revision 1.96  2003-04-05 21:09:31  jonas
+  Revision 1.97  2003-04-16 09:26:55  jonas
+    * assembler procedures now again get a stackframe if they have local
+      variables. No space is reserved for a function result however.
+      Also, the register parameters aren't automatically saved on the stack
+      anymore in assembler procedures.
+
+  Revision 1.96  2003/04/05 21:09:31  jonas
     * several ppc/generic result offset related fixes. The "normal" result
       offset seems now to be calculated correctly and a lot of duplicate
       calculations have been removed. Nested functions accessing the parent's