Browse Source

Fixed bug on x86 platforms where the stack pointer was not allocated if it was different to the frame pointer

J. Gareth "Curious Kit" Moreton 3 years ago
parent
commit
fe39f9ca21
3 changed files with 27 additions and 3 deletions
  1. 19 1
      compiler/i386/cgcpu.pas
  2. 2 1
      compiler/x86/cgx86.pas
  3. 6 1
      compiler/x86_64/cgcpu.pas

+ 19 - 1
compiler/i386/cgcpu.pas

@@ -378,6 +378,10 @@ unit cgcpu;
             list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
             list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
             { this restores the flags }
+
+            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+              list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
             list.concat(Taicpu.Op_none(A_IRET,S_NO));
           end
         { Routines with the poclearstack flag set use only a ret }
@@ -388,6 +392,9 @@ unit cgcpu;
            { but not on win32 }
            { and not for safecall with hidden exceptions, because the result }
            { wich contains the exception is passed in EAX }
+           if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+             list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
            if ((target_info.system <> system_i386_win32) or
                (target_info.abi=abi_old_win32_gnu)) and
               not ((current_procinfo.procdef.proccalloption = pocall_safecall) and
@@ -398,16 +405,27 @@ unit cgcpu;
            else
              list.concat(Taicpu.Op_none(A_RET,S_NO));
          end
+
         { ... also routines with parasize=0 }
         else if (parasize=0) then
-         list.concat(Taicpu.Op_none(A_RET,S_NO))
+         begin
+           if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+             list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
+           list.concat(Taicpu.Op_none(A_RET,S_NO))
+         end
         else
          begin
            { parameters are limited to 65535 bytes because ret allows only imm16 }
            if (parasize>65535) then
              CGMessage(cg_e_parasize_too_big);
+
+           if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+             list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
            list.concat(Taicpu.Op_const(A_RET,S_W,parasize));
          end;
+
       end;
 
 

+ 2 - 1
compiler/x86/cgx86.pas

@@ -3376,6 +3376,7 @@ unit cgx86;
       begin
         regsize:=0;
         stackmisalignment:=0;
+        list.concat(tai_regalloc.alloc(NR_STACK_POINTER_REG,nil));
 {$ifdef i8086}
         { Win16 callback/exported proc prologue support.
           Since callbacks can be called from different modules, DS on entry may be
@@ -3500,7 +3501,6 @@ unit cgx86;
           begin
             { return address }
             inc(stackmisalignment,sizeof(pint));
-            list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
               begin
 {$ifdef i386}
@@ -3511,6 +3511,7 @@ unit cgx86;
               end
             else
               begin
+                list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
 {$ifdef i8086}
                 if ((ts_x86_far_procs_push_odd_bp in current_settings.targetswitches) or
                     ((po_exports in current_procinfo.procdef.procoptions) and

+ 6 - 1
compiler/x86_64/cgcpu.pas

@@ -206,12 +206,13 @@ unit cgcpu;
           is expected to be one of those directives, and not generated here. }
         suppress_endprologue:=(pi_has_unwind_info in current_procinfo.flags);
 
+        list.concat(tai_regalloc.alloc(NR_STACK_POINTER_REG,nil));
+
         { save old framepointer }
         if not nostackframe then
           begin
             { return address }
             stackmisalignment := sizeof(pint);
-            list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
               begin
                 push_regs;
@@ -219,6 +220,7 @@ unit cgcpu;
               end
             else
               begin
+                list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
                 { push <frame_pointer> }
                 inc(stackmisalignment,sizeof(pint));
                 push_one_reg(NR_FRAME_POINTER_REG);
@@ -427,6 +429,9 @@ unit cgcpu;
               list.Concat(taicpu.op_none(A_VZEROUPPER));
           end;
 
+        if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+          list.concat(tai_regalloc.dealloc(NR_STACK_POINTER_REG,nil));
+
         list.concat(Taicpu.Op_none(A_RET,S_NO));
 
         if (pi_has_unwind_info in current_procinfo.flags) then