Kaynağa Gözat

+ support for passing parameters via pre-allocated stack space on i386
(override/adjust cgutils.use_fixed_stack to change conditions where
this is done, currently only activated for darwin-i386)
* make sure the stack is always aligned to 16 bytes on darwin-i386

git-svn-id: trunk@2840 -

Jonas Maebe 19 yıl önce
ebeveyn
işleme
9de2847865

+ 0 - 8
compiler/arm/cpupi.pas

@@ -37,7 +37,6 @@ unit cpupi;
           // procedure handle_body_start;override;
           // procedure after_pass1;override;
           procedure set_first_temp_offset;override;
-          procedure allocate_push_parasize(size: longint);override;
           function calc_stackframe_size:longint;override;
        end;
 
@@ -67,13 +66,6 @@ unit cpupi;
       end;
 
 
-    procedure tarmprocinfo.allocate_push_parasize(size:longint);
-      begin
-        if size>maxpushedparasize then
-          maxpushedparasize:=size;
-      end;
-
-
     function tarmprocinfo.calc_stackframe_size:longint;
       var
          firstfloatreg,lastfloatreg,

+ 15 - 0
compiler/cgutils.pas

@@ -113,8 +113,15 @@ unit cgutils;
     procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
     procedure location_swap(var destloc,sourceloc : tlocation);
 
+
+    { allocate room for parameters on the stack in the entry code? }
+    function use_fixed_stack: boolean;
+
 implementation
 
+uses
+  systems;
+
 {****************************************************************************
                                   TReference
 ****************************************************************************}
@@ -182,5 +189,13 @@ implementation
       end;
 
 
+    function use_fixed_stack: boolean;
+      begin
+{$ifdef i386}
+        result := (target_info.system = system_i386_darwin);
+{$else i386}
+        result := false;
+{$endif i386}
+      end;
 
 end.

+ 4 - 2
compiler/i386/cgcpu.pas

@@ -71,7 +71,8 @@ unit cgcpu;
 
     function use_push(const cgpara:tcgpara):boolean;
       begin
