Browse Source

-- Aufzeichnung der Informationen für Zusammenführung von r43005 in ».«:
G .
-- Aufzeichnung der Informationen für Zusammenführung von r43006 in ».«:
G .
-- Aufzeichnung der Informationen für Zusammenführung von r43007 in ».«:
G .
-- Aufzeichnung der Informationen für Zusammenführung von r43008 in ».«:
G .
-- Zusammenführen von r43000 in ».«:
U compiler/pp.pas
-- Aufzeichnung der Informationen für Zusammenführung von r43000 in ».«:
G .
-- Zusammenführen von r43011 in ».«:
U rtl/inc/system.inc
-- Aufzeichnung der Informationen für Zusammenführung von r43011 in ».«:
G .
-- Zusammenführen von r43012 in ».«:
U rtl/i386/i386.inc
-- Aufzeichnung der Informationen für Zusammenführung von r43012 in ».«:
G .
-- Zusammenführen von r43013 in ».«:
U rtl/linux/i386/si_c21.inc
-- Aufzeichnung der Informationen für Zusammenführung von r43013 in ».«:
G .
-- Zusammenführen von r43014 in ».«:
U compiler/systems/i_linux.pas
-- Aufzeichnung der Informationen für Zusammenführung von r43014 in ».«:
G .
-- Zusammenführen von r43176 in ».«:
U compiler/i386/cpupi.pas
U compiler/i386/n386cal.pas
U compiler/ncgcal.pas
U compiler/ncgutil.pas
G compiler/systems/i_linux.pas
U compiler/systems.inc
C compiler/systems.pas
G tests/webtbs/tw7808.pp
-- Aufzeichnung der Informationen für Zusammenführung von r43176 in ».«:
G .
Konfliktübersicht:
Textkonflikte: 1
Konfliktübersicht:
Textkonflikte: 1

git-svn-id: branches/fixes_3_2@43434 -

florian 5 years ago
parent
commit
7cdb39b3f9

+ 1 - 3
compiler/i386/cgcpu.pas

@@ -334,9 +334,7 @@ unit cgcpu;
           end;
 
         { return from proc }
-        if (po_interrupt in current_procinfo.procdef.procoptions) and
-           { this messes up stack alignment }
-           (target_info.stackalign=4) then
+        if po_interrupt in current_procinfo.procdef.procoptions then
           begin
             if assigned(current_procinfo.procdef.funcretloc[calleeside].location) and
                (current_procinfo.procdef.funcretloc[calleeside].location^.loc=LOC_REGISTER) then

+ 1 - 1
compiler/i386/cpupara.pas

@@ -423,7 +423,7 @@ unit cpupara;
         { we push Flags and CS as long
           to cope with the IRETD
           and we save 6 register + 4 selectors }
-        if po_interrupt in p.procoptions then
+        if (po_interrupt in p.procoptions) and (side=calleeside) then
           inc(parasize,8+6*4+4*2);
         { Offset is calculated like:
            sub esp,12

+ 5 - 4
compiler/i386/cpupi.pas

@@ -88,10 +88,11 @@ unit cpupi;
     procedure tcpuprocinfo.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 paramanager.use_fixed_stack then
+        { 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, except
+          if a 16 byte aligned stack on i386-linux is used     }
+        if paramanager.use_fixed_stack and not(target_info.abi=abi_linux386_sysv) then
           para_stack_size := 0;
       end;
 

+ 10 - 4
compiler/i386/n386cal.pas

@@ -52,7 +52,8 @@ implementation
       nbas,nmem,nld,ncnv,
       parabase,
       symdef,symsym,symcpu,symconst,
-      cga,cgobj,cpuinfo;
+      cga,cgobj,cgx86,
+      cpuinfo;
 
 
 {*****************************************************************************
@@ -104,16 +105,21 @@ implementation
     procedure ti386callnode.pop_parasize(pop_size:longint);
       var
         hreg : tregister;
+        href : treference;
       begin
-        if (paramanager.use_fixed_stack) then
+        if paramanager.use_fixed_stack then
           begin
             { very weird: in this case the callee does a "ret $4" and the }
             { caller immediately a "subl $4,%esp". Possibly this is for   }
             { use_fixed_stack code to be able to transparently call       }
             { old-style code (JM)                                         }
             dec(pop_size,pushedparasize);
-            if (pop_size < 0) then
-              current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_SUB,S_L,-pop_size,NR_ESP));
+            if pop_size<0 then
+              begin
+                reference_reset_base(href,NR_STACK_POINTER_REG,pop_size,ctempposinvalid,0,[]);
+                { it is better to use lea here }
+                current_asmdata.CurrAsmList.concat(Taicpu.op_ref_reg(A_LEA,TCGSize2OpSize[OS_ADDR],href,NR_ESP));
+              end;
             exit;
           end;
 

