Sfoglia il codice sorgente

* framepointer fixes for sparc
* parent framepointer code more generic

peter 22 anni fa
parent
commit
32d076480b

+ 33 - 29
compiler/cgbase.pas

@@ -77,7 +77,7 @@ unit cgbase;
              On the PowerPC, this is used to store the offset where the
              frame pointer from the outer procedure is stored.
           }
-          framepointer_offset : longint;
+          parent_framepointer_offset : longint;
           {# firsttemp position }
           firsttemp_offset : longint;
 
@@ -114,23 +114,21 @@ unit cgbase;
           constructor create(aparent:tprocinfo);virtual;
           destructor destroy;override;
 
-          procedure allocate_interrupt_parameter;virtual;
+          procedure allocate_parent_framepointer_parameter;virtual;
 
-          procedure allocate_implicit_parameter;virtual;
+          procedure allocate_interrupt_parameter;virtual;
 
           { Allocate framepointer so it can not be used by the
             register allocator }
-          procedure allocate_framepointer;virtual;
+          procedure allocate_framepointer_reg;virtual;
+
+          procedure allocate_push_parasize(size:longint);virtual;
+
+          function calc_stackframe_size:longint;virtual;
 
           { Does the necessary stuff before a procedure body is compiled }
           procedure handle_body_start;virtual;
 
-          { This is called by parser, after the header of a subroutine is parsed.
-            If the local symtable offset depends on the para symtable size, the
-            necessary stuff must be done here.
-          }
-          procedure after_header;virtual;
-
           { This procedure is called after the pass 1 of the subroutine body is done.
             Here the address fix ups to generate code for the body must be done.
           }
@@ -319,7 +317,7 @@ implementation
       begin
         parent:=aparent;
         procdef:=nil;
-        framepointer_offset:=0;
+        parent_framepointer_offset:=0;
         firsttemp_offset:=0;
         flags:=[];
         framepointer.enum:=R_INTREGISTER;
@@ -340,16 +338,34 @@ implementation
       end;
 
 
+    procedure tprocinfo.allocate_parent_framepointer_parameter;
+      begin
+        parent_framepointer_offset:=procdef.parast.address_fixup;
+        inc(procdef.parast.address_fixup,POINTER_SIZE);
+      end;
+
+
     procedure tprocinfo.allocate_interrupt_parameter;
       begin
       end;
 
 
-    procedure tprocinfo.allocate_framepointer;
+    procedure tprocinfo.allocate_framepointer_reg;
       begin
       end;
 
 
+    procedure tprocinfo.allocate_push_parasize(size:longint);
+      begin
+      end;
+
+
+    function tprocinfo.calc_stackframe_size:longint;
+      begin
+        result:=procdef.localst.datasize+tg.gettempsize;
+      end;
+
+
     procedure tprocinfo.handle_body_start;
       var
         paramloc : tparalocation;
@@ -395,22 +411,6 @@ implementation
       end;
 
 
-    procedure tprocinfo.allocate_implicit_parameter;
-      begin
-         { Insert implicit parameters, will be removed in the future }
-         if (procdef.parast.symtablelevel>normal_function_level) then
-           begin
-              framepointer_offset:=procdef.parast.address_fixup;
-              inc(procdef.parast.address_fixup,POINTER_SIZE);
-           end;
-      end;
-
-
-    procedure tprocinfo.after_header;
-      begin
-      end;
-
-
     procedure tprocinfo.after_pass1;
       begin
       end;
@@ -571,7 +571,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.56  2003-06-13 21:19:30  peter
+  Revision 1.57  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.56  2003/06/13 21:19:30  peter
     * current_procdef removed, use current_procinfo.procdef instead
 
   Revision 1.55  2003/06/12 16:43:07  peter

+ 33 - 1
compiler/cgobj.pas

@@ -311,6 +311,9 @@ unit cgobj;
           }
          procedure g_exception_reason_load(list : taasmoutput; const href : treference);virtual;
 
