mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-28 16:40:28 +02:00
* pass records that (recursively) only contain floating point values of the
same type (even in other records or in arrays), with 8 or less such values, as if those values were passed individually on ppc64/ELFv2 git-svn-id: trunk@30200 -
This commit is contained in:
parent
9a73c9a460
commit
f0ee1a9ee3
@ -60,7 +60,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
verbose, systems,
|
verbose, systems,
|
||||||
defutil,symtable,
|
defutil,symtable,symcpu,
|
||||||
procinfo, cpupi;
|
procinfo, cpupi;
|
||||||
|
|
||||||
function tppcparamanager.get_volatile_registers_int(calloption:
|
function tppcparamanager.get_volatile_registers_int(calloption:
|
||||||
@ -262,6 +262,7 @@ var
|
|||||||
stack_offset: longint;
|
stack_offset: longint;
|
||||||
paralen: aint;
|
paralen: aint;
|
||||||
nextintreg, nextfloatreg, nextmmreg : tsuperregister;
|
nextintreg, nextfloatreg, nextmmreg : tsuperregister;
|
||||||
|
tmpdef,
|
||||||
locdef,
|
locdef,
|
||||||
paradef: tdef;
|
paradef: tdef;
|
||||||
paraloc: pcgparalocation;
|
paraloc: pcgparalocation;
|
||||||
@ -291,6 +292,7 @@ begin
|
|||||||
hp := tparavarsym(paras[i]);
|
hp := tparavarsym(paras[i]);
|
||||||
|
|
||||||
paradef := hp.vardef;
|
paradef := hp.vardef;
|
||||||
|
locdef := nil;
|
||||||
{ Syscall for Morphos can have already a paraloc set; not supported on ppc64 }
|
{ Syscall for Morphos can have already a paraloc set; not supported on ppc64 }
|
||||||
if (vo_has_explicit_paraloc in hp.varoptions) then begin
|
if (vo_has_explicit_paraloc in hp.varoptions) then begin
|
||||||
internalerror(200412153);
|
internalerror(200412153);
|
||||||
@ -329,7 +331,17 @@ begin
|
|||||||
(fsym.vardef.typ in [orddef, enumdef]))) then begin
|
(fsym.vardef.typ in [orddef, enumdef]))) then begin
|
||||||
paradef := fsym.vardef;
|
paradef := fsym.vardef;
|
||||||
loc := getparaloc(paradef);
|
loc := getparaloc(paradef);
|
||||||
paracgsize := def_cgsize(paradef);
|
paracgsize := def_cgsize(paradef)
|
||||||
|
{ With the new ABI, so-called "homogeneous" aggregates, i.e. struct, arrays,
|
||||||
|
or unions that (recursively) contain only elements of the same floating-
|
||||||
|
point or vector type are passed as if those elements were passed as
|
||||||
|
separate arguments. (This is done for up to 8 such elements.) }
|
||||||
|
end else if (target_info.abi=abi_powerpc_elfv2) and
|
||||||
|
tcpurecorddef(paradef).has_single_type_elfv2(tmpdef) and
|
||||||
|
((8*tmpdef.size)<=paradef.size) then begin
|
||||||
|
locdef := tmpdef;
|
||||||
|
loc := getparaloc(locdef);
|
||||||
|
paracgsize := def_cgsize(locdef);
|
||||||
end else begin
|
end else begin
|
||||||
loc := LOC_REGISTER;
|
loc := LOC_REGISTER;
|
||||||
paracgsize := int_cgsize(paralen);
|
paracgsize := int_cgsize(paralen);
|
||||||
@ -369,7 +381,8 @@ begin
|
|||||||
end else
|
end else
|
||||||
internalerror(2005011310);
|
internalerror(2005011310);
|
||||||
adjusttail:=paralen>8;
|
adjusttail:=paralen>8;
|
||||||
locdef:=paradef;
|
if not assigned(locdef) then
|
||||||
|
locdef:=paradef;
|
||||||
firstparaloc:=true;
|
firstparaloc:=true;
|
||||||
{ can become < 0 for e.g. 3-byte records }
|
{ can become < 0 for e.g. 3-byte records }
|
||||||
while (paralen > 0) do begin
|
while (paralen > 0) do begin
|
||||||
|
@ -59,6 +59,10 @@ type
|
|||||||
tcpupointerdefclass = class of tcpupointerdef;
|
tcpupointerdefclass = class of tcpupointerdef;
|
||||||
|
|
||||||
tcpurecorddef = class(trecorddef)
|
tcpurecorddef = class(trecorddef)
|
||||||
|
{ returns whether the record's elements (including arrays) all have
|
||||||
|
the same floating point or vector type; returns that type in the "def"
|
||||||
|
parameter if so }
|
||||||
|
function has_single_type_elfv2(out def: tdef): boolean;
|
||||||
end;
|
end;
|
||||||
tcpurecorddefclass = class of tcpurecorddef;
|
tcpurecorddefclass = class of tcpurecorddef;
|
||||||
|
|
||||||
@ -170,6 +174,50 @@ const
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
symconst, defutil, defcmp;
|
||||||
|
|
||||||
|
{ tcpurecorddef }
|
||||||
|
|
||||||
|
function tcpurecorddef.has_single_type_elfv2(out def: tdef): boolean;
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
checkdef, tmpdef: tdef;
|
||||||
|
begin
|
||||||
|
def:=nil;
|
||||||
|
tmpdef:=nil;
|
||||||
|
result:=false;
|
||||||
|
for i:=0 to symtable.SymList.Count-1 do
|
||||||
|
begin
|
||||||
|
if tsym(symtable.symlist[i]).typ=fieldvarsym then
|
||||||
|
begin
|
||||||
|
checkdef:=tfieldvarsym(symtable.symlist[i]).vardef;
|
||||||
|
repeat
|
||||||
|
case checkdef.typ of
|
||||||
|
floatdef:
|
||||||
|
;
|
||||||
|
arraydef:
|
||||||
|
if not is_special_array(checkdef) then
|
||||||
|
checkdef:=tarraydef(checkdef).elementdef
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
recorddef:
|
||||||
|
if not tcpurecorddef(checkdef).has_single_type_elfv2(checkdef) then
|
||||||
|
exit;
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
until checkdef.typ=floatdef;
|
||||||
|
if not assigned(def) then
|
||||||
|
def:=checkdef
|
||||||
|
else if not equal_defs(def,checkdef) then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if assigned(def) then
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
{ used tdef classes }
|
{ used tdef classes }
|
||||||
cfiledef:=tcpufiledef;
|
cfiledef:=tcpufiledef;
|
||||||
|
Loading…
Reference in New Issue
Block a user