* 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 ret_in_param(def: tdef; pd: tabstractprocdef):boolean;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 param_use_paraloc(const cgpara: tcgpara): boolean; override;
private
@ -639,12 +639,12 @@ unit cpupara;
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
init_para_alloc_values;
{ 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
begin
{ on Darwin, we cannot use any registers for variadic parameters }
@ -654,11 +654,19 @@ unit cpupara;
curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
end;
{ 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;
end
else
internalerror(200410231);
create_funcretloc_info(p,side);
end;
begin

View File

@ -42,7 +42,7 @@ unit cpupara;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;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_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;
private
procedure init_values(p: tabstractprocdef; side: tcallercallee; var curintreg,
@ -778,20 +778,30 @@ unit cpupara;
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
cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister;
sparesinglereg:tregister;
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
{ just continue loading the parameters in the registers }
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
begin
{ just continue loading the parameters in the registers }
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
internalerror(200410231);
create_funcretloc_info(p,side);
end;
begin

View File

@ -39,7 +39,7 @@ unit cpupara;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;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;
private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@ -526,17 +526,25 @@ unit cpupara;
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
cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister;
begin
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
{ just continue loading the parameters in the registers }
result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset)
begin
{ just continue loading the parameters in the registers }
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
internalerror(200410231);
end;

View File

@ -325,6 +325,9 @@ interface
{ # returns true if the procdef has no parameters and no specified return type }
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
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 }
@ -1496,6 +1499,12 @@ implementation
(pd.proctypeoption = potype_constructor));
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;
var

View File

@ -42,7 +42,7 @@ unit cpupara;
function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
function get_saved_registers_int(calloption : tproccalloption):tcpuregisterarray;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;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override;
private
@ -767,15 +767,22 @@ unit cpupara;
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
parasize : longint;
begin
parasize:=0;
{ 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 }
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;
end;

View File

@ -55,7 +55,7 @@ unit cpupara;
}
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);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;
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override;
private
@ -783,15 +783,22 @@ unit cpupara;
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
parasize : longint;
begin
parasize:=0;
{ 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 }
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;
end;

View File

@ -46,7 +46,7 @@ interface
@param(nr Parameter number of routine, starting from 1)}
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);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 param_use_paraloc(const cgpara: tcgpara): boolean; override;
function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
@ -209,15 +209,22 @@ implementation
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
parasize : longint;
begin
parasize:=0;
{ 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 }
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;
end;

View File

@ -45,7 +45,7 @@ unit cpupara;
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;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;
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 get_volatile_registers_int(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);
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
cur_stack_offset: aword;
begin
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
{ just continue loading the parameters in the registers }
result:=create_stdcall_paraloc_info(p,callerside,varargspara,cur_stack_offset)
begin
{ just continue loading the parameters in the registers }
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
internalerror(200410231);
create_funcretloc_info(p,side);
end;

View File

@ -73,7 +73,7 @@ interface
function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
function get_saved_registers_int(calloption : tproccalloption):TCpuRegisterArray;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 param_use_paraloc(const cgpara: tcgpara): boolean; override;
private
@ -490,7 +490,7 @@ implementation
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
intparareg:=0;
intparasize:=0;
@ -498,13 +498,20 @@ implementation
{ Create Function result paraloc }
create_funcretloc_info(p,callerside);
{ 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 }
can_use_float := false;
{ restore correct intparasize value }
if intparareg < 4 then
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 }
result:=intparasize;
end;

View File

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

View File

@ -140,7 +140,7 @@ unit paramgr;
for the routine that are passed as varargs. It returns
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;
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);
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 }
if assigned(pd) and
(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;
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;
private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@ -628,7 +628,7 @@ unit cpupara;
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
cur_stack_offset: aword;
parasize, l: longint;
@ -640,36 +640,27 @@ unit cpupara;
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
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
{ just continue loading the parameters in the registers }
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 }
if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
(result < 32) then
result := 32;
end
else
begin
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
include(varargspara.varargsinfo,va_uses_float_reg);
internalerror(2019021710);
create_funcretloc_info(p,side);
end;

View File