+          procedure g_load_parent_framepointer(list:taasmoutput;parentsymtable:tsymtable;reg:tregister);
+          procedure g_save_parent_framepointer_param(list:taasmoutput);virtual;
+
           procedure g_maybe_testself(list : taasmoutput;reg:tregister);
           procedure g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef);
           {# This should emit the opcode to copy len bytes from the source
@@ -1353,6 +1356,31 @@ unit cgobj;
       end;
 
 
+    procedure tcg.g_load_parent_framepointer(list:taasmoutput;parentsymtable:tsymtable;reg:tregister);
+      var
+        href : treference;
+        i : integer;
+      begin
+        { make a reference }
+        reference_reset_base(href,current_procinfo.framepointer,PARENT_FRAMEPOINTER_OFFSET);
+        cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg);
+        { walk parents }
+        i:=current_procinfo.procdef.parast.symtablelevel-1;
+        while (i>parentsymtable.symtablelevel) do
+          begin
+             { make a reference }
+             reference_reset_base(href,reg,PARENT_FRAMEPOINTER_OFFSET);
+             cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg);
+             dec(i);
+          end;
+      end;
+
+
+    procedure tcg.g_save_parent_framepointer_param(list:taasmoutput);
+      begin
+      end;
+
+
     procedure tcg.g_copyshortstring(list : taasmoutput;const source,dest : treference;len:byte;delsource,loadref : boolean);
       begin
 {$ifdef FPC}