-        result:=assigned(cgpara.location) and
+        result:=(not use_fixed_stack) and
+                assigned(cgpara.location) and
                 (cgpara.location^.loc=LOC_REFERENCE) and
                 (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
       end;
@@ -295,7 +296,8 @@ unit cgcpu;
             list.concat(Taicpu.Op_none(A_IRET,S_NO));
           end
         { Routines with the poclearstack flag set use only a ret }
-        else if current_procinfo.procdef.proccalloption in clearstack_pocalls then
+        else if (current_procinfo.procdef.proccalloption in clearstack_pocalls) and
+                (not use_fixed_stack)  then
          begin
            { complex return values are removed from stack in C code PM }
            if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,

+ 11 - 2
compiler/i386/cpupara.pas

@@ -396,7 +396,8 @@ unit cpupara;
             hp.paraloc[side].intsize:=paralen;
             hp.paraloc[side].Alignment:=paraalign;
             { Copy to stack? }
-            if paracgsize=OS_NO then
+            if (paracgsize=OS_NO) or
+               (use_fixed_stack) then
               begin
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc^.loc:=LOC_REFERENCE;
@@ -406,6 +407,13 @@ unit cpupara;
                 else
                   paraloc^.reference.index:=NR_FRAME_POINTER_REG;
                 varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+
+                { don't let push_size return 16, because then we can    }
+                { read past the end of the heap since the value is only }
+                { 10 bytes long (JM)                                    }
+                if (paracgsize = OS_F80) and
+                   (target_info.system = system_i386_darwin) then
+                  paralen:=16;
                 paraloc^.reference.offset:=parasize;
                 if side=calleeside then
                   inc(paraloc^.reference.offset,target_info.first_parm_offset);
@@ -509,7 +517,8 @@ unit cpupara;
             else
               begin
                 { Copy to stack? }
-                if paracgsize=OS_NO then
+                if (use_fixed_stack) or
+                   (paracgsize=OS_NO) then
                   begin
                     paraloc:=hp.paraloc[side].add_location;
                     paraloc^.loc:=LOC_REFERENCE;

+ 14 - 2
compiler/i386/cpupi.pas

@@ -34,6 +34,7 @@ unit cpupi;
        ti386procinfo = class(tcgprocinfo)
          constructor create(aparent:tprocinfo);override;
          function calc_stackframe_size:longint;override;
+         procedure generate_parameter_info;override;
        end;
 
 
@@ -43,7 +44,8 @@ unit cpupi;
       cutils,
       systems,globals,
       tgobj,
-      cpubase;
+      cpubase,
+      cgutils;
 
     constructor ti386procinfo.create(aparent:tprocinfo);
       begin
@@ -59,10 +61,20 @@ unit cpupi;
         if (target_info.system <> system_i386_darwin) then
           result:=Align(tg.direction*tg.lasttemp,min(aktalignment.localalignmin,4))
         else
-          result:=Align(tg.direction*tg.lasttemp,min(aktalignment.localalignmin,16));
+          result:=tg.direction*tg.lasttemp+maxpushedparasize;
       end;
 
 
+    procedure ti386procinfo.generate_parameter_info;
+      begin
+        inherited generate_parameter_info;
+        { Para_stack_size is only used to determine how many bytes to remove }
+        { from the stack at the end of the procedure (in the "ret $xx").     }
+        { If the stack is fixed, nothing has to be removed by the callee     }
+        if use_fixed_stack then
+          para_stack_size := 0;
+      end;
+
 
 begin
    cprocinfo:=ti386procinfo;

+ 3 - 1
compiler/i386/n386cal.pas

@@ -43,7 +43,7 @@ implementation
     uses
       globtype,systems,
       cutils,verbose,globals,
-      cgbase,
+      cgbase,cgutils,
       cpubase,paramgr,
       aasmtai,aasmcpu,
       ncal,nbas,nmem,nld,ncnv,
@@ -66,6 +66,8 @@ implementation
       var
         hreg : tregister;
       begin
+        if (use_fixed_stack) then
+          exit;
         { better than an add on all processors }
         if pop_size=4 then
           begin

+ 0 - 8
compiler/powerpc/cpupi.pas

@@ -66,7 +66,6 @@ unit cpupi;
 
       begin
          inherited create(aparent);
-         maxpushedparasize:=0;
          first_save_int_reg:=32;
          first_save_fpu_reg:=32;
          needs_frame_pointer:=false;
@@ -126,13 +125,6 @@ unit cpupi;
 *)
 
 
-    procedure tppcprocinfo.allocate_push_parasize(size:longint);
-      begin
-        if size>maxpushedparasize then
-          maxpushedparasize:=size;
-      end;
-
-
     function tppcprocinfo.uses_stack_temps: boolean;
       begin
         result := tg.firsttemp <> tg.lasttemp;

+ 0 - 7
compiler/powerpc64/cpupi.pas

@@ -37,7 +37,6 @@ type
     parent_framepointer_offset: longint;
     constructor create(aparent: tprocinfo); override;
     procedure set_first_temp_offset; override;
-    procedure allocate_push_parasize(size: longint); override;
     function calc_stackframe_size: longint; override;
     function calc_stackframe_size(numgpr, numfpr : longint): longint;
 
@@ -87,12 +86,6 @@ begin
   end;
 end;
 
-procedure tppcprocinfo.allocate_push_parasize(size: longint);
-begin
-  if size > maxpushedparasize then
-    maxpushedparasize := size;
-end;
-
 function tppcprocinfo.calc_stackframe_size: longint;
 begin
   result := calc_stackframe_size(18, 18);

+ 4 - 1
compiler/procinfo.pas

@@ -99,7 +99,7 @@ unit procinfo;
           constructor create(aparent:tprocinfo);virtual;
           destructor destroy;override;
 
-          procedure allocate_push_parasize(size:longint);virtual;
+          procedure allocate_push_parasize(size:longint);
 
           function calc_stackframe_size:longint;virtual;
 
@@ -146,6 +146,7 @@ implementation
         { labels }
         objectlibrary.getjumplabel(aktexitlabel);
         objectlibrary.getjumplabel(gotlabel);
+        maxpushedparasize:=0;
       end;
 
 
@@ -158,6 +159,8 @@ implementation
 
     procedure tprocinfo.allocate_push_parasize(size:longint);
       begin
+        if size>maxpushedparasize then
+          maxpushedparasize:=size;
       end;
 
 

+ 0 - 8
compiler/sparc/cpupi.pas

@@ -34,7 +34,6 @@ interface
     TSparcProcInfo=class(tcgprocinfo)
     public
       constructor create(aparent:tprocinfo);override;
-      procedure allocate_push_parasize(size:longint);override;
       function calc_stackframe_size:longint;override;
     end;
 
@@ -51,13 +50,6 @@ implementation
       end;
 
 
-    procedure tsparcprocinfo.allocate_push_parasize(size:longint);
-      begin
-        if size>maxpushedparasize then
-          maxpushedparasize:=size;
-      end;
-
-
     function TSparcProcInfo.calc_stackframe_size:longint;
       begin
         {

+ 13 - 2
compiler/x86/cgx86.pas

@@ -557,8 +557,8 @@ unit cgx86;
 
         asmlist[al_imports].concat(Tai_section.create(sec_stub,'',0));
         result := objectlibrary.newasmsymbol(stubname,AB_EXTERNAL,AT_FUNCTION);
-        asmlist[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
         asmlist[al_imports].concat(Tai_symbol.Create(result,0));
+        asmlist[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
         asmlist[al_imports].concat(taicpu.op_none(A_HLT));
         asmlist[al_imports].concat(taicpu.op_none(A_HLT));
         asmlist[al_imports].concat(taicpu.op_none(A_HLT));
@@ -1857,6 +1857,8 @@ unit cgx86;
 
 
     procedure tcgx86.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
+      var
+        stackmisalignment: longint;
       begin
 {$ifdef i386}
         { interrupt support for i386 }
@@ -1880,11 +1882,15 @@ unit cgx86;
         { save old framepointer }
         if not nostackframe then
           begin
+            { return address }
+            stackmisalignment := sizeof(aint);
             list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
               CGmessage(cg_d_stackframe_omited)
             else
               begin
+                { push <frame_pointer> }
+                inc(stackmisalignment,sizeof(aint));
                 include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
                 list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG));
                 { Return address and FP are both on stack }
@@ -1895,8 +1901,13 @@ unit cgx86;
               end;
 
             { allocate stackframe space }
-            if localsize<>0 then
+            if (localsize<>0) or
+               ((target_info.system = system_i386_darwin) and
+                (stackmisalignment <> 0) and
+                (pi_do_call in current_procinfo.flags)) then
               begin
+                if (target_info.system = system_i386_darwin) then
+                  localsize := align(localsize+stackmisalignment,16)-stackmisalignment;
                 cg.g_stackpointer_alloc(list,localsize);
                 if current_procinfo.framepointer=NR_STACK_POINTER_REG then
                   dwarfcfi.cfa_def_cfa_offset(list,localsize+sizeof(aint));