* adapted 16 byte alignment handling on linux: it is now assumed that the callee tries to clear the stack, so in the caller, the stack is re-adjusted

git-svn-id: trunk@43176 -
This commit is contained in:
florian 2019-10-12 21:51:13 +00:00
parent 67fc9a7853
commit fb91899457
8 changed files with 55 additions and 31 deletions

View File

@ -88,10 +88,11 @@ unit cpupi;
procedure tcpuprocinfo.generate_parameter_info; procedure tcpuprocinfo.generate_parameter_info;
begin begin
inherited generate_parameter_info; inherited generate_parameter_info;
{ Para_stack_size is only used to determine how many bytes to remove } { 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"). } 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 the stack is fixed, nothing has to be removed by the callee, except
if paramanager.use_fixed_stack then 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; para_stack_size := 0;
end; end;

View File

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

View File

@ -1187,7 +1187,7 @@ implementation
end; end;
{ Need to remove the parameters from the stack? } { Need to remove the parameters from the stack? }
if (procdefinition.proccalloption in clearstack_pocalls) then if procdefinition.proccalloption in clearstack_pocalls then
begin begin
pop_size:=pushedparasize; pop_size:=pushedparasize;
{ for Cdecl functions we don't need to pop the funcret when it { for Cdecl functions we don't need to pop the funcret when it
@ -1202,6 +1202,21 @@ implementation
{ Remove parameters/alignment from the stack } { Remove parameters/alignment from the stack }
pop_parasize(pop_size); pop_parasize(pop_size);
end 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 { frame pointer parameter is popped by the caller when it's passed the
Delphi way } Delphi way }
else if (po_delphi_nested_cc in procdefinition.procoptions) and else if (po_delphi_nested_cc in procdefinition.procoptions) and

View File

@ -775,9 +775,9 @@ implementation
else else
begin begin
parasize:=current_procinfo.para_stack_size; 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 } 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 (po_delphi_nested_cc in current_procinfo.procdef.procoptions) then
dec(parasize,sizeof(pint)); dec(parasize,sizeof(pint));
end; end;

View File

@ -321,6 +321,7 @@
,abi_old_win32_gnu ,abi_old_win32_gnu
,abi_aarch64_darwin ,abi_aarch64_darwin
,abi_riscv_hf ,abi_riscv_hf
,abi_linux386_sysv
); );
const const

View File

@ -239,7 +239,7 @@ interface
end; end;
tabiinfo = record tabiinfo = record
name: string[11]; name: string[13];
supported: boolean; supported: boolean;
end; end;
@ -433,7 +433,8 @@ interface
(name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}), (name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}),
(name: 'OLDWIN32GNU'; supported:{$ifdef I386}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: 'RISCVHF'; supported:{$if defined(riscv32) or defined(riscv64)}true{$else}false{$endif}) (name: 'RISCVHF'; supported:{$if defined(riscv32) or defined(riscv64)}true{$else}false{$endif}),
(name: 'LINUX386_SYSV'; supported:{$if defined(i386)}true{$else}false{$endif})
); );
{ x86 asm modes with an Intel-style syntax } { x86 asm modes with an Intel-style syntax }

View File

@ -101,7 +101,7 @@ unit i_linux;
first_parm_offset : 8; first_parm_offset : 8;
stacksize : 8*1024*1024; stacksize : 8*1024*1024;
stackalign : 16; stackalign : 16;
abi : abi_default; abi : abi_linux386_sysv;
{ note: default LLVM stack alignment is 16 bytes for this target } { 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'; 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';
); );

View File

@ -22,7 +22,7 @@ begin
push word $beef push word $beef
call test call test
{$if FPC_STACKALIGNMENT=16} {$if FPC_STACKALIGNMENT=16}
lea esp,[esp+16] lea esp,[esp-4]
{$endif FPC_STACKALIGNMENT=16} {$endif FPC_STACKALIGNMENT=16}
end; end;
end. end.