+ 31 - 16
compiler/ncgcal.pas

@@ -1176,25 +1176,40 @@ implementation
            end;
 
          { Need to remove the parameters from the stack? }
-         if (procdefinition.proccalloption in clearstack_pocalls) then
-          begin
-            pop_size:=pushedparasize;
-            { for Cdecl functions we don't need to pop the funcret when it
-              was pushed by para. Except for safecall functions with
-              safecall-exceptions enabled. In that case the funcret is always
-              returned as a para which is considered a normal para on the
-              c-side, so the funcret has to be pop'ed normally. }
-            if not ((procdefinition.proccalloption=pocall_safecall) and
-                    (tf_safecall_exceptions in target_info.flags)) and
-               paramanager.ret_in_param(procdefinition.returndef,procdefinition) then
-              dec(pop_size,sizeof(pint));
-            { Remove parameters/alignment from the stack }
-            pop_parasize(pop_size);
-          end
+         if procdefinition.proccalloption in clearstack_pocalls then
+           begin
+             pop_size:=pushedparasize;
+             { for Cdecl functions we don't need to pop the funcret when it
+               was pushed by para. Except for safecall functions with
+               safecall-exceptions enabled. In that case the funcret is always
+               returned as a para which is considered a normal para on the
+               c-side, so the funcret has to be pop'ed normally. }
+             if not ((procdefinition.proccalloption=pocall_safecall) and
+                     (tf_safecall_exceptions in target_info.flags)) and
+                paramanager.ret_in_param(procdefinition.returndef,procdefinition) then
+               dec(pop_size,sizeof(pint));
+             { Remove parameters/alignment from the stack }
+             pop_parasize(pop_size);
+           end
+         { in case we use a fixed stack, we did not push anything, if the stack is
+           really adjusted because a ret xxx was done, depends on
+           pop_parasize which uses pushedparasize to determine this
+
+           This does not apply to interrupt procedures, their ret statment never clears any stack parameters }
+         else if paramanager.use_fixed_stack and not(po_interrupt in procdefinition.procoptions) then
+           begin
+             { however, a delphi style frame pointer for a nested subroutine
+               is not cleared by the callee, so we have to compensate for this
+               by passing 4 as pushedparasize does include it }
+             if po_delphi_nested_cc in procdefinition.procoptions then
+               pop_parasize(sizeof(pint))
+             else
+               pop_parasize(0);
+           end
          { frame pointer parameter is popped by the caller when it's passed the
            Delphi way }
          else if (po_delphi_nested_cc in procdefinition.procoptions) and
-                 not paramanager.use_fixed_stack then
+           not paramanager.use_fixed_stack then
            pop_parasize(sizeof(pint));
          { Release registers, but not the registers that contain the
            function result }

+ 2 - 2
compiler/ncgutil.pas

@@ -1392,9 +1392,9 @@ implementation
         else
           begin
             parasize:=current_procinfo.para_stack_size;
-            { the parent frame pointer para has to be removed by the caller in
+            { the parent frame pointer para has to be removed always by the caller in
               case of Delphi-style parent frame pointer passing }
-            if not paramanager.use_fixed_stack and
+            if (not(paramanager.use_fixed_stack) or (target_info.abi=abi_linux386_sysv)) and
                (po_delphi_nested_cc in current_procinfo.procdef.procoptions) then
               dec(parasize,sizeof(pint));
           end;

+ 2 - 0
compiler/options.pas

@@ -4386,6 +4386,8 @@ begin
         end;
     end;
 {$pop}
+  { as stackalign is not part of the alignment record, we do not need to define the others alignments for symmetry yet }
+  set_system_macro('FPC_STACKALIGNMENT',tostr(target_info.stackalign));
 
   option.free;
   Option:=nil;

+ 2 - 0
compiler/pp.pas

@@ -49,6 +49,8 @@ program pp;
   EXTDEBUG            some extra debug code is executed
   EXTERN_MSG          Don't compile the msgfiles in the compiler, always
                       use external messagefiles, default for TP
+  LLVM                Create an LLVM-based code generator for the selected
+                      target architecture (not supported for all targets)
 
   -----------------------------------------------------------------
   ARM specfic switches

+ 1 - 0
compiler/systems.inc

@@ -316,6 +316,7 @@
             ,abi_eabi,abi_armeb,abi_eabihf
             ,abi_old_win32_gnu
             ,abi_aarch64_darwin
+            ,abi_linux386_sysv
        );
 
      const

+ 3 - 2
compiler/systems.pas

@@ -220,7 +220,7 @@ interface
        end;
 
     tabiinfo = record
-      name: string[11];
+      name: string[13];
       supported: boolean;
     end;
 
@@ -411,7 +411,8 @@ interface
          (name: 'ARMEB'  ; supported:{$ifdef FPC_ARMEB}true{$else}false{$endif}),
          (name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}),
          (name: 'OLDWIN32GNU'; supported:{$ifdef I386}true{$else}false{$endif}),
-         (name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif})
+         (name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif}),
+         (name: 'LINUX386_SYSV'; supported:{$if defined(i386)}true{$else}false{$endif})
        );
 
     var