@@ -1767,7 +1795,11 @@ finalization
 end.
 {
   $Log$
-  Revision 1.113  2003-07-02 22:18:04  peter
+  Revision 1.114  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.113  2003/07/02 22:18:04  peter
     * paraloc splitted in callerparaloc,calleeparaloc
     * sparc calling convention updates
 

+ 8 - 1
compiler/i386/cpubase.inc

@@ -181,6 +181,9 @@
       fpu_result_reg = R_ST;
       mmresultreg = R_MM0;
 
+      { Offset where the parent framepointer is pushed }
+      PARENT_FRAMEPOINTER_OFFSET = 8;
+
 {*****************************************************************************
                        GCC /ABI linking information
 *****************************************************************************}
@@ -205,7 +208,11 @@
 
 {
   $Log$
-  Revision 1.6  2003-06-03 13:01:59  daniel
+  Revision 1.7  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.6  2003/06/03 13:01:59  daniel
     * Register allocator finished
 
   Revision 1.5  2003/05/31 15:05:28  peter

+ 7 - 3
compiler/i386/cpupi.pas

@@ -34,7 +34,7 @@ unit cpupi;
     type
        ti386procinfo = class(tcgprocinfo)
           procedure allocate_interrupt_parameter;override;
-          procedure allocate_framepointer;override;
+          procedure allocate_framepointer_reg;override;
        end;
 
 
@@ -52,7 +52,7 @@ unit cpupi;
       end;
 
 
-    procedure ti386procinfo.allocate_framepointer;
+    procedure ti386procinfo.allocate_framepointer_reg;
       begin
         if framepointer.number=NR_EBP then
           begin
@@ -69,7 +69,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.8  2003-06-13 21:19:31  peter
+  Revision 1.9  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.8  2003/06/13 21:19:31  peter
     * current_procdef removed, use current_procinfo.procdef instead
 
   Revision 1.7  2003/06/12 18:12:49  jonas

+ 12 - 29
compiler/ncgcal.pas

@@ -90,9 +90,6 @@ implementation
 {$else cpu64bit}
       cg64f32,
 {$endif cpu64bit}
-{$ifdef powerpc}
-      cpupi,
-{$endif powerpc}
       ncgutil,cgobj,tgobj,regvars,rgobj,rgcpu;
 
 
@@ -370,12 +367,11 @@ implementation
       var
         href : treference;
         hregister : tregister;
-        i : integer;
       begin
         { this routine is itself not nested }
         if current_procinfo.procdef.parast.symtablelevel=(tprocdef(procdefinition).parast.symtablelevel) then
           begin
-            reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
+            reference_reset_base(href,current_procinfo.framepointer,current_procinfo.parent_framepointer_offset);
             cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(exprasmlist,1));
           end
         { one nesting level }
@@ -384,18 +380,10 @@ implementation
             cg.a_param_reg(exprasmlist,OS_ADDR,current_procinfo.framepointer,paramanager.getintparaloc(exprasmlist,1));
           end
         { very complex nesting level ... }
-        else if (current_procinfo.procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then
+       else if (current_procinfo.procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then
           begin
             hregister:=rg.getaddressregister(exprasmlist);
-            reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
-            cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
-            i:=current_procinfo.procdef.parast.symtablelevel;
-            while (i>tprocdef(procdefinition).parast.symtablelevel) do
-              begin
-                reference_reset_base(href,hregister,current_procinfo.framepointer_offset);
-                cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
-                dec(i);
-              end;
+            cg.g_load_parent_framepointer(exprasmlist,tprocdef(procdefinition).parast,hregister);
             cg.a_param_reg(exprasmlist,OS_ADDR,hregister,paramanager.getintparaloc(exprasmlist,1));
             rg.ungetaddressregister(exprasmlist,hregister);
           end;
@@ -1050,11 +1038,8 @@ implementation
          if pop_size>0 then
            pop_parasize(pop_size);
 
-{$ifdef powerpc}
-         { this calculation must be done in pass_1 anyway, so don't worry }
-         if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
-           tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
-{$endif powerpc}
+         { Reserve space for storing parameters that will be pushed }
+         current_procinfo.allocate_push_parasize(pushedparasize);
 
          { Restore }
          pushedparasize:=oldpushedparasize;
@@ -1252,9 +1237,6 @@ implementation
 {$endif extdebug}
            end;
 
-         { Calculate offsets }
-         current_procinfo.after_header;
-
          exprasmList.concat(Tai_Marker.Create(InlineStart));
 {$ifdef extdebug}
          exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
@@ -1398,11 +1380,8 @@ implementation
          { process the inline code }
          secondpass(inlinecode);
 
-{$ifdef powerpc}
-         { this calculation must be done in pass_1 anyway, so don't worry }
-         if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
-           tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
-{$endif powerpc}
+         { Reserve space for storing parameters that will be pushed }
+         current_procinfo.allocate_push_parasize(pushedparasize);
 
          { Restore }
          pushedparasize:=oldpushedparasize;
@@ -1541,7 +1520,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.98  2003-07-06 15:31:20  daniel
+  Revision 1.99  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.98  2003/07/06 15:31:20  daniel
     * Fixed register allocator. *Lots* of fixes.
 
   Revision 1.97  2003/07/05 20:21:26  jonas

+ 6 - 17
compiler/ncgld.pas

@@ -213,22 +213,7 @@ implementation
                                   if (current_procinfo.procdef.parast.symtablelevel>symtable.symtablelevel) then
                                     begin
                                        hregister:=rg.getaddressregister(exprasmlist);
-                                       { make a reference }
-                                       reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
-                                       cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
-                                       { walk parents }
-                                       i:=current_procinfo.procdef.parast.symtablelevel-1;
-                                       while (i>symtable.symtablelevel) do
-                                         begin
-                                            { make a reference }
-{$ifdef powerpc}
-                                            reference_reset_base(href,hregister,current_procinfo.framepointer_offset);
-{$else powerpc}
-                                            reference_reset_base(href,hregister,target_info.first_parm_offset);
-{$endif powerpc}
-                                            cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
-                                            dec(i);
-                                         end;
+                                       cg.g_load_parent_framepointer(exprasmlist,symtable,hregister);
                                        location.reference.base:=hregister;
                                     end;
                                 end;
@@ -954,7 +939,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.73  2003-07-06 15:25:54  jonas
+  Revision 1.74  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.73  2003/07/06 15:25:54  jonas
     * newra fix for threadvars
 
   Revision 1.72  2003/06/15 15:13:12  jonas

+ 91 - 88
compiler/ncgutil.pas

@@ -68,7 +68,7 @@ interface
     procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean);
 
     procedure gen_entry_code(list:TAAsmoutput;inlined:boolean);
-    procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
+    procedure gen_stackalloc_code(list:Taasmoutput);
     procedure gen_exit_code(list:Taasmoutput;inlined:boolean);
 
 (*
@@ -1567,32 +1567,34 @@ implementation
           code, since temp. allocation might occur before - carl
         }
 
-        if assigned(current_procinfo.procdef.parast) then
+        if assigned(current_procinfo.procdef.parast) and
+           not (po_assembler in current_procinfo.procdef.procoptions) then
           begin
-             if not (po_assembler in current_procinfo.procdef.procoptions) then
-               begin
-                 { move register parameters which aren't regable into memory                               }
-                 { we do this before init_paras because that one calls routines which may overwrite these  }
-                 { registers and it also expects the values to be in memory                                }
-                 hp:=tparaitem(current_procinfo.procdef.para.first);
-                 while assigned(hp) do
-                   begin
-                     if Tvarsym(hp.parasym).reg.enum>R_INTREGISTER then
-                       internalerror(200301081);
-                     if (tvarsym(hp.parasym).reg.enum<>R_NO) then
-                       begin
-                         cg.a_load_param_reg(list,hp.calleeparaloc,tvarsym(hp.parasym).reg);
-                       end
-                     else if (hp.calleeparaloc.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,current_procinfo.framepointer,tvarsym(hp.parasym).adjusted_address);
-                         cg.a_load_param_ref(list,hp.calleeparaloc,href);
-                       end;
-                     hp:=tparaitem(hp.next);
-                   end;
-               end;
+            { save framepointer in memory }
+            if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
+              cg.g_save_parent_framepointer_param(list);
+
+            { move register parameters which aren't regable into memory                               }
+            { we do this before init_paras because that one calls routines which may overwrite these  }
+            { registers and it also expects the values to be in memory                                }
+            hp:=tparaitem(current_procinfo.procdef.para.first);
+            while assigned(hp) do
+              begin
+                if Tvarsym(hp.parasym).reg.enum>R_INTREGISTER then
+                  internalerror(200301081);
+                if (tvarsym(hp.parasym).reg.enum<>R_NO) then
+                  begin
+                    cg.a_load_param_reg(list,hp.calleeparaloc,tvarsym(hp.parasym).reg);
+                  end
+                else if (hp.calleeparaloc.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,current_procinfo.framepointer,tvarsym(hp.parasym).adjusted_address);
+                    cg.a_load_param_ref(list,hp.calleeparaloc,href);
+                  end;
+                hp:=tparaitem(hp.next);
+              end;
           end;
 
         { for the save all registers we can simply use a pusha,popa which
@@ -1618,76 +1620,73 @@ implementation
       end;
 
 
-    procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
-
-    var hs:string;
-
-    begin
-      {************************* Stack allocation **************************}
-      { and symbol entry point as well as debug information                 }
-      { will be inserted in front of the rest of this list.                 }
-      { Insert alignment and assembler names }
-      { Align, gprof uses 16 byte granularity }
-      if (cs_profile in aktmoduleswitches) then
-        list.concat(Tai_align.create(16))
-      else
-        list.concat(Tai_align.create(aktalignment.procalign));
+    procedure gen_stackalloc_code(list:Taasmoutput);
+      var
+        hs : string;
+        stackframe : longint;
+      begin
+        {************************* Stack allocation **************************}
+        { and symbol entry point as well as debug information                 }
+        { will be inserted in front of the rest of this list.                 }
+        { Insert alignment and assembler names }
+        { Align, gprof uses 16 byte granularity }
+        if (cs_profile in aktmoduleswitches) then
+          list.concat(Tai_align.create(16))
+        else
+          list.concat(Tai_align.create(aktalignment.procalign));
 
 {$ifdef GDB}
-      if (cs_debuginfo in aktmoduleswitches) then
-        begin
-          if (po_public in current_procinfo.procdef.procoptions) then
-            Tprocsym(current_procinfo.procdef.procsym).is_global:=true;
-          current_procinfo.procdef.concatstabto(list);
-          Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true;
-        end;
+        if (cs_debuginfo in aktmoduleswitches) then
+          begin
+            if (po_public in current_procinfo.procdef.procoptions) then
+              Tprocsym(current_procinfo.procdef.procsym).is_global:=true;
+            current_procinfo.procdef.concatstabto(list);
+            Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true;
+          end;
 {$endif GDB}
 
-      repeat
-        hs:=current_procinfo.procdef.aliasnames.getfirst;
-        if hs='' then
-          break;
+        repeat
+          hs:=current_procinfo.procdef.aliasnames.getfirst;
+          if hs='' then
+            break;
 {$ifdef GDB}
-        if (cs_debuginfo in aktmoduleswitches) and
-           target_info.use_function_relative_addresses then
-        list.concat(Tai_stab_function_name.create(strpnew(hs)));
+          if (cs_debuginfo in aktmoduleswitches) and
+             target_info.use_function_relative_addresses then
+          list.concat(Tai_stab_function_name.create(strpnew(hs)));
 {$endif GDB}
-        if (cs_profile in aktmoduleswitches) or
-           (po_public in current_procinfo.procdef.procoptions) then
-          list.concat(Tai_symbol.createname_global(hs,0))
-        else
-          list.concat(Tai_symbol.createname(hs,0));
-      until false;
-
-      stackframe:=stackframe+tg.gettempsize;
-{$ifndef m68k}
-          { give a warning if the limit of local variables is reached }
-      if stackframe>maxlocalsize then
-        message(cg_w_localsize_too_big);
-{$endif}
+          if (cs_profile in aktmoduleswitches) or
+             (po_public in current_procinfo.procdef.procoptions) then
+            list.concat(Tai_symbol.createname_global(hs,0))
+          else
+            list.concat(Tai_symbol.createname(hs,0));
+        until false;
+
+        { Calculate size of stackframe }
+        stackframe:=current_procinfo.calc_stackframe_size;
+
 {$ifndef powerpc}
-      { at least for the ppc this applies always, so this code isn't usable (FK) }
-      { omit stack frame ? }
-      if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
-        begin
-          CGmessage(cg_d_stackframe_omited);
-          if stackframe<>0 then
-            cg.g_stackpointer_alloc(list,stackframe);
-        end
-      else
+        { at least for the ppc this applies always, so this code isn't usable (FK) }
+        { omit stack frame ? }
+        if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
+          begin
+            CGmessage(cg_d_stackframe_omited);
+            if stackframe<>0 then
+              cg.g_stackpointer_alloc(list,stackframe);
+          end
+        else
 {$endif powerpc}
-        begin
-          if (po_interrupt in current_procinfo.procdef.procoptions) then
-            cg.g_interrupt_stackframe_entry(list);
+          begin
+            if (po_interrupt in current_procinfo.procdef.procoptions) then
+              cg.g_interrupt_stackframe_entry(list);
 
-          cg.g_stackframe_entry(list,stackframe);
+            cg.g_stackframe_entry(list,stackframe);
 
-          {Never call stack checking before the standard system unit
-           has been initialized.}
-           if (cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit) then
-             cg.g_stackcheck(list,stackframe);
-        end;
-    end;
+            {Never call stack checking before the standard system unit
+             has been initialized.}
+             if (cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit) then
+               cg.g_stackcheck(list,stackframe);
+          end;
+      end;
 
 
     procedure gen_exit_code(list : TAAsmoutput;inlined:boolean);
@@ -1789,7 +1788,7 @@ implementation
                 (current_procinfo.procdef.parast.symtablelevel>normal_function_level) then
               list.concat(Tai_stabs.Create(strpnew(
                '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
-               tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.framepointer_offset))));
+               tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.parent_framepointer_offset))));
 
             if (not is_void(current_procinfo.procdef.rettype.def)) then
               begin
@@ -1988,7 +1987,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.129  2003-07-06 15:31:20  daniel
+  Revision 1.130  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.129  2003/07/06 15:31:20  daniel
     * Fixed register allocator. *Lots* of fixes.
 
   Revision 1.128  2003/07/02 22:18:04  peter

+ 6 - 2
compiler/pass_2.pas

@@ -302,7 +302,7 @@ implementation
 //              cleanup_regvars(current_procinfo.aktexitcode);
 {$endif i386}
 
-              current_procinfo.allocate_framepointer;
+              current_procinfo.allocate_framepointer_reg;
 
               do_secondpass(p);
 
@@ -316,7 +316,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.60  2003-07-06 15:31:20  daniel
+  Revision 1.61  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.60  2003/07/06 15:31:20  daniel
     * Fixed register allocator. *Lots* of fixes.
 
   Revision 1.59  2003/07/06 10:18:47  jonas

+ 6 - 8
compiler/pmodules.pas

@@ -768,7 +768,7 @@ implementation
             internalerror(200304253);
         end;
         include(current_procinfo.flags,pi_do_call);
-        gen_stackalloc_code(list,0);
+        gen_stackalloc_code(list);
         gen_entry_code(list,false);
         gen_initialize_code(list,false);
         gen_finalize_code(list,false);
@@ -1312,12 +1312,6 @@ implementation
             pd:=create_main_proc('main',potype_proginit,st);
             pd.aliasnames.insert('PASCALMAIN');
           end;
-{$IFDEF SPARC}
-         current_procinfo.After_Header;
-{main function is declared as
-  PROCEDURE main(ArgC:Integer;ArgV,EnvP:ARRAY OF PChar):Integer;CDECL;
-So, all parameters are passerd into registers in sparc architecture.}
-{$ENDIF SPARC}
          tcgprocinfo(current_procinfo).parse_body;
          tcgprocinfo(current_procinfo).generate_code;
          tcgprocinfo(current_procinfo).resetprocdef;
@@ -1452,7 +1446,11 @@ So, all parameters are passerd into registers in sparc architecture.}
 end.
 {
   $Log$
-  Revision 1.114  2003-06-13 21:19:31  peter
+  Revision 1.115  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.114  2003/06/13 21:19:31  peter
     * current_procdef removed, use current_procinfo.procdef instead
 
   Revision 1.113  2003/06/09 12:23:30  peter

+ 8 - 6
compiler/psub.pas

@@ -654,7 +654,7 @@ implementation
           end;
 
         stackalloccode:=Taasmoutput.create;
-        gen_stackalloc_code(stackalloccode,0);
+        gen_stackalloc_code(stackalloccode);
         stackalloccode.convert_registers;
         aktproccode.insertlist(stackalloccode);
         stackalloccode.destroy;
@@ -1076,15 +1076,13 @@ implementation
                pd.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_init_paras,nil);
 
              { Update parameter information }
-             current_procinfo.allocate_implicit_parameter;
+             if (current_procinfo.procdef.parast.symtablelevel>normal_function_level) then
+               current_procinfo.allocate_parent_framepointer_parameter;
 
              { add implicit pushes for interrupt routines }
              if (po_interrupt in pd.procoptions) then
                current_procinfo.allocate_interrupt_parameter;
 
-             { Calculate offsets }
-             current_procinfo.after_header;
-
              { set _FAIL as keyword if constructor }
              if (pd.proctypeoption=potype_constructor) then
               begin
@@ -1254,7 +1252,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.131  2003-07-06 15:31:21  daniel
+  Revision 1.132  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.131  2003/07/06 15:31:21  daniel
     * Fixed register allocator. *Lots* of fixes.
 
   Revision 1.130  2003/07/05 20:15:24  jonas

+ 21 - 3
compiler/sparc/cgcpu.pas

@@ -74,6 +74,7 @@ interface
         procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override;
         procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override;
         procedure g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);override;
+        procedure g_save_parent_framepointer_param(list:taasmoutput);override;
         procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
         procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override;
         procedure g_restore_frame_pointer(list:TAasmOutput);override;
@@ -637,10 +638,10 @@ implementation
                         end;
                     end
                   else
-                    list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,r));
+                    list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),r));
                 end
               else
