* keep track of whether a routine has a C-style variadic parameter in the

procoptions even when it's through an array-of-const parameter
  * always call create_varargs_paraloc_info() instead of create_paraloc_info()
    in the former case, even when no varargs parameters are specified (because
    on some platforms even some non-variadic parameters need to be passed
    differently, such as on ARM with gnueabihf)

git-svn-id: trunk@41420 -
This commit is contained in:
Jonas Maebe 2019-02-23 15:42:45 +00:00
parent 1a559f5c60
commit 8b9e90dc7a
21 changed files with 231 additions and 156 deletions

View File

@ -42,7 +42,7 @@ unit cpupara;
function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override; function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override; function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override;
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;override; function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist):longint;override;
function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
function param_use_paraloc(const cgpara: tcgpara): boolean; override; function param_use_paraloc(const cgpara: tcgpara): boolean; override;
private private
@ -639,12 +639,12 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist):longint;
begin begin
init_para_alloc_values; init_para_alloc_values;
{ non-variadic parameters } { non-variadic parameters }
create_paraloc_info_intern(p,callerside,p.paras,false); create_paraloc_info_intern(p,side,p.paras,false);
if p.proccalloption in cstylearrayofconst then if p.proccalloption in cstylearrayofconst then
begin begin
{ on Darwin, we cannot use any registers for variadic parameters } { on Darwin, we cannot use any registers for variadic parameters }
@ -654,11 +654,19 @@ unit cpupara;
curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG); curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
end; end;
{ continue loading the parameters } { continue loading the parameters }
create_paraloc_info_intern(p,callerside,varargspara,true); if assigned(varargspara) then
begin
if side=callerside then
create_paraloc_info_intern(p,side,varargspara,true)
else
internalerror(2019021916);
end;
result:=curstackoffset; result:=curstackoffset;
end end
else else
internalerror(200410231); internalerror(200410231);
create_funcretloc_info(p,side);
end; end;
begin begin

View File

@ -42,7 +42,7 @@ unit cpupara;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override; function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private private
procedure init_values(p: tabstractprocdef; side: tcallercallee; var curintreg, procedure init_values(p: tabstractprocdef; side: tcallercallee; var curintreg,
@ -778,20 +778,30 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister; curintreg, curfloatreg, curmmreg: tsuperregister;
sparesinglereg:tregister; sparesinglereg:tregister;
begin begin
init_values(p,callerside,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg); init_values(p,side,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true); result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
if (p.proccalloption in cstylearrayofconst) then if (p.proccalloption in cstylearrayofconst) then
begin
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true) if assigned(varargspara) then
begin
if side=callerside then
result:=create_paraloc_info_intern(p,side,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
else
internalerror(2019021915);
end;
end
else else
internalerror(200410231); internalerror(200410231);
create_funcretloc_info(p,side);
end; end;
begin begin

View File

@ -39,7 +39,7 @@ unit cpupara;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override; function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override; function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@ -526,17 +526,25 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister; curintreg, curfloatreg, curmmreg: tsuperregister;
begin begin
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
if (p.proccalloption in cstylearrayofconst) then if (p.proccalloption in cstylearrayofconst) then
begin
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset) if assigned(varargspara) then
begin
if side=callerside then
result:=create_paraloc_info_intern(p,side,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset)
else
internalerror(2019021914);
end;
end
else else
internalerror(200410231); internalerror(200410231);
end; end;

View File

@ -325,6 +325,9 @@ interface
{ # returns true if the procdef has no parameters and no specified return type } { # returns true if the procdef has no parameters and no specified return type }
function is_bareprocdef(pd : tprocdef): boolean; function is_bareprocdef(pd : tprocdef): boolean;
{ returns true if the procdef is a C-style variadic function }
function is_c_variadic(pd: tabstractprocdef): boolean; {$ifdef USEINLINE}inline;{$endif}
{ # returns the smallest base integer type whose range encompasses that of { # returns the smallest base integer type whose range encompasses that of
both ld and rd; if keep_sign_if_equal, then if ld and rd have the same both ld and rd; if keep_sign_if_equal, then if ld and rd have the same
signdness, the result will also get that signdness } signdness, the result will also get that signdness }
@ -1496,6 +1499,12 @@ implementation
(pd.proctypeoption = potype_constructor)); (pd.proctypeoption = potype_constructor));
end; end;
function is_c_variadic(pd: tabstractprocdef): boolean;
begin
result:=
(po_varargs in pd.procoptions) or
(po_variadic in pd.procoptions);
end;
function get_common_intdef(ld, rd: torddef; keep_sign_if_equal: boolean): torddef; function get_common_intdef(ld, rd: torddef; keep_sign_if_equal: boolean): torddef;
var var