+ 2 - 2
compiler/systems/i_linux.pas

@@ -93,8 +93,8 @@ unit i_linux;
               );
             first_parm_offset : 8;
             stacksize    : 8*1024*1024;
-            stackalign   : 4;
-            abi : abi_default;
+            stackalign   : 16;
+            abi : abi_linux386_sysv;
             { note: default LLVM stack alignment is 16 bytes for this target }
             llvmdatalayout : 'e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32';
           );

+ 4 - 4
compiler/x86/cgx86.pas

@@ -3315,6 +3315,7 @@ unit cgx86;
         end;
 
       begin
+        stackmisalignment:=0;
 {$ifdef i8086}
         { Win16 callback/exported proc prologue support.
           Since callbacks can be called from different modules, DS on entry may be
@@ -3415,9 +3416,7 @@ unit cgx86;
 {$endif i8086}
 {$ifdef i386}
         { interrupt support for i386 }
-        if (po_interrupt in current_procinfo.procdef.procoptions) and
-           { this messes up stack alignment }
-           not(target_info.system in [system_i386_darwin,system_i386_iphonesim,system_i386_android]) then
+        if (po_interrupt in current_procinfo.procdef.procoptions) then
           begin
             { .... also the segment registers }
             list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_GS));
@@ -3431,6 +3430,7 @@ unit cgx86;
             list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ECX));
             list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EBX));
             list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EAX));
+            inc(stackmisalignment,4*2+6*8);
           end;
 {$endif i386}
 
@@ -3438,7 +3438,7 @@ unit cgx86;
         if not nostackframe then
           begin
             { return address }
-            stackmisalignment := sizeof(pint);
+            inc(stackmisalignment,sizeof(pint));
             list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if current_procinfo.framepointer=NR_STACK_POINTER_REG then
               begin

+ 18 - 0
rtl/i386/i386.inc

@@ -14,6 +14,10 @@
 
  **********************************************************************}
 
+{$if not(defined(VER3_0)) and defined(linux)}
+  {$define FPC_SYSTEM_STACKALIGNMENT16}
+{$endif not(defined(VER3_0)) and defined(linux)}
+
 {****************************************************************************
                                Primitives
 ****************************************************************************}
@@ -1433,7 +1437,15 @@ asm
         je      .Lj3596
 .Lj3620:
         movl    %esi,%eax
+        { freemem is not an assembler leaf function like fpc_geteipasebx and cpudeclocked, so it
+          needs to be called with proper stack alignment }
+{$ifdef FPC_SYSTEM_STACKALIGNMENT16}
+        leal    -8(%esp),%esp
+{$endif FPC_SYSTEM_STACKALIGNMENT16}
         call    FPC_FREEMEM
+{$ifdef FPC_SYSTEM_STACKALIGNMENT16}
+        leal    8(%esp),%esp
+{$endif FPC_SYSTEM_STACKALIGNMENT16}
 .Lj3596:
         popl    %esi
 .Lquit:
@@ -1459,7 +1471,13 @@ asm
         je      .Lj4038
 // [441] result:=fpc_truely_ansistr_unique(s);
         movl    %edx,%eax
+{$ifdef FPC_SYSTEM_STACKALIGNMENT16}
+        leal    -12(%esp),%esp
+{$endif FPC_SYSTEM_STACKALIGNMENT16}
         call    fpc_truely_ansistr_unique
+{$ifdef FPC_SYSTEM_STACKALIGNMENT16}
+        leal    12(%esp),%esp
+{$endif FPC_SYSTEM_STACKALIGNMENT16}
 .Lj4038:
 .Lj4031:
 // [442] end;

+ 15 - 5
rtl/inc/system.inc

@@ -888,15 +888,25 @@ begin
   { Avoid recursive calls when called from the exit routines }
   if StackError then
    exit;