-                list.concat(taicpu.op_reg_const_reg(A_ADD,zeroreg,ref.offset,r));
+                list.concat(taicpu.op_reg_const_reg(A_ADD,zeroreg,aword(ref.offset),r));
             end
         else
         { Both base and index }
@@ -868,6 +869,19 @@ implementation
 
   { *********** entry/exit code and address loading ************ }
 
+    procedure tcgsparc.g_save_parent_framepointer_param(list:taasmoutput);
+      var
+        hreg : tregister;
+        href : treference;
+      begin
+        reference_reset_base(href,current_procinfo.framepointer,PARENT_FRAMEPOINTER_OFFSET);
+        { Parent framepointer is always pushed in o0 }
+        hreg.enum:=R_INTREGISTER;
+        hreg.number:=NR_O0;
+        a_load_reg_ref(list,OS_ADDR,OS_ADDR,hreg,href);
+      end;
+
+
     procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
       var
         r : tregister;
@@ -1241,7 +1255,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.62  2003-07-03 21:09:53  peter
+  Revision 1.63  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.62  2003/07/03 21:09:53  peter
     * delay slot NOPs and comments added
     * a_loadaddr_ref_reg fixed and optimized to reuse passed register
       if it is not used by the ref

+ 11 - 4
compiler/sparc/cpubase.pas