View File

@ -42,7 +42,7 @@ unit cpupara;
function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override; function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override; function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override; procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override;
private private
@ -767,15 +767,22 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
parasize : longint; parasize : longint;
begin begin
parasize:=0; parasize:=0;
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_stdcall_paraloc_info(p,callerside,p.paras,parasize); create_stdcall_paraloc_info(p,side,p.paras,parasize);
{ append the varargs } { append the varargs }
create_stdcall_paraloc_info(p,callerside,varargspara,parasize); if assigned(varargspara) then
begin
if side=callerside then
create_stdcall_paraloc_info(p,side,varargspara,parasize)
else
internalerror(2019021926);
end;
create_funcretloc_info(p,side);
result:=parasize; result:=parasize;
end; end;

View File

@ -55,7 +55,7 @@ unit cpupara;
} }
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override; procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override;
private private
@ -783,15 +783,22 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
parasize : longint; parasize : longint;
begin begin
parasize:=0; parasize:=0;
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_stdcall_paraloc_info(p,callerside,p.paras,parasize); create_stdcall_paraloc_info(p,side,p.paras,parasize);
{ append the varargs } { append the varargs }
create_stdcall_paraloc_info(p,callerside,varargspara,parasize); if assigned(varargspara) then
begin
if side=callerside then
create_stdcall_paraloc_info(p,side,varargspara,parasize)
else
internalerror(2019021925);
end;
create_funcretloc_info(p,side);
result:=parasize; result:=parasize;
end; end;

View File

@ -46,7 +46,7 @@ interface
@param(nr Parameter number of routine, starting from 1)} @param(nr Parameter number of routine, starting from 1)}
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override; function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
function param_use_paraloc(const cgpara: tcgpara): boolean; override; function param_use_paraloc(const cgpara: tcgpara): boolean; override;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override; function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
@ -209,15 +209,22 @@ implementation
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
parasize : longint; parasize : longint;
begin begin
parasize:=0; parasize:=0;
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_paraloc_info_intern(p,callerside,p.paras,parasize); create_paraloc_info_intern(p,side,p.paras,parasize);
{ append the varargs } { append the varargs }
create_paraloc_info_intern(p,callerside,varargspara,parasize); if assigned(varargspara) then
begin
if side=callerside then
create_paraloc_info_intern(p,side,varargspara,parasize)
else
internalerror(2019021924);
end;
create_funcretloc_info(p,side);
result:=parasize; result:=parasize;
end; end;

View File

@ -45,7 +45,7 @@ unit cpupara;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override; function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override; procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;override; function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;override;
function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override; function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override; function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
@ -675,18 +675,27 @@ unit cpupara;
inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara); inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
begin begin
cur_stack_offset:=0; cur_stack_offset:=0;
result:=create_stdcall_paraloc_info(p,callerside,p.paras,cur_stack_offset); result:=create_stdcall_paraloc_info(p,side,p.paras,cur_stack_offset);
if (p.proccalloption in cstylearrayofconst) then if (p.proccalloption in cstylearrayofconst) then
begin
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
result:=create_stdcall_paraloc_info(p,callerside,varargspara,cur_stack_offset) if assigned(varargspara) then
begin
if side=callerside then
result:=create_stdcall_paraloc_info(p,side,varargspara,cur_stack_offset)
else
internalerror(2019021923);
end;
end
else else
internalerror(200410231); internalerror(200410231);
create_funcretloc_info(p,side);
end; end;

View File