@ -45,8 +45,7 @@ type
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); 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;
private
@ -743,7 +742,7 @@ implemented
end;
end;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee;
varargspara: tvarargsparalist): longint;
var
cur_stack_offset: aword;
@ -756,33 +755,28 @@ begin
init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
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);
if (p.proccalloption in cstylearrayofconst) then begin
{ just continue loading the parameters in the registers }
result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
curfloatreg, curmmreg, cur_stack_offset, true);
{ varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
if (result < 64) then
result := 64;
end else begin
parasize := cur_stack_offset;
for i := 0 to varargspara.count - 1 do begin
hp := tparavarsym(varargspara[i]);
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);
if (p.proccalloption in cstylearrayofconst) then
begin
{ just continue loading the parameters in the registers }
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(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 }
if (result < 64) then
result := 64;
end
else
internalerror(2019021911);
create_funcretloc_info(p, side);
end;
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;
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;
private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@ -505,7 +505,7 @@ unit cpupara;
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
cur_stack_offset: aword;
parasize, l: longint;
@ -517,32 +517,23 @@ unit cpupara;
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
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
{ just continue loading the parameters in the registers }
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(2019021919);
if curfloatreg<>firstfloatreg then
include(varargspara.varargsinfo,va_uses_float_reg);
end;
end
else
begin
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
include(varargspara.varargsinfo,va_uses_float_reg);
internalerror(2019021912);
create_funcretloc_info(p,side);
end;
begin

View File

@ -40,7 +40,7 @@ unit cpupara;
procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr: longint; var cgpara: tcgpara); 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;
private
@ -490,7 +490,7 @@ implementation
end;
end;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee;
varargspara: tvarargsparalist): longint;
var
cur_stack_offset: aword;
@ -503,33 +503,29 @@ begin
init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
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);
if (p.proccalloption in [pocall_cdecl, pocall_cppdecl, pocall_mwpascal]) then begin
{ just continue loading the parameters in the registers }
result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
curfloatreg, curmmreg, cur_stack_offset, true);
{ varargs routines have to reserve at least 64 bytes for the RiscV ABI }
if (result < 64) then
result := 64;
end else begin
parasize := cur_stack_offset;
for i := 0 to varargspara.count - 1 do begin
hp := tparavarsym(varargspara[i]);
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);
if (p.proccalloption in [pocall_cdecl, pocall_cppdecl, pocall_mwpascal]) then
begin
{ just continue loading the parameters in the registers }
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(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 }
if (result < 64) then
result := 64;
end
else
internalerror(2019021913);
create_funcretloc_info(p, side);
end;
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_fpu(calloption : tproccalloption):TCpuRegisterSet;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;
var curintreg: longint; curfloatreg: tsuperregister; var cur_stack_offset: aword);virtual;abstract;
end;
@ -66,7 +66,7 @@ implementation
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
curintreg : LongInt;
curfloatreg : TSuperRegister;
@ -76,9 +76,15 @@ implementation
curfloatreg:=RS_F0;
cur_stack_offset:=0;
{ 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 }
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;
end;

View File

@ -415,7 +415,10 @@ type
{ procedure is an automatically generated property setter }
po_is_auto_setter,
{ 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;
@ -1027,7 +1030,8 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has
'C-style blocks',{po_is_block}
'po_is_auto_getter',{po_is_auto_getter}
'po_is_auto_setter',{po_is_auto_setter}
'po_noinline'{po_noinline}
'po_noinline',{po_noinline}
'C-style array-of-const' {po_variadic}
);
implementation

View File

@ -5284,7 +5284,10 @@ implementation
if (side in [callerside,callbothsides]) and
not(has_paraloc_info in [callerside,callbothsides]) then
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
has_paraloc_info:=callbothsides
else
@ -5293,7 +5296,10 @@ implementation
if (side in [calleeside,callbothsides]) and
not(has_paraloc_info in [calleeside,callbothsides]) then
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
has_paraloc_info:=callbothsides
else

View File

@ -2016,7 +2016,8 @@ const
(mask:po_is_block; str: 'C "Block"'),
(mask:po_is_auto_getter; str: 'Automatically generated getter'),
(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
proctypeoption : tproctypeoption;

View File

@ -46,7 +46,7 @@ unit cpupara;
function get_saved_registers_int(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_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;
end;
@ -1946,7 +1946,7 @@ unit cpupara;
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
intparareg,mmparareg,
parasize : longint;
@ -1958,11 +1958,18 @@ unit cpupara;
else
parasize:=0;
{ 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 }
create_paraloc_info_intern(p,callerside,varargspara,intparareg,mmparareg,parasize,true);
{ store used no. of SSE registers, that needs to be passed in %AL }
varargspara.mmregsused:=mmparareg;
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 }
varargspara.mmregsused:=mmparareg;
end;
create_funcretloc_info(p,side);
result:=parasize;
end;