@@ -785,9 +785,10 @@ type
       usableregsaddr = [];
       c_countusableregsaddr = 0;
 
-      firstsaveintreg = RS_G0; { L0..L7 are already saved, I0..O7 are parameter }
-      lastsaveintreg = RS_G7;
-      firstsavefpureg = R_F0;
+{$warning firstsaveintreg shall be RS_NO}
+      firstsaveintreg = RS_L0; { Temporary, having RS_NO is broken }
+      lastsaveintreg = RS_L0; { L0..L7 are already saved, I0..O7 are parameter }
+      firstsavefpureg = R_F2; { F0..F1 is used for return value }
       lastsavefpureg = R_F31;
       firstsavemmreg = R_NO;
       lastsavemmreg = R_NO;
@@ -933,6 +934,8 @@ type
       FPU_RESULT_REG = R_F0;
       mmresultreg = R_NO;
 
+      PARENT_FRAMEPOINTER_OFFSET = 68; { o0 }
+
 {*****************************************************************************
                        GCC /ABI linking information
 *****************************************************************************}
@@ -1051,7 +1054,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.44  2003-07-02 22:18:04  peter
+  Revision 1.45  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.44  2003/07/02 22:18:04  peter
     * paraloc splitted in callerparaloc,calleeparaloc
     * sparc calling convention updates
 

