mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-25 03:11:01 +02:00
* has_single_field() now looks recursively into fields that are aggregate
types until it finds a non-aggregate type, and then returns "true" if that aggregate (record or array) contains one element * it now also returns the type of that element directly rather than a tfieldvarsym, since we only care about the type and in case of an array there is no field git-svn-id: trunk@30205 -
This commit is contained in:
parent
2e126bb723
commit
3d9713b9c8
@ -292,7 +292,7 @@ unit cpupara;
|
|||||||
var
|
var
|
||||||
retcgsize : tcgsize;
|
retcgsize : tcgsize;
|
||||||
paraloc : pcgparalocation;
|
paraloc : pcgparalocation;
|
||||||
sym: tfieldvarsym;
|
fdef,
|
||||||
usedef: tdef;
|
usedef: tdef;
|
||||||
handled: boolean;
|
handled: boolean;
|
||||||
begin
|
begin
|
||||||
@ -307,10 +307,10 @@ unit cpupara;
|
|||||||
system_i386_os2,system_i386_emx]) and
|
system_i386_os2,system_i386_emx]) and
|
||||||
((usedef.typ=recorddef) or
|
((usedef.typ=recorddef) or
|
||||||
is_object(usedef)) and
|
is_object(usedef)) and
|
||||||
tabstractrecordsymtable(tabstractrecorddef(usedef).symtable).has_single_field(sym) and
|
tabstractrecordsymtable(tabstractrecorddef(usedef).symtable).has_single_field(fdef) and
|
||||||
(sym.vardef.typ=floatdef) and
|
(fdef.typ=floatdef) and
|
||||||
(tfloatdef(sym.vardef).floattype in [s32real,s64real]) then
|
(tfloatdef(fdef).floattype in [s32real,s64real]) then
|
||||||
usedef:=sym.vardef;
|
usedef:=fdef;
|
||||||
|
|
||||||
handled:=set_common_funcretloc_info(p,usedef,retcgsize,result);
|
handled:=set_common_funcretloc_info(p,usedef,retcgsize,result);
|
||||||
{ normally forcetempdef is passed straight through to
|
{ normally forcetempdef is passed straight through to
|
||||||
|
@ -330,13 +330,13 @@ unit cpupara;
|
|||||||
paralen: aint;
|
paralen: aint;
|
||||||
nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
|
nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
|
||||||
locdef,
|
locdef,
|
||||||
|
fdef,
|
||||||
paradef : tdef;
|
paradef : tdef;
|
||||||
paraloc : pcgparalocation;
|
paraloc : pcgparalocation;
|
||||||
i : integer;
|
i : integer;
|
||||||
hp : tparavarsym;
|
hp : tparavarsym;
|
||||||
loc : tcgloc;
|
loc : tcgloc;
|
||||||
paracgsize: tcgsize;
|
paracgsize: tcgsize;
|
||||||
sym: tfieldvarsym;
|
|
||||||
firstparaloc: boolean;
|
firstparaloc: boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -404,13 +404,12 @@ unit cpupara;
|
|||||||
{ if a record has only one field and that field is }
|
{ if a record has only one field and that field is }
|
||||||
{ non-composite (not array or record), it must be }
|
{ non-composite (not array or record), it must be }
|
||||||
{ passed according to the rules of that type. }
|
{ passed according to the rules of that type. }
|
||||||
sym:=nil;
|
if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fdef) and
|
||||||
if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
|
((fdef.typ=floatdef) or
|
||||||
((sym.vardef.typ=floatdef) or
|
|
||||||
((target_info.system=system_powerpc_darwin) and
|
((target_info.system=system_powerpc_darwin) and
|
||||||
(sym.vardef.typ in [orddef,enumdef]))) then
|
(fdef.typ in [orddef,enumdef]))) then
|
||||||
begin
|
begin
|
||||||
paradef:=sym.vardef;
|
paradef:=fdef;
|
||||||
paracgsize:=def_cgsize(paradef);
|
paracgsize:=def_cgsize(paradef);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -320,7 +320,6 @@ var
|
|||||||
locdef,
|
locdef,
|
||||||
tmpdef: tdef;
|
tmpdef: tdef;
|
||||||
paralen: aint;
|
paralen: aint;
|
||||||
fsym: tfieldvarsym;
|
|
||||||
parashift: byte;
|
parashift: byte;
|
||||||
tailpadding,
|
tailpadding,
|
||||||
firstparaloc,
|
firstparaloc,
|
||||||
@ -422,10 +421,10 @@ implemented
|
|||||||
{ AIX/ELFv1 b) }
|
{ AIX/ELFv1 b) }
|
||||||
else if (target_info.abi in [abi_powerpc_aix,abi_powerpc_sysv]) and
|
else if (target_info.abi in [abi_powerpc_aix,abi_powerpc_sysv]) and
|
||||||
(paradef.typ=recorddef) and
|
(paradef.typ=recorddef) and
|
||||||
tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fsym) and
|
tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(tmpdef) and
|
||||||
(fsym.vardef.typ=floatdef) then
|
(tmpdef.typ=floatdef) then
|
||||||
begin
|
begin
|
||||||
paradef:=fsym.vardef;
|
paradef:=tmpdef;
|
||||||
loc:=getparaloc(paradef);
|
loc:=getparaloc(paradef);
|
||||||
paracgsize:=def_cgsize(paradef)
|
paracgsize:=def_cgsize(paradef)
|
||||||
end
|
end
|
||||||
|
@ -86,7 +86,7 @@ interface
|
|||||||
procedure addalignmentpadding;
|
procedure addalignmentpadding;
|
||||||
procedure insertdef(def:TDefEntry);override;
|
procedure insertdef(def:TDefEntry);override;
|
||||||
function is_packed: boolean;
|
function is_packed: boolean;
|
||||||
function has_single_field(out sym:tfieldvarsym): boolean;
|
function has_single_field(out def:tdef): boolean;
|
||||||
function get_unit_symtable: tsymtable;
|
function get_unit_symtable: tsymtable;
|
||||||
protected
|
protected
|
||||||
{ size in bytes including padding }
|
{ size in bytes including padding }
|
||||||
@ -1238,9 +1238,12 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tabstractrecordsymtable.has_single_field(out sym: tfieldvarsym): boolean;
|
function tabstractrecordsymtable.has_single_field(out def:tdef): boolean;
|
||||||
var
|
var
|
||||||
i: longint;
|
i: longint;
|
||||||
|
currentsymlist: TFPHashObjectList;
|
||||||
|
currentdef: tdef;
|
||||||
|
sym: tfieldvarsym;
|
||||||
begin
|
begin
|
||||||
result:=false;
|
result:=false;
|
||||||
{ If a record contains a union, it does not contain a "single
|
{ If a record contains a union, it does not contain a "single
|
||||||
@ -1250,7 +1253,12 @@ implementation
|
|||||||
trecorddef(defowner).isunion then
|
trecorddef(defowner).isunion then
|
||||||
exit;
|
exit;
|
||||||
{ a record/object can contain other things than fields }
|
{ a record/object can contain other things than fields }
|
||||||
for i:=0 to SymList.Count-1 do
|
currentsymlist:=symlist;
|
||||||
|
{ recurse in arrays and records }
|
||||||
|
sym:=nil;
|
||||||
|
repeat
|
||||||
|
{ record has one field? }
|
||||||
|
for i:=0 to currentsymlist.Count-1 do
|
||||||
begin
|
begin
|
||||||
if tsym(symlist[i]).typ=fieldvarsym then
|
if tsym(symlist[i]).typ=fieldvarsym then
|
||||||
begin
|
begin
|
||||||
@ -1263,6 +1271,33 @@ implementation
|
|||||||
sym:=tfieldvarsym(symlist[i])
|
sym:=tfieldvarsym(symlist[i])
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
if assigned(sym) then
|
||||||
|
begin
|
||||||
|
{ if the field is an array, does it contain one element? }
|
||||||
|
currentdef:=sym.vardef;
|
||||||
|
while (currentdef.typ=arraydef) and
|
||||||
|
not is_special_array(currentdef) do
|
||||||
|
begin
|
||||||
|
if tarraydef(currentdef).elecount<>1 then
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
currentdef:=tarraydef(currentdef).elementdef;
|
||||||
|
end;
|
||||||
|
{ if the array element is again a record, continue descending }
|
||||||
|
if currentdef.typ=recorddef then
|
||||||
|
currentsymlist:=trecorddef(currentdef).symtable.SymList
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ otherwise we found the type of the single element }
|
||||||
|
def:=currentdef;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
exit
|
||||||
|
until false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function tabstractrecordsymtable.get_unit_symtable: tsymtable;
|
function tabstractrecordsymtable.get_unit_symtable: tsymtable;
|
||||||
|
@ -1069,6 +1069,7 @@ unit cpupara;
|
|||||||
var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
|
var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
|
||||||
var
|
var
|
||||||
hp : tparavarsym;
|
hp : tparavarsym;
|
||||||
|
fdef,
|
||||||
paradef : tdef;
|
paradef : tdef;
|
||||||
paraloc : pcgparalocation;
|
paraloc : pcgparalocation;
|
||||||
subreg : tsubregister;
|
subreg : tsubregister;
|
||||||
@ -1082,7 +1083,6 @@ unit cpupara;
|
|||||||
i,
|
i,
|
||||||
varalign,
|
varalign,
|
||||||
paraalign : longint;
|
paraalign : longint;
|
||||||
sym: tfieldvarsym;
|
|
||||||
begin
|
begin
|
||||||
paraalign:=get_para_align(p.proccalloption);
|
paraalign:=get_para_align(p.proccalloption);
|
||||||
{ Register parameters are assigned from left to right }
|
{ Register parameters are assigned from left to right }
|
||||||
@ -1095,10 +1095,10 @@ unit cpupara;
|
|||||||
if (target_info.system=system_x86_64_win64) and
|
if (target_info.system=system_x86_64_win64) and
|
||||||
((paradef.typ=recorddef) {or
|
((paradef.typ=recorddef) {or
|
||||||
is_object(paradef)}) and
|
is_object(paradef)}) and
|
||||||
tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
|
tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(fdef) and
|
||||||
(sym.vardef.typ=floatdef) and
|
(fdef.typ=floatdef) and
|
||||||
(tfloatdef(sym.vardef).floattype in [s32real,s64real]) then
|
(tfloatdef(fdef).floattype in [s32real,s64real]) then
|
||||||
paradef:=sym.vardef;
|
paradef:=fdef;
|
||||||
|
|
||||||
pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
|
pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
|
||||||
if pushaddr then
|
if pushaddr then
|
||||||
|
Loading…
Reference in New Issue
Block a user