@ -73,7 +73,7 @@ interface
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override; function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
function get_saved_registers_int(calloption : tproccalloption):TCpuRegisterArray;override; function get_saved_registers_int(calloption : tproccalloption):TCpuRegisterArray;override;
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override; function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : TAbstractProcDef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
function param_use_paraloc(const cgpara: tcgpara): boolean; override; function param_use_paraloc(const cgpara: tcgpara): boolean; override;
private private
@ -490,7 +490,7 @@ implementation
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
begin begin
intparareg:=0; intparareg:=0;
intparasize:=0; intparasize:=0;
@ -498,13 +498,20 @@ implementation
{ Create Function result paraloc } { Create Function result paraloc }
create_funcretloc_info(p,callerside); create_funcretloc_info(p,callerside);
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_paraloc_info_intern(p,callerside,p.paras); create_paraloc_info_intern(p,side,p.paras);
{ append the varargs } { append the varargs }
can_use_float := false; can_use_float := false;
{ restore correct intparasize value } { restore correct intparasize value }
if intparareg < 4 then if intparareg < 4 then
intparasize:=intparareg * 4; intparasize:=intparareg * 4;
create_paraloc_info_intern(p,callerside,varargspara); if assigned(varargspara) then
begin
if side=callerside then
create_paraloc_info_intern(p,side,varargspara)
else
internalerror(2019021922);
end;
create_funcretloc_info(p,side);
{ We need to return the size allocated on the stack } { We need to return the size allocated on the stack }
result:=intparasize; result:=intparasize;
end; end;

View File

@ -4416,7 +4416,7 @@ implementation
{ calculate the parameter size needed for this call include varargs if they are available } { calculate the parameter size needed for this call include varargs if they are available }
if assigned(varargsparas) then if assigned(varargsparas) then
pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,varargsparas) pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,callerside,varargsparas)
else else
pushedparasize:=procdefinition.callerargareasize; pushedparasize:=procdefinition.callerargareasize;

View File

@ -140,7 +140,7 @@ unit paramgr;
for the routine that are passed as varargs. It returns for the routine that are passed as varargs. It returns
the size allocated on the stack (including the normal parameters) the size allocated on the stack (including the normal parameters)
} }
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;virtual;abstract; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;virtual;abstract;
function is_stack_paraloc(paraloc: pcgparalocation): boolean;virtual; function is_stack_paraloc(paraloc: pcgparalocation): boolean;virtual;
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);virtual; procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);virtual;

View File

@ -1520,6 +1520,13 @@ implementation
internalerror(2015052202); internalerror(2015052202);
end; end;
if (pd.proccalloption in cdecl_pocalls) and
(pd.paras.count>0) and
is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef) then
begin
include(pd.procoptions,po_variadic);
end;
{ file types can't be function results } { file types can't be function results }
if assigned(pd) and if assigned(pd) and
(pd.returndef.typ=filedef) then (pd.returndef.typ=filedef) then

View File

@ -40,7 +40,7 @@ unit cpupara;
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@ -628,7 +628,7 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
parasize, l: longint; parasize, l: longint;
@ -640,36 +640,27 @@ unit cpupara;
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
firstfloatreg:=curfloatreg; firstfloatreg:=curfloatreg;
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false); result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
if (p.proccalloption in cstylearrayofconst) then if (p.proccalloption in cstylearrayofconst) then
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
begin begin
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true); if assigned(varargspara) then
begin
if side=callerside then
result:=create_paraloc_info_intern(p,side,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true)
else
internalerror(2019021921);
if curfloatreg<>firstfloatreg then
include(varargspara.varargsinfo,va_uses_float_reg);
end;
{ varargs routines have to reserve at least 32 bytes for the AIX abi } { varargs routines have to reserve at least 32 bytes for the AIX abi }
if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
(result < 32) then (result < 32) then
result := 32; result := 32;
end end
else else
begin internalerror(2019021710);
parasize:=cur_stack_offset; create_funcretloc_info(p,side);
for i:=0 to varargspara.count-1 do
begin
hp:=tparavarsym(varargspara[i]);
hp.paraloc[callerside].alignment:=4;
paraloc:=hp.paraloc[callerside].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=def_cgsize(hp.vardef);
paraloc^.def:=hp.vardef;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
paraloc^.reference.offset:=parasize;
parasize:=parasize+l;
end;
result:=parasize;
end;
if curfloatreg<>firstfloatreg then
include(varargspara.varargsinfo,va_uses_float_reg);
end; end;