+ 8 - 3
compiler/sparc/cpupara.pas

@@ -122,14 +122,15 @@ implementation
     procedure TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee);
       var
         nextintreg : tsuperregister;
-        nextfloatreg : toldregister;
         stack_offset : longint;
         hp : tparaitem;
         is_64bit : boolean;
         paraloc : tparalocation;
       begin
         nextintreg:=RS_O0;
-        nextfloatreg:=R_F0;
+        { Nested procedures have the parent framepoint in o0 }
+        if p.parast.symtablelevel>normal_function_level then
+          inc(NextIntReg);
         stack_offset:=92;
         hp:=TParaItem(p.para.First);
         while assigned(hp) do
@@ -275,7 +276,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.23  2003-07-05 20:11:41  jonas
+  Revision 1.24  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.23  2003/07/05 20:11:41  jonas
     * create_paraloc_info() is now called separately for the caller and
       callee info
     * fixed ppc cycle

+ 48 - 59
compiler/sparc/cpupi.pas

@@ -1,4 +1,4 @@
-{*****************************************************************************
+{
     $Id$
     Copyright (c) 2002 by Florian Klaempfl
 
@@ -18,11 +18,11 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- ****************************************************************************}
-{ This unit contains the CPU specific part of tprocinfo. }
+ ****************************************************************************
+}
 unit cpupi;
 
