From 7cdb39b3f9b82e8d343f113c545fcc780a1cad88 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 9 Nov 2019 22:07:33 +0000 Subject: [PATCH] =?UTF-8?q?--=20Aufzeichnung=20der=20Informationen=20f?= =?UTF-8?q?=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43005=20in=20=C2=BB.?= =?UTF-8?q?=C2=AB:=20=20G=20=20=20.=20--=20Aufzeichnung=20der=20Informatio?= =?UTF-8?q?nen=20f=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43006=20in=20?= =?UTF-8?q?=C2=BB.=C2=AB:=20=20G=20=20=20.=20--=20Aufzeichnung=20der=20Inf?= =?UTF-8?q?ormationen=20f=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43007=20i?= =?UTF-8?q?n=20=C2=BB.=C2=AB:=20=20G=20=20=20.=20--=20Aufzeichnung=20der?= =?UTF-8?q?=20Informationen=20f=C3=BCr=20Zusammenf=C3=BChrung=20von=20r430?= =?UTF-8?q?08=20in=20=C2=BB.=C2=AB:=20=20G=20=20=20.=20--=20Zusammenf?= =?UTF-8?q?=C3=BChren=20von=20r43000=20in=20=C2=BB.=C2=AB:=20U=20=20=20=20?= =?UTF-8?q?compiler/pp.pas=20--=20Aufzeichnung=20der=20Informationen=20f?= =?UTF-8?q?=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43000=20in=20=C2=BB.?= =?UTF-8?q?=C2=AB:=20=20G=20=20=20.=20--=20Zusammenf=C3=BChren=20von=20r43?= =?UTF-8?q?011=20in=20=C2=BB.=C2=AB:=20U=20=20=20=20rtl/inc/system.inc=20-?= =?UTF-8?q?-=20Aufzeichnung=20der=20Informationen=20f=C3=BCr=20Zusammenf?= =?UTF-8?q?=C3=BChrung=20von=20r43011=20in=20=C2=BB.=C2=AB:=20=20G=20=20?= =?UTF-8?q?=20.=20--=20Zusammenf=C3=BChren=20von=20r43012=20in=20=C2=BB.?= =?UTF-8?q?=C2=AB:=20U=20=20=20=20rtl/i386/i386.inc=20--=20Aufzeichnung=20?= =?UTF-8?q?der=20Informationen=20f=C3=BCr=20Zusammenf=C3=BChrung=20von=20r?= =?UTF-8?q?43012=20in=20=C2=BB.=C2=AB:=20=20G=20=20=20.=20--=20Zusammenf?= =?UTF-8?q?=C3=BChren=20von=20r43013=20in=20=C2=BB.=C2=AB:=20U=20=20=20=20?= =?UTF-8?q?rtl/linux/i386/si=5Fc21.inc=20--=20Aufzeichnung=20der=20Informa?= =?UTF-8?q?tionen=20f=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43013=20in=20?= =?UTF-8?q?=C2=BB.=C2=AB:=20=20G=20=20=20.=20--=20Zusammenf=C3=BChren=20vo?= =?UTF-8?q?n=20r43014=20in=20=C2=BB.=C2=AB:=20U=20=20=20=20compiler/system?= =?UTF-8?q?s/i=5Flinux.pas=20--=20Aufzeichnung=20der=20Informationen=20f?= =?UTF-8?q?=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43014=20in=20=C2=BB.?= =?UTF-8?q?=C2=AB:=20=20G=20=20=20.=20--=20Zusammenf=C3=BChren=20von=20r43?= =?UTF-8?q?176=20in=20=C2=BB.=C2=AB:=20U=20=20=20=20compiler/i386/cpupi.pa?= =?UTF-8?q?s=20U=20=20=20=20compiler/i386/n386cal.pas=20U=20=20=20=20compi?= =?UTF-8?q?ler/ncgcal.pas=20U=20=20=20=20compiler/ncgutil.pas=20G=20=20=20?= =?UTF-8?q?=20compiler/systems/i=5Flinux.pas=20U=20=20=20=20compiler/syste?= =?UTF-8?q?ms.inc=20C=20=20=20=20compiler/systems.pas=20G=20=20=20=20tests?= =?UTF-8?q?/webtbs/tw7808.pp=20--=20Aufzeichnung=20der=20Informationen=20f?= =?UTF-8?q?=C3=BCr=20Zusammenf=C3=BChrung=20von=20r43176=20in=20=C2=BB.?= =?UTF-8?q?=C2=AB:=20=20G=20=20=20.=20Konflikt=C3=BCbersicht:=20=20=20Text?= =?UTF-8?q?konflikte:=201=20Konflikt=C3=BCbersicht:=20=20=20Textkonflikte:?= =?UTF-8?q?=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: branches/fixes_3_2@43434 - --- compiler/i386/cgcpu.pas | 4 +-- compiler/i386/cpupara.pas | 2 +- compiler/i386/cpupi.pas | 9 ++++--- compiler/i386/n386cal.pas | 14 ++++++++--- compiler/ncgcal.pas | 47 ++++++++++++++++++++++++------------ compiler/ncgutil.pas | 4 +-- compiler/options.pas | 2 ++ compiler/pp.pas | 2 ++ compiler/systems.inc | 1 + compiler/systems.pas | 5 ++-- compiler/systems/i_linux.pas | 4 +-- compiler/x86/cgx86.pas | 8 +++--- rtl/i386/i386.inc | 18 ++++++++++++++ rtl/inc/system.inc | 20 +++++++++++---- rtl/linux/i386/si_c21.inc | 14 ++++++----- tests/test/tasm18g.pp | 4 +-- tests/test/tasm23a.pp | 4 +-- tests/webtbs/tw6687.pp | 2 +- tests/webtbs/tw7808.pp | 11 ++++++++- tests/webtbs/tw8155.pp | 2 +- 20 files changed, 121 insertions(+), 56 deletions(-) diff --git a/compiler/i386/cgcpu.pas b/compiler/i386/cgcpu.pas index dacfaba87d..794d539110 100644 --- a/compiler/i386/cgcpu.pas +++ b/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 diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas index 50a177d061..4d36705dfd 100644 --- a/compiler/i386/cpupara.pas +++ b/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 diff --git a/compiler/i386/cpupi.pas b/compiler/i386/cpupi.pas index 968ae8bbe4..cfba463371 100644 --- a/compiler/i386/cpupi.pas +++ b/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; diff --git a/compiler/i386/n386cal.pas b/compiler/i386/n386cal.pas index 06278cbb4b..331c44270e 100644 --- a/compiler/i386/n386cal.pas +++ b/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; diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 490f2934ab..6667510b3c 100644 --- a/compiler/ncgcal.pas +++ b/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 } diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index fc9775a3ad..3df0a91df6 100644 --- a/compiler/ncgutil.pas +++ b/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; diff --git a/compiler/options.pas b/compiler/options.pas index 56b36585a1..a54e1e17af 100644 --- a/compiler/options.pas +++ b/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; diff --git a/compiler/pp.pas b/compiler/pp.pas index aec3a42891..8235dcd161 100644 --- a/compiler/pp.pas +++ b/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 diff --git a/compiler/systems.inc b/compiler/systems.inc index 5c52a09df7..1442137726 100644 --- a/compiler/systems.inc +++ b/compiler/systems.inc @@ -316,6 +316,7 @@ ,abi_eabi,abi_armeb,abi_eabihf ,abi_old_win32_gnu ,abi_aarch64_darwin + ,abi_linux386_sysv ); const diff --git a/compiler/systems.pas b/compiler/systems.pas index 4d54be7aa0..4b700e9b2e 100644 --- a/compiler/systems.pas +++ b/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 diff --git a/compiler/systems/i_linux.pas b/compiler/systems/i_linux.pas index baf9340a4b..73378cfe29 100644 --- a/compiler/systems/i_linux.pas +++ b/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'; ); diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas index ea1ae79b94..cff801f9d9 100644 --- a/compiler/x86/cgx86.pas +++ b/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 diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index 632f6f5382..01bc03e442 100644 --- a/rtl/i386/i386.inc +++ b/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; diff --git a/rtl/inc/system.inc b/rtl/inc/system.inc index cbf6c0f3a4..8ff625a52f 100644 --- a/rtl/inc/system.inc +++ b/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} diff --git a/rtl/linux/i386/si_c21.inc b/rtl/linux/i386/si_c21.inc index c266e245ce..71df29b6ef 100644 --- a/rtl/linux/i386/si_c21.inc +++ b/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; diff --git a/tests/test/tasm18g.pp b/tests/test/tasm18g.pp index 39d518b149..f7fad7bf99 100644 --- a/tests/test/tasm18g.pp +++ b/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 } diff --git a/tests/test/tasm23a.pp b/tests/test/tasm23a.pp index 7ba4bfb112..221b5ecdda 100644 --- a/tests/test/tasm23a.pp +++ b/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]] } diff --git a/tests/webtbs/tw6687.pp b/tests/webtbs/tw6687.pp index 5b86ee4ba0..3180e588ae 100644 --- a/tests/webtbs/tw6687.pp +++ b/tests/webtbs/tw6687.pp @@ -1,5 +1,5 @@ { %cpu=i386 } -{ %target=win32,linux,freebsd,haiku } +{ %target=win32,freebsd,haiku } {$ifdef fpc} {$mode delphi} diff --git a/tests/webtbs/tw7808.pp b/tests/webtbs/tw7808.pp index 4856e8866c..c4480e1a53 100644 --- a/tests/webtbs/tw7808.pp +++ b/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. diff --git a/tests/webtbs/tw8155.pp b/tests/webtbs/tw8155.pp index e5aa919e7b..1addd48122 100644 --- a/tests/webtbs/tw8155.pp +++ b/tests/webtbs/tw8155.pp @@ -1,5 +1,5 @@ { %cpu=i386 } -{ %target=win32,linux,freebsd,haiku } +{ %target=win32,freebsd,haiku } {$ifdef fpc} {$mode delphi}