View File

@ -45,8 +45,7 @@ type
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override; function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
function create_varargs_paraloc_info(p: tabstractprocdef; varargspara: function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist): longint; override;
tvarargsparalist): longint; override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private private
@ -743,7 +742,7 @@ implemented
end; end;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee;
varargspara: tvarargsparalist): longint; varargspara: tvarargsparalist): longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
@ -756,33 +755,28 @@ begin
init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset); init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
firstfloatreg := curfloatreg; firstfloatreg := curfloatreg;
result := create_paraloc_info_intern(p, callerside, p.paras, curintreg, result := create_paraloc_info_intern(p, side, p.paras, curintreg,
curfloatreg, curmmreg, cur_stack_offset, false); curfloatreg, curmmreg, cur_stack_offset, false);
if (p.proccalloption in cstylearrayofconst) then begin if (p.proccalloption in cstylearrayofconst) then
begin
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
result := create_paraloc_info_intern(p, callerside, varargspara, curintreg, if assigned(varargspara) then
curfloatreg, curmmreg, cur_stack_offset, true); begin
if side=callerside then
result := create_paraloc_info_intern(p, side, varargspara, curintreg,
curfloatreg, curmmreg, cur_stack_offset, true)
else
internalerror(2019021920);
if curfloatreg <> firstfloatreg then
include(varargspara.varargsinfo, va_uses_float_reg);
end;
{ varargs routines have to reserve at least 64 bytes for the PPC64 ABI } { varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
if (result < 64) then if (result < 64) then
result := 64; result := 64;
end else begin end
parasize := cur_stack_offset; else
for i := 0 to varargspara.count - 1 do begin internalerror(2019021911);
hp := tparavarsym(varargspara[i]); create_funcretloc_info(p, side);
hp.paraloc[callerside].alignment := 8;
paraloc := hp.paraloc[callerside].add_location;
paraloc^.loc := LOC_REFERENCE;
paraloc^.size := def_cgsize(hp.vardef);
paraloc^.def := hp.vardef;
paraloc^.reference.index := NR_STACK_POINTER_REG;
l := push_size(hp.varspez, hp.vardef, p.proccalloption);
paraloc^.reference.offset := parasize;
parasize := parasize + l;
end;
result := parasize;
end;
if curfloatreg <> firstfloatreg then
include(varargspara.varargsinfo, va_uses_float_reg);
end; end;
function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean; function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;

View File

@ -39,7 +39,7 @@ unit cpupara;
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@ -505,7 +505,7 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
parasize, l: longint; parasize, l: longint;
@ -517,33 +517,24 @@ unit cpupara;
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
firstfloatreg:=curfloatreg; firstfloatreg:=curfloatreg;
result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false); result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
if (p.proccalloption in cstylearrayofconst) then if (p.proccalloption in cstylearrayofconst) then
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
begin begin
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true); if assigned(varargspara) then
end begin
if side=callerside then
result:=create_paraloc_info_intern(p,side,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true)
else else
begin internalerror(2019021919);
parasize:=cur_stack_offset;
for i:=0 to varargspara.count-1 do
begin
hp:=tparavarsym(varargspara[i]);
hp.paraloc[callerside].alignment:=4;
paraloc:=hp.paraloc[callerside].add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=def_cgsize(hp.vardef);
paraloc^.def:=hp.vardef;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
paraloc^.reference.offset:=parasize;
parasize:=parasize+l;
end;
result:=parasize;
end;
if curfloatreg<>firstfloatreg then if curfloatreg<>firstfloatreg then
include(varargspara.varargsinfo,va_uses_float_reg); include(varargspara.varargsinfo,va_uses_float_reg);
end; end;
end
else
internalerror(2019021912);
create_funcretloc_info(p,side);
end;
begin begin
paramanager:=tcpuparamanager.create; paramanager:=tcpuparamanager.create;

View File