-{$I fpcdefs.inc}
+{$i fpcdefs.inc}
 
 interface
 
@@ -33,75 +33,64 @@ interface
 
   type
     TSparcProcInfo=class(tcgprocinfo)
-      { overall size of allocated stack space, currently this is used for the
-        PowerPC only }
-      LocalSize:aword;
-      {max of space need for parameters, currently used by the PowerPC port only}
-      maxpushedparasize:aword;
+    private
+      maxpushedparasize : longint;
+    public
       constructor create(aparent:tprocinfo);override;
-      { According the the SPARC ABI the standard stack frame must include :
-        *  16 word save for the in and local registers in case of overflow/underflow.
-           this save area always must exist at the %o6+0,
-        *  software conventions requires space for the aggregate return value pointer, even if the word is not used,
-        *  althogh the first six words of arguments reside in registers, the standard
-           stack frame reserves space for them. Arguments beond the sixth reside on the
-           stack as in the Intel architecture,
-        * other areas depend on the compiler and the code being compiled. The
-          standard calling sequence does not define a maximum stack frame size, nor does
-          it restrict how a language system uses the "unspecified" areas of the standard
-          stack frame.}
-      procedure after_header;override;
-      procedure after_pass1;override;
+      procedure allocate_push_parasize(size:longint);override;
+      function calc_stackframe_size:longint;override;
     end;
 
 implementation
-uses
-        tgobj,paramgr,symsym,systems;
-
-constructor TSparcprocinfo.create(aparent:tprocinfo);
-        begin
-                inherited create(aparent);
-                maxpushedparasize:=0;
-                LocalSize:=(16+1)*4;
-        {First 16 words are in the frame are used to save registers in case of a
-    register overflow/underflow.The 17th word is used to save the address of
-    the variable which will receive the return value of the called function}
-//    Return_Offset:=16*4;
-        end;
-
-    procedure TSparcprocinfo.after_header;
+
+    uses
+      globtype,systems,
+      tgobj,paramgr,symconst,symsym;
+
+    constructor tsparcprocinfo.create(aparent:tprocinfo);
+      begin
+        inherited create(aparent);
+        maxpushedparasize:=0;
+      end;
+
+
+    procedure tsparcprocinfo.allocate_push_parasize(size:longint);
       begin
-        { this value is necessary for nested procedures }
-        if assigned(procdef.localst) then
-          procdef.localst.address_fixup:=align(procdef.parast.address_fixup+procdef.parast.datasize,16);
+        if size>maxpushedparasize then
+          maxpushedparasize:=size;
       end;
 
-procedure TSparcProcInfo.after_pass1;
-        begin
-    with ProcDef do
+
+    function TSparcProcInfo.calc_stackframe_size:longint;
+      var
+        savearea : longint;
       begin
-            {Reserve the stack for copying parameters passed into registers. By
-        default we reserve space for the 6 input registers if the function had
-        less parameters. Otherwise, we allocate data sizeof parameters}
-        if parast.datasize>6*4
-        then
-          localst.address_fixup:=parast.address_fixup+parast.datasize
-        else
-          procdef.localst.address_fixup:=parast.address_fixup+6*4;
-                    firsttemp_offset:=localst.address_fixup+localst.datasize;
-        with tg do
-          begin
-                        SetFirstTemp(firsttemp_offset);
-                        //LastTemp:=firsttemp_offset;
-          end;
+        { ABI requires at least space to save 6 arguments }
+        savearea:=procdef.parast.address_fixup+max(maxpushedparasize,6*4);
+        {
+          Stackframe layout:
+          %fp
+            <locals>
+            <temp>
+            <arguments for calling>
+            <return pointer for calling>
+            <register window save area for calling>
+          %sp
+        }
+        result:=procdef.localst.datasize+tg.gettempsize+savearea;
       end;
