mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-07-23 21:16:22 +02:00
* enable specifying the alignment mismatch of the frame/stack pointer
relative to the normal stack alignment of the target (e.g., when using ebp as framepointer, all addresses are offset 8 to the stack pointer) in the temp generator. This enables allocating temps/locals with the correct alignment as long as the required alignment is not bigger than the guaranteed stack pointer alignment (fixes mantis #15582 on systems where the stack pointer is at least aligned to 16 bytes; e.g., not yet on i386-platforms other than darwin) git-svn-id: trunk@22277 -
This commit is contained in:
parent
4cae00f97a
commit
a5cb157091
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -12426,6 +12426,7 @@ tests/webtbs/tw15500.pp svneol=native#text/plain
|
|||||||
tests/webtbs/tw15504.pp svneol=native#text/plain
|
tests/webtbs/tw15504.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw15530.pp svneol=native#text/pascal
|
tests/webtbs/tw15530.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw15571.pp svneol=native#text/pascal
|
tests/webtbs/tw15571.pp svneol=native#text/pascal
|
||||||
|
tests/webtbs/tw15582.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw15591.pp svneol=native#text/pascal
|
tests/webtbs/tw15591.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw15592.pp svneol=native#text/plain
|
tests/webtbs/tw15592.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw15599.pp svneol=native#text/plain
|
tests/webtbs/tw15599.pp svneol=native#text/plain
|
||||||
@ -13587,6 +13588,7 @@ tests/webtbs/uw13345y.pp svneol=native#text/plain
|
|||||||
tests/webtbs/uw13583.pp svneol=native#text/plain
|
tests/webtbs/uw13583.pp svneol=native#text/plain
|
||||||
tests/webtbs/uw14124.pp svneol=native#text/plain
|
tests/webtbs/uw14124.pp svneol=native#text/plain
|
||||||
tests/webtbs/uw14958.pp svneol=native#text/plain
|
tests/webtbs/uw14958.pp svneol=native#text/plain
|
||||||
|
tests/webtbs/uw15582.pp svneol=native#text/plain
|
||||||
tests/webtbs/uw15591.pp svneol=native#text/pascal
|
tests/webtbs/uw15591.pp svneol=native#text/pascal
|
||||||
tests/webtbs/uw15909.pp svneol=native#text/plain
|
tests/webtbs/uw15909.pp svneol=native#text/plain
|
||||||
tests/webtbs/uw15966.pp svneol=native#text/plain
|
tests/webtbs/uw15966.pp svneol=native#text/plain
|
||||||
|
@ -64,6 +64,10 @@ unit cpupi;
|
|||||||
if not(po_assembler in procdef.procoptions) and
|
if not(po_assembler in procdef.procoptions) and
|
||||||
(tg.direction > 0) then
|
(tg.direction > 0) then
|
||||||
tg.setfirsttemp(tg.direction*maxpushedparasize);
|
tg.setfirsttemp(tg.direction*maxpushedparasize);
|
||||||
|
if (tg.direction < 0) and
|
||||||
|
not(po_nostackframe in procdef.procoptions) then
|
||||||
|
{ compensate for the return address and the "pushl %ebp" }
|
||||||
|
tg.setalignmentmismatch(sizeof(pint)*2);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -67,7 +67,11 @@ unit tgobj;
|
|||||||
templist : ptemprecord;
|
templist : ptemprecord;
|
||||||
{ Offsets of the first/last temp }
|
{ Offsets of the first/last temp }
|
||||||
firsttemp,
|
firsttemp,
|
||||||
lasttemp : longint;
|
lasttemp,
|
||||||
|
{ Offset of temp base register relative to guaranteed stack alignment
|
||||||
|
(note: currently only behaves as expected if it's a power of 2,
|
||||||
|
and if all requested alignments are also a power of 2) }
|
||||||
|
alignmismatch: longint;
|
||||||
direction : shortint;
|
direction : shortint;
|
||||||
constructor create;virtual;reintroduce;
|
constructor create;virtual;reintroduce;
|
||||||
{# Clear and free the complete linked list of temporary memory
|
{# Clear and free the complete linked list of temporary memory
|
||||||
@ -80,6 +84,7 @@ unit tgobj;
|
|||||||
@param(l start offset where temps will start in stack)
|
@param(l start offset where temps will start in stack)
|
||||||
}
|
}
|
||||||
procedure setfirsttemp(l : longint); virtual;
|
procedure setfirsttemp(l : longint); virtual;
|
||||||
|
procedure setalignmentmismatch(l : longint); virtual;
|
||||||
|
|
||||||
{ version of gettemp that is compatible with hlcg-based targets;
|
{ version of gettemp that is compatible with hlcg-based targets;
|
||||||
always use in common code, only use gettemp in cgobj and
|
always use in common code, only use gettemp in cgobj and
|
||||||
@ -206,6 +211,7 @@ implementation
|
|||||||
tempfreelist:=nil;
|
tempfreelist:=nil;
|
||||||
firsttemp:=0;
|
firsttemp:=0;
|
||||||
lasttemp:=0;
|
lasttemp:=0;
|
||||||
|
alignmismatch:=0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -224,12 +230,19 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure ttgobj.setalignmentmismatch(l: longint);
|
||||||
|
begin
|
||||||
|
alignmismatch:=l*direction;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function ttgobj.AllocTemp(list: TAsmList; size,alignment : longint; temptype : ttemptype;def : tdef) : longint;
|
function ttgobj.AllocTemp(list: TAsmList; size,alignment : longint; temptype : ttemptype;def : tdef) : longint;
|
||||||
var
|
var
|
||||||
tl,htl,
|
tl,htl,
|
||||||
bestslot,bestprev,
|
bestslot,bestprev,
|
||||||
hprev,hp : ptemprecord;
|
hprev,hp : ptemprecord;
|
||||||
freetype : ttemptype;
|
freetype : ttemptype;
|
||||||
|
adjustedpos : longint;
|
||||||
bestatend,
|
bestatend,
|
||||||
fitatbegin,
|
fitatbegin,
|
||||||
fitatend : boolean;
|
fitatend : boolean;
|
||||||
@ -270,11 +283,12 @@ implementation
|
|||||||
- share the same type
|
- share the same type
|
||||||
- contain enough space
|
- contain enough space
|
||||||
- has a correct alignment }
|
- has a correct alignment }
|
||||||
|
adjustedpos:=hp^.pos+alignmismatch;
|
||||||
if (hp^.temptype=freetype) and
|
if (hp^.temptype=freetype) and
|
||||||
(hp^.def=def) and
|
(hp^.def=def) and
|
||||||
(hp^.size>=size) and
|
(hp^.size>=size) and
|
||||||
((hp^.pos=align(hp^.pos,alignment)) or
|
((adjustedpos=align(adjustedpos,alignment)) or
|
||||||
(hp^.pos+hp^.size-size = align(hp^.pos+hp^.size-size,alignment))) then
|
(adjustedpos+hp^.size-size = align(adjustedpos+hp^.size-size,alignment))) then
|
||||||
begin
|
begin
|
||||||
{ Slot is the same size then leave immediatly }
|
{ Slot is the same size then leave immediatly }
|
||||||
if (hp^.size=size) then
|
if (hp^.size=size) then
|
||||||
@ -293,25 +307,25 @@ implementation
|
|||||||
{ still suffices. And we pick the block which will }
|
{ still suffices. And we pick the block which will }
|
||||||
{ have the best alignmenment after this new block is }
|
{ have the best alignmenment after this new block is }
|
||||||
{ substracted from it. }
|
{ substracted from it. }
|
||||||
fitatend:=(hp^.pos+hp^.size-size)=align(hp^.pos+hp^.size-size,alignment);
|
fitatend:=(adjustedpos+hp^.size-size)=align(adjustedpos+hp^.size-size,alignment);
|
||||||
fitatbegin:=hp^.pos=align(hp^.pos,alignment);
|
fitatbegin:=adjustedpos=align(adjustedpos,alignment);
|
||||||
if assigned(bestslot) then
|
if assigned(bestslot) then
|
||||||
begin
|
begin
|
||||||
fitatend:=fitatend and
|
fitatend:=fitatend and
|
||||||
((not bestatend and
|
((not bestatend and
|
||||||
(direction=-1)) or
|
(direction=-1)) or
|
||||||
(bestatend and
|
(bestatend and
|
||||||
isbetteralignedthan(abs(bestslot^.pos+hp^.size-size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax)));
|
isbetteralignedthan(abs(bestslot^.pos+hp^.size-size),abs(adjustedpos+hp^.size-size),current_settings.alignment.localalignmax)));
|
||||||
fitatbegin:=fitatbegin and
|
fitatbegin:=fitatbegin and
|
||||||
(not bestatend or
|
(not bestatend or
|
||||||
(direction=1)) and
|
(direction=1)) and
|
||||||
isbetteralignedthan(abs(hp^.pos+size),abs(bestslot^.pos+size),current_settings.alignment.localalignmax);
|
isbetteralignedthan(abs(adjustedpos+size),abs(bestslot^.pos+size),current_settings.alignment.localalignmax);
|
||||||
end;
|
end;
|
||||||
if fitatend and
|
if fitatend and
|
||||||
fitatbegin then
|
fitatbegin then
|
||||||
if isbetteralignedthan(abs(hp^.pos+hp^.size-size),abs(hp^.pos+size),current_settings.alignment.localalignmax) then
|
if isbetteralignedthan(abs(adjustedpos+hp^.size-size),abs(adjustedpos+size),current_settings.alignment.localalignmax) then
|
||||||
fitatbegin:=false
|
fitatbegin:=false
|
||||||
else if isbetteralignedthan(abs(hp^.pos+size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax) then
|
else if isbetteralignedthan(abs(adjustedpos+size),abs(adjustedpos+hp^.size-size),current_settings.alignment.localalignmax) then
|
||||||
fitatend:=false
|
fitatend:=false
|
||||||
else if (direction=1) then
|
else if (direction=1) then
|
||||||
fitatend:=false
|
fitatend:=false
|
||||||
@ -392,13 +406,13 @@ implementation
|
|||||||
{ Extend the temp }
|
{ Extend the temp }
|
||||||
if direction=-1 then
|
if direction=-1 then
|
||||||
begin
|
begin
|
||||||
lasttemp:=(-align(-lasttemp,alignment))-size;
|
lasttemp:=(-align(-lasttemp-alignmismatch,alignment))-size-alignmismatch;
|
||||||
tl^.pos:=lasttemp;
|
tl^.pos:=lasttemp;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
tl^.pos:=align(lasttemp,alignment);
|
tl^.pos:=align(lasttemp+alignmismatch,alignment)-alignmismatch;
|
||||||
lasttemp:=tl^.pos+size;
|
lasttemp:=tl^.pos+size;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tl^.size:=size;
|
tl^.size:=size;
|
||||||
|
52
tests/webtbs/tw15582.pp
Normal file
52
tests/webtbs/tw15582.pp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{ %cpu=x86_64,i386,powerpc,powerpc64}
|
||||||
|
{ %skiptarget=linux,freebsd,netbsd,openbsd,win32,os2,go32v2}
|
||||||
|
|
||||||
|
{ should actually only skip i386-variants of win32/linux/.. for now, but that can't be specified }
|
||||||
|
|
||||||
|
{ test can only work correctly (for now) on targets with 16-byte aligned stacks }
|
||||||
|
|
||||||
|
program tw15582;
|
||||||
|
|
||||||
|
{$MODE OBJFPC}{$H+}
|
||||||
|
|
||||||
|
{$codealign varmin=16}
|
||||||
|
{$codealign localmin=16}
|
||||||
|
|
||||||
|
uses
|
||||||
|
uw15582;
|
||||||
|
|
||||||
|
var g1,g2,g3 : byte;
|
||||||
|
g4 : integer;
|
||||||
|
g5 : byte;
|
||||||
|
g6 : array[0..39] of double;
|
||||||
|
|
||||||
|
procedure l;
|
||||||
|
var l1,l2,l3 : byte;
|
||||||
|
l4 : integer;
|
||||||
|
l5 : byte;
|
||||||
|
l6 : array[0..39] of double;
|
||||||
|
|
||||||
|
begin
|
||||||
|
check('l1',@l1);
|
||||||
|
check('l2',@l2);
|
||||||
|
check('l3',@l3);
|
||||||
|
check('l4',@l4);
|
||||||
|
check('l5',@l5);
|
||||||
|
check('l6',@l6);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
check('g1',@g1);
|
||||||
|
check('g2',@g2);
|
||||||
|
check('g3',@g3);
|
||||||
|
check('g4',@g4);
|
||||||
|
check('g5',@g5);
|
||||||
|
check('g6',@g6);
|
||||||
|
l;
|
||||||
|
l_unit('main ');
|
||||||
|
l_unit_nostackframe;
|
||||||
|
writeln(n_checks,' tests. ',n_failed,' failed');
|
||||||
|
if n_failed > 0 then
|
||||||
|
halt(1);
|
||||||
|
end.
|
72
tests/webtbs/uw15582.pp
Normal file
72
tests/webtbs/uw15582.pp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
unit uw15582;
|
||||||
|
|
||||||
|
{$MODE OBJFPC}{$H+}
|
||||||
|
|
||||||
|
|
||||||
|
{$codealign varmin=16}
|
||||||
|
{$codealign localmin=16}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
var
|
||||||
|
n_checks : integer = 0;
|
||||||
|
n_failed : integer = 0;
|
||||||
|
|
||||||
|
procedure check(const v : string;p : pointer);
|
||||||
|
procedure l_unit(const pfx : string);
|
||||||
|
procedure l_unit_nostackframe;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
var g1,g2,g3 : byte;
|
||||||
|
g4 : integer;
|
||||||
|
g5 : byte;
|
||||||
|
g6 : array[0..39] of double;
|
||||||
|
|
||||||
|
procedure check(const v : string;p : pointer);
|
||||||
|
begin
|
||||||
|
inc(n_checks);
|
||||||
|
if (ptruint(p) and ptruint(-16)) <> ptruint(p) then begin
|
||||||
|
writeln('Wrong aligned: "',v,'" : ',hexstr(p));
|
||||||
|
inc(n_failed);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure l_unit(const pfx : string);
|
||||||
|
var l1,l2,l3 : byte;
|
||||||
|
l4 : integer;
|
||||||
|
l5 : byte;
|
||||||
|
l6 : array[0..39] of double;
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
check(pfx+'l_unit1',@l1);
|
||||||
|
check(pfx+'l_unit2',@l2);
|
||||||
|
check(pfx+'l_unit3',@l3);
|
||||||
|
check(pfx+'l_unit4',@l4);
|
||||||
|
check(pfx+'l_unit5',@l5);
|
||||||
|
check(pfx+'l_unit6',@l6);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure l_unit_nostackframe;
|
||||||
|
var
|
||||||
|
b1, b2: byte;
|
||||||
|
begin
|
||||||
|
inc(n_checks);
|
||||||
|
if (ptruint(@b1) and ptruint(15)) <> 0 then
|
||||||
|
inc(n_failed);
|
||||||
|
inc(n_checks);
|
||||||
|
if (ptruint(@b2) and ptruint(15)) <> 0 then
|
||||||
|
inc(n_failed);
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
check('g_unit1',@g1);
|
||||||
|
check('g_unit2',@g2);
|
||||||
|
check('g_unit3',@g3);
|
||||||
|
check('g_unit4',@g4);
|
||||||
|
check('g_unit5',@g5);
|
||||||
|
check('g_unit6',@g6);
|
||||||
|
l_unit('ca_unit.initialization ');
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user