@ -40,7 +40,7 @@ unit cpupara;
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override; procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); override;
function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override; function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
function create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist): longint; override; function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist): longint; override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private private
@ -490,7 +490,7 @@ implementation
end; end;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee;
varargspara: tvarargsparalist): longint; varargspara: tvarargsparalist): longint;
var var
cur_stack_offset: aword; cur_stack_offset: aword;
@ -503,33 +503,29 @@ begin
init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset); init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
firstfloatreg := curfloatreg; firstfloatreg := curfloatreg;
result := create_paraloc_info_intern(p, callerside, p.paras, curintreg, result := create_paraloc_info_intern(p, side, p.paras, curintreg,
curfloatreg, curmmreg, cur_stack_offset, false); curfloatreg, curmmreg, cur_stack_offset, false);
if (p.proccalloption in [pocall_cdecl, pocall_cppdecl, pocall_mwpascal]) then begin if (p.proccalloption in [pocall_cdecl, pocall_cppdecl, pocall_mwpascal]) then
begin
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
result := create_paraloc_info_intern(p, callerside, varargspara, curintreg, if assigned(varargspara) then
curfloatreg, curmmreg, cur_stack_offset, true); begin
if side=callerside then
result := create_paraloc_info_intern(p, side, varargspara, curintreg,
curfloatreg, curmmreg, cur_stack_offset, true)
else
internalerror(2019021918);
if curfloatreg <> firstfloatreg then
include(varargspara.varargsinfo, va_uses_float_reg);
end;
{ varargs routines have to reserve at least 64 bytes for the RiscV ABI } { varargs routines have to reserve at least 64 bytes for the RiscV ABI }
if (result < 64) then if (result < 64) then
result := 64; result := 64;
end else begin end
parasize := cur_stack_offset; else
for i := 0 to varargspara.count - 1 do begin internalerror(2019021913);
hp := tparavarsym(varargspara[i]);
hp.paraloc[callerside].alignment := 8; create_funcretloc_info(p, side);
paraloc := hp.paraloc[callerside].add_location;
paraloc^.loc := LOC_REFERENCE;
paraloc^.size := def_cgsize(hp.vardef);
paraloc^.def := hp.vardef;
paraloc^.reference.index := NR_STACK_POINTER_REG;
l := push_size(hp.varspez, hp.vardef, p.proccalloption);
paraloc^.reference.offset := parasize;
parasize := parasize + l;
end;
result := parasize;
end;
if curfloatreg <> firstfloatreg then
include(varargspara.varargsinfo, va_uses_float_reg);
end; end;
function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean; function tcpuparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;

View File

@ -35,7 +35,7 @@ interface
function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override; function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override; function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override; function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : TAbstractProcDef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
var curintreg: longint; curfloatreg: tsuperregister; var cur_stack_offset: aword);virtual;abstract; var curintreg: longint; curfloatreg: tsuperregister; var cur_stack_offset: aword);virtual;abstract;
end; end;
@ -66,7 +66,7 @@ implementation
end; end;
function tsparcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tsparcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
curintreg : LongInt; curintreg : LongInt;
curfloatreg : TSuperRegister; curfloatreg : TSuperRegister;
@ -76,9 +76,15 @@ implementation
curfloatreg:=RS_F0; curfloatreg:=RS_F0;
cur_stack_offset:=0; cur_stack_offset:=0;
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,cur_stack_offset); create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,cur_stack_offset);
{ append the varargs } { append the varargs }
create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,cur_stack_offset); if assigned(varargspara) then
begin
if side=callerside then
create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,cur_stack_offset)
else
internalerror(2019021927);
end;
result:=cur_stack_offset; result:=cur_stack_offset;
end; end;

View File

@ -415,7 +415,10 @@ type
{ procedure is an automatically generated property setter } { procedure is an automatically generated property setter }
po_is_auto_setter, po_is_auto_setter,
{ must never be inlined by auto-inlining } { must never be inlined by auto-inlining }
po_noinline po_noinline,
{ same as po_varargs, but with an array-of-const parameter instead of with the
"varargs" modifier or Mac-Pascal ".." parameter }
po_variadic
); );
tprocoptions=set of tprocoption; tprocoptions=set of tprocoption;
@ -1027,7 +1030,8 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has
'C-style blocks',{po_is_block} 'C-style blocks',{po_is_block}
'po_is_auto_getter',{po_is_auto_getter} 'po_is_auto_getter',{po_is_auto_getter}
'po_is_auto_setter',{po_is_auto_setter} 'po_is_auto_setter',{po_is_auto_setter}
'po_noinline'{po_noinline} 'po_noinline',{po_noinline}
'C-style array-of-const' {po_variadic}
); );
implementation implementation