-        end;
+
+
 begin
   cprocinfo:=TSparcProcInfo;
 end.
 {
   $Log$
-  Revision 1.17  2003-06-13 21:19:32  peter
+  Revision 1.18  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.17  2003/06/13 21:19:32  peter
     * current_procdef removed, use current_procinfo.procdef instead
 
   Revision 1.16  2003/05/30 23:57:08  peter

+ 26 - 40
compiler/sparc/ncpucall.pas

@@ -1,8 +1,8 @@
-{******************************************************************************
+{
     $Id$
     Copyright (c) 1998-2002 by Florian Klaempfl
 
-    Generate SPARC assembler for in call nodes
+    Generate sparc assembler for in call nodes
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -18,51 +18,37 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- ****************************************************************************}
+ ****************************************************************************
+}
 unit ncpucall;
-{$INCLUDE fpcdefs.inc}
+
+{$i fpcdefs.inc}
+
 interface
-uses
-  symdef,node,ncal,ncgcal;
-type
-  TSparcCallNode=class(TCgCallNode)
-    function pass_1:TNode;override;
-{Under SPARC, the frame pointer is automatically set by the SAVE instruction
-which is part of the stardrad calling mechanism. This function will do nothing.
-the frame pointer register is the stack pointer register of the caller, and is
-set when generating function prologue in cgcpu.tcgSPARC.g_stackframe_entry}
-    procedure push_framepointer;override;
-  end;
+
+    uses
+      ncgcal;
+
+    type
+       tsparccallnode = class(tcgcallnode)
+       end;
+
+
 implementation
-uses
-  systems,
-  cutils,verbose,
-  paramgr,
-  cgbase,
-  nmem,nld,ncnv,
-  cgobj,tgobj,rgobj,rgcpu,cgcpu,cpupi;
-function TSparcCallNode.pass_1:TNode;
-  begin
-    result:=inherited pass_1;
-    if assigned(result)
-    then
-      exit;
-    if ProcDefinition is TProcDef
-    then
-      with TProcDef(procdefinition).parast do
-        if datasize>TSparcProcInfo(current_procinfo).maxpushedparasize
-        then
-          TSparcProcInfo(current_procinfo).maxpushedparasize:=datasize;
-  end;
-procedure TSparcCallNode.push_framepointer;
-  begin
-  end;
+
+    uses
+      ncal;
+
 begin
-   ccallnode:=TSparcCallNode;
+  ccallnode:=TSparcCallNode;
 end.
 {
   $Log$
-  Revision 1.12  2003-06-13 21:19:32  peter
+  Revision 1.13  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.12  2003/06/13 21:19:32  peter
     * current_procdef removed, use current_procinfo.procdef instead
 
   Revision 1.11  2003/04/28 09:49:58  mazen

+ 8 - 4
compiler/systems/i_linux.pas

@@ -403,8 +403,8 @@ unit i_linux;
                 localalignmin   : 0;
                 localalignmax   : 4;
                 paraalign       : 4;
-                recordalignmin  : 0;
-                recordalignmax  : 2;
+                recordalignmin  : 4;
+                recordalignmax  : 4;
                 maxCrecordalign : 4
               );
             first_parm_offset : (16+1)*4;
@@ -447,14 +447,18 @@ initialization
 {$endif CPUSPARC}
 {$ifdef CPUPOWERPC}
   {$ifdef linux}
-    set_source_info(system_powerpc_linux_info); 
+    set_source_info(system_powerpc_linux_info);
   {$endif linux}
 {$endif CPUPOWERPC}
 
 end.
 {
   $Log$
-  Revision 1.8  2003-05-31 18:14:06  jonas
+  Revision 1.9  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.8  2003/05/31 18:14:06  jonas
     * add default system for ppc
 
   Revision 1.7  2003/05/19 12:15:28  florian

+ 5 - 4
compiler/tgobj.pas

@@ -157,9 +157,6 @@ unit tgobj;
 {$else powerpc}
        direction:=-1;
 {$endif powerpc}
-{$IFDEF SPARC}
-        Direction:=1;
-{$ENDIF SPARC}
      end;
 
 
@@ -554,7 +551,11 @@ finalization
 end.
 {
   $Log$
-  Revision 1.35  2003-06-03 13:01:59  daniel
+  Revision 1.36  2003-07-06 17:58:22  peter
+    * framepointer fixes for sparc
+    * parent framepointer code more generic
+
+  Revision 1.35  2003/06/03 13:01:59  daniel
     * Register allocator finished
 
   Revision 1.34  2003/05/17 13:30:08  jonas