-  { don't use sack_size, since the stack pointer has already been
+  { check stack alignment }
+{$ifdef CPUI386}
+{$ifdef FPC_STACKALIGNMENT=16}
+  if ((PtrUInt(Sptr)+4) mod 16)<>0 then
+    begin
+      StackError:=true;
+      HandleError(202);
+    end;
+{$endif FPC_STACKALIGNMENT=16}
+{$endif CPUI386}
+  { don't use stack_size, since the stack pointer has already been
     decreased when this routine is called
   }
   c := Sptr - STACK_MARGIN;
   if (c <= StackBottom) then
-   begin
-     StackError:=true;
-     HandleError(202);
-   end;
+    begin
+      StackError:=true;
+      HandleError(202);
+    end;
 end;
 {$POP}
 

+ 8 - 6
rtl/linux/i386/si_c21.inc

@@ -103,9 +103,11 @@ asm
 	hlt
 end;
 
-procedure _FPC_libc21_haltproc(e: longint); cdecl; assembler; public name '_haltproc';
-asm
-        push  e
-        call  libc_exit
-        hlt
-end;
+procedure _FPC_libc21_haltproc(e: longint); cdecl; public name '_haltproc';
+  begin
+    libc_exit(e);
+    { we should never return from libc_exit }
+    asm
+      hlt
+    end;
+  end;

+ 2 - 2
tests/test/tasm18g.pp

@@ -90,7 +90,7 @@ const
   );
 
 
-procedure test1; assembler;
+procedure test1; nostackframe; assembler;
 asm
   test [edi+foo2], cval                   { test word ptr [edi], 1   }
   test byte ptr [edi+foo], cval           { test byte ptr [edi], 1   }
@@ -142,7 +142,7 @@ asm
   test word ptr [edi+foo32_2.l], cval     { test word ptr [edi+1], 1 }
 end;
 
-procedure test2; assembler;
+procedure test2; nostackframe; assembler;
 asm
   test [edi+foo32], cval                   { test dword ptr [edi], 1   }
   test [edi+foo32_2.l], cval               { test dword ptr [edi+1], 1 }

+ 2 - 2
tests/test/tasm23a.pp

@@ -7,14 +7,14 @@ program tasm23a;
 
 const
   t_size = 19;
-procedure t; assembler;
+procedure t; nostackframe; assembler;
 asm
   mov eax, [ebx[5]][edi][54][-17][45][4]      { mov eax, [ebx+edi+5Bh] }
   mov eax, [[ebx+5]+[edi+54]+[-17]+[45]+[4]]  { mov eax, [ebx+edi+5Bh] }
   mov eax, [5[7]]                             { mov eax, [000Ch] }
   mov eax, [5+[7]]                            { mov eax, [000Ch] }
 end;
-procedure t_verify; assembler;
+procedure t_verify; nostackframe; assembler;
 asm
   mov eax, [ebx+edi+5Bh]  { mov eax, [ebx[5]][edi][54][-17][45][4]     }
   mov eax, [ebx+edi+5Bh]  { mov eax, [[ebx+5]+[edi+54]+[-17]+[45]+[4]] }

+ 1 - 1
tests/webtbs/tw6687.pp

@@ -1,5 +1,5 @@
 { %cpu=i386 }
-{ %target=win32,linux,freebsd,haiku }
+{ %target=win32,freebsd,haiku }
 
 {$ifdef fpc}
 {$mode delphi}

+ 10 - 1
tests/webtbs/tw7808.pp

@@ -2,6 +2,9 @@
 { %target=go32v2,linux,freebsd,win32,haiku}
 { %opt=-Sew -vw }
 
+{ do not warn about the lea esp,[esp+16] }
+{$WARN 7105 OFF}
+
 {$mode delphi}
 
 procedure test(l: longint); stdcall;
@@ -12,8 +15,14 @@ end;
 
 begin
   asm
+{$if FPC_STACKALIGNMENT=16}
+    lea esp,[esp-12]
+{$endif FPC_STACKALIGNMENT=16}  
     push word $dead
     push word $beef
-    call test
+    call test        
+{$if FPC_STACKALIGNMENT=16}
+    lea esp,[esp-4]
+{$endif FPC_STACKALIGNMENT=16}  
   end;
 end.

+ 1 - 1
tests/webtbs/tw8155.pp

@@ -1,5 +1,5 @@
 { %cpu=i386 }
-{ %target=win32,linux,freebsd,haiku }
+{ %target=win32,freebsd,haiku }
 
 {$ifdef fpc}
 {$mode delphi}