View File

@ -5284,7 +5284,10 @@ implementation
if (side in [callerside,callbothsides]) and if (side in [callerside,callbothsides]) and
not(has_paraloc_info in [callerside,callbothsides]) then not(has_paraloc_info in [callerside,callbothsides]) then
begin begin
callerargareasize:=paramanager.create_paraloc_info(self,callerside); if not is_c_variadic(self) then
callerargareasize:=paramanager.create_paraloc_info(self,callerside)
else
callerargareasize:=paramanager.create_varargs_paraloc_info(self,callerside,nil);
if has_paraloc_info in [calleeside,callbothsides] then if has_paraloc_info in [calleeside,callbothsides] then
has_paraloc_info:=callbothsides has_paraloc_info:=callbothsides
else else
@ -5293,7 +5296,10 @@ implementation
if (side in [calleeside,callbothsides]) and if (side in [calleeside,callbothsides]) and
not(has_paraloc_info in [calleeside,callbothsides]) then not(has_paraloc_info in [calleeside,callbothsides]) then
begin begin
calleeargareasize:=paramanager.create_paraloc_info(self,calleeside); if not is_c_variadic(self) then
calleeargareasize:=paramanager.create_paraloc_info(self,calleeside)
else
callerargareasize:=paramanager.create_varargs_paraloc_info(self,calleeside,nil);
if has_paraloc_info in [callerside,callbothsides] then if has_paraloc_info in [callerside,callbothsides] then
has_paraloc_info:=callbothsides has_paraloc_info:=callbothsides
else else

View File

@ -2016,7 +2016,8 @@ const
(mask:po_is_block; str: 'C "Block"'), (mask:po_is_block; str: 'C "Block"'),
(mask:po_is_auto_getter; str: 'Automatically generated getter'), (mask:po_is_auto_getter; str: 'Automatically generated getter'),
(mask:po_is_auto_setter; str: 'Automatically generated setter'), (mask:po_is_auto_setter; str: 'Automatically generated setter'),
(mask:po_noinline; str: 'Never inline') (mask:po_noinline; str: 'Never inline'),
(mask:po_variadic; str: 'C VarArgs with array-of-const para')
); );
var var
proctypeoption : tproctypeoption; proctypeoption : tproctypeoption;

View File

@ -46,7 +46,7 @@ unit cpupara;
function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override; function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;override;
function get_saved_registers_mm(calloption: tproccalloption):tcpuregisterarray;override; function get_saved_registers_mm(calloption: tproccalloption):tcpuregisterarray;override;
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;override;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override; function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
end; end;
@ -1946,7 +1946,7 @@ unit cpupara;
end; end;
function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
var var
intparareg,mmparareg, intparareg,mmparareg,
parasize : longint; parasize : longint;
@ -1958,11 +1958,18 @@ unit cpupara;
else else
parasize:=0; parasize:=0;
{ calculate the registers for the normal parameters } { calculate the registers for the normal parameters }
create_paraloc_info_intern(p,callerside,p.paras,intparareg,mmparareg,parasize,false); create_paraloc_info_intern(p,side,p.paras,intparareg,mmparareg,parasize,false);
{ append the varargs } { append the varargs }
create_paraloc_info_intern(p,callerside,varargspara,intparareg,mmparareg,parasize,true); if assigned(varargspara) then
begin
if side=callerside then
create_paraloc_info_intern(p,side,varargspara,intparareg,mmparareg,parasize,true)
else
internalerror(2019021917);
{ store used no. of SSE registers, that needs to be passed in %AL } { store used no. of SSE registers, that needs to be passed in %AL }
varargspara.mmregsused:=mmparareg; varargspara.mmregsused:=mmparareg;
end;
create_funcretloc_info(p,side);
result:=parasize; result:=parasize;
end; end;