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

* 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