* implemented parameter passing and function result locations

git-svn-id: trunk@29862 -
This commit is contained in:
Jonas Maebe 2015-02-23 22:49:55 +00:00
parent edef6b2a0a
commit 2214966f26

View File

@ -34,18 +34,23 @@ unit cpupara;
type
taarch64paramanager = class(tparamanager)
function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
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 get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
function get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset; override;
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 get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
private
procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
curintreg,
curmmreg: tsuperregister;
curstackoffset: aword;
procedure init_para_alloc_values;
procedure alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
procedure create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
end;
implementation
@ -55,6 +60,13 @@ unit cpupara;
rgobj,
defutil,symsym,symtable;
const
RS_FIRST_INT_PARAM_SUPREG = RS_X0;
RS_LAST_INT_PARAM_SUPREG = RS_X7;
{ Q0/D0/S0/H0/B0 all have the same superregister number }
RS_FIRST_MM_PARAM_SUPREG = RS_D0;
RS_LAST_MM_PARAM_SUPREG = RS_D7;
function taarch64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
begin
@ -265,7 +277,7 @@ unit cpupara;
end;
function taarch64paramanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
function taarch64paramanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
begin
if handle_common_ret_in_param(def,pd,result) then
exit;
@ -275,428 +287,329 @@ unit cpupara;
end;
procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
begin
curintreg:=RS_R0;
curfloatreg:=RS_F0;
curmmreg:=RS_D0;
cur_stack_offset:=0;
sparesinglereg := NR_NO;
end;
function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
procedure taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
var
nextintreg,nextfloatreg,nextmmreg : tsuperregister;
paradef : tdef;
paraloc : pcgparalocation;
stack_offset : aword;
hp : tparavarsym;
loc : tcgloc;
paracgsize : tcgsize;
paralen : longint;
i : integer;
firstparaloc: boolean;
procedure assignintreg;
begin
{ In case of po_delphi_nested_cc, the parent frame pointer
is always passed on the stack. }
if (nextintreg<=RS_R3) and
(not(vo_is_parentfp in hp.varoptions) or
not(po_delphi_nested_cc in p.procoptions)) then
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
inc(nextintreg);
end
else
begin
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,4);
end;
end;
hp: tparavarsym;
i: longint;
begin
result:=0;
nextintreg:=curintreg;
nextfloatreg:=curfloatreg;
nextmmreg:=curmmreg;
stack_offset:=cur_stack_offset;
for i:=0 to paras.count-1 do
begin
hp:=tparavarsym(paras[i]);
paradef:=hp.vardef;
hp.paraloc[side].reset;
{ currently only support C-style array of const,
there should be no location assigned to the vararg array itself }
if (p.proccalloption in cstylearrayofconst) and
is_array_of_const(paradef) then
{ hidden function result parameter is passed in X8 (doesn't have to
be valid on return) }
if vo_is_funcret in hp.varoptions then
begin
paraloc:=hp.paraloc[side].add_location;
{ hack: the paraloc must be valid, but is not actually used }
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_R0;
paraloc^.size:=OS_ADDR;
break;
end;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paradef:=getpointerdef(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
hp.paraloc[side].reset;
hp.paraloc[side].size:=OS_ADDR;
hp.paraloc[side].alignment:=voidpointertype.alignment;
hp.paraloc[side].intsize:=voidpointertype.size;
hp.paraloc[side].def:=getpointerdef(hp.vardef);
with hp.paraloc[side].add_location^ do
begin
size:=OS_ADDR;
def:=hp.paraloc[side].def;
loc:=LOC_REGISTER;
register:=NR_X8;
end
end
else
begin
if not is_special_array(paradef) then
paralen := paradef.size
else
paralen := tcgsize2size[def_cgsize(paradef)];
loc := getparaloc(p.proccalloption,paradef,isvariadic);
if (paradef.typ in [objectdef,arraydef,recorddef]) and
not is_special_array(paradef) and
(hp.varspez in [vs_value,vs_const]) then
paracgsize := int_cgsize(paralen)
else
begin
paracgsize:=def_cgsize(paradef);
{ for things like formaldef }
if (paracgsize=OS_NO) then
begin
paracgsize:=OS_ADDR;
paralen:=tcgsize2size[OS_ADDR];
paradef:=voidpointertype;
end;
end
end;
hp.paraloc[side].size:=paracgsize;
hp.paraloc[side].Alignment:=std_param_align;
hp.paraloc[side].intsize:=paralen;
hp.paraloc[side].def:=paradef;
firstparaloc:=true;
{$ifdef EXTDEBUG}
if paralen=0 then
internalerror(200410311);
{$endif EXTDEBUG}
while paralen>0 do
begin
paraloc:=hp.paraloc[side].add_location;
if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
case paracgsize of
OS_F32:
paraloc^.size:=OS_32;
OS_F64:
paraloc^.size:=OS_32;
else
internalerror(2005082901);
end
else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
paraloc^.size := OS_32
else
paraloc^.size:=paracgsize;
case loc of
LOC_REGISTER:
begin
{ align registers for eabi }
if (target_info.abi in [abi_eabi,abi_eabihf]) and
firstparaloc and
(paradef.alignment=8) then
begin
if (nextintreg in [RS_R1,RS_R3]) then
inc(nextintreg)
else if nextintreg>RS_R3 then
stack_offset:=align(stack_offset,8);
end;
{ this is not abi compliant
why? (FK) }
if nextintreg<=RS_R3 then
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
inc(nextintreg);
end
else
begin
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,align(paralen,4));
paralen:=0;
end;
end;
LOC_FPUREGISTER:
begin
if nextfloatreg<=RS_F3 then
begin
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
inc(nextfloatreg);
end
else
begin
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
case paraloc^.size of
OS_F32:
inc(stack_offset,4);
OS_F64:
inc(stack_offset,8);
OS_F80:
inc(stack_offset,10);
OS_F128:
inc(stack_offset,16);
else
internalerror(200403201);
end;
end;
end;
LOC_MMREGISTER:
begin
if (nextmmreg<=RS_D7) or
((paraloc^.size = OS_F32) and
(sparesinglereg<>NR_NO)) then
begin
paraloc^.loc:=LOC_MMREGISTER;
case paraloc^.size of
OS_F32:
if sparesinglereg = NR_NO then
begin
paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
inc(nextmmreg);
end
else
begin
paraloc^.register:=sparesinglereg;
sparesinglereg := NR_NO;
end;
OS_F64:
begin
paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
inc(nextmmreg);
end;
else
internalerror(2012031601);
end;
end
else
begin
{ once a floating point parameters has been placed
on the stack we must not pass any more in vfp regs
even if there is a single precision register still
free}
sparesinglereg := NR_NO;
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,align(paralen,4));
paralen:=0;
end;
end;
LOC_REFERENCE:
begin
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paraloc^.size:=OS_ADDR;
assignintreg
end
else
begin
{ align stack for eabi }
if (target_info.abi in [abi_eabi,abi_eabihf]) and
firstparaloc and
(paradef.alignment=8) then
stack_offset:=align(stack_offset,8);
paraloc^.size:=paracgsize;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
inc(stack_offset,align(paralen,4));
paralen:=0
end;
end;
else
internalerror(2002071002);
end;
if side=calleeside then
begin
if paraloc^.loc=LOC_REFERENCE then
begin
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
{ on non-Darwin, the framepointer contains the value
of the stack pointer on entry. On Darwin, the
framepointer points to the previously saved
framepointer (which is followed only by the saved
return address -> framepointer + 4 = stack pointer
on entry }
if not(target_info.system in systems_darwin) then
inc(paraloc^.reference.offset,4)
else
inc(paraloc^.reference.offset,8);
end;
end;
dec(paralen,tcgsize2size[paraloc^.size]);
firstparaloc:=false
end;
alloc_para(hp.paraloc[side],p,hp.varspez,side,hp.vardef,isvariadic,
(vo_is_parentfp in hp.varoptions) and
(po_delphi_nested_cc in p.procoptions));
end;
curintreg:=nextintreg;
curfloatreg:=nextfloatreg;
curmmreg:=nextmmreg;
cur_stack_offset:=stack_offset;
result:=cur_stack_offset;
end;
function taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
var
paraloc : pcgparalocation;
retcgsize : tcgsize;
retcgsize: tcgsize;
begin
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
exit;
paraloc:=result.add_location;
{ Return in FPU register? }
if result.def.typ=floatdef then
begin
if target_info.abi = abi_eabihf then
begin
paraloc^.loc:=LOC_MMREGISTER;
case retcgsize of
OS_64,
OS_F64:
begin
paraloc^.register:=NR_MM_RESULT_REG;
end;
OS_32,
OS_F32:
begin
paraloc^.register:=NR_S0;
end;
else
internalerror(2012032501);
end;
paraloc^.size:=retcgsize;
end
else if (p.proccalloption in [pocall_softfloat]) or
(cs_fp_emulation in current_settings.moduleswitches) or
(current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
begin
case retcgsize of
OS_64,
OS_F64:
begin
paraloc^.loc:=LOC_REGISTER;
if target_info.endian = endian_big then
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
else
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
paraloc^.size:=OS_32;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if target_info.endian = endian_big then
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
else
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
paraloc^.size:=OS_32;
end;
OS_32,
OS_F32:
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
paraloc^.size:=OS_32;
end;
else
internalerror(2005082603);
end;
end
else
begin
paraloc^.loc:=LOC_FPUREGISTER;
paraloc^.register:=NR_FPU_RESULT_REG;
paraloc^.size:=retcgsize;
end;
end
{ Return in register }
else
begin
if retcgsize in [OS_64,OS_S64] then
begin
paraloc^.loc:=LOC_REGISTER;
if target_info.endian = endian_big then
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
else
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
paraloc^.size:=OS_32;
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if target_info.endian = endian_big then
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
else
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
paraloc^.size:=OS_32;
end
else
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_FUNCTION_RETURN_REG;
if (result.intsize<>3) then
paraloc^.size:=retcgsize
else
paraloc^.size:=OS_32;
end;
end;
{ in this case, it must be returned in registers as if it were passed
as the first parameter }
init_para_alloc_values;
alloc_para(result,p,vs_value,side,result.def,false,false);
{ sanity check (LOC_VOID for empty records) }
if not assigned(result.location) or
not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
internalerror(2014113001);
end;
function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
var
cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister;
sparesinglereg:tregister;
procedure taarch64paramanager.init_para_alloc_values;
begin
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
curintreg:=RS_FIRST_INT_PARAM_SUPREG;
curmmreg:=RS_FIRST_MM_PARAM_SUPREG;
curstackoffset:=0;
end;
result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
procedure taarch64paramanager.alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
var
hfabasedef, locdef: tdef;
paraloc: pcgparalocation;
paralen, stackslotlen: asizeint;
loc: tcgloc;
paracgsize, locsize: tcgsize;
firstparaloc: boolean;
begin
result.reset;
{ currently only support C-style array of const,
there should be no location assigned to the vararg array itself }
if (p.proccalloption in cstylearrayofconst) and
is_array_of_const(paradef) then
begin
paraloc:=result.add_location;
{ hack: the paraloc must be valid, but is not actually used }
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_X0;
paraloc^.size:=OS_ADDR;
exit;
end;
if push_addr_param(varspez,paradef,p.proccalloption) then
begin
paradef:=getpointerdef(paradef);
loc:=LOC_REGISTER;
paracgsize:=OS_ADDR;
paralen:=tcgsize2size[OS_ADDR];
end
else
begin
if not is_special_array(paradef) then
paralen:=paradef.size
else
paralen:=tcgsize2size[def_cgsize(paradef)];
loc:=getparaloc(p.proccalloption,paradef);
if (paradef.typ in [objectdef,arraydef,recorddef]) and
not is_special_array(paradef) and
(varspez in [vs_value,vs_const]) then
paracgsize:=int_cgsize(paralen)
else
begin
paracgsize:=def_cgsize(paradef);
{ for things like formaldef }
if paracgsize=OS_NO then
begin
paracgsize:=OS_ADDR;
paralen:=tcgsize2size[OS_ADDR];
paradef:=voidpointertype;
end;
end
end;
{ get hfa basedef if applicable }
if not is_hfa(paradef,hfabasedef) then
hfabasedef:=nil;
result.size:=paracgsize;
result.alignment:=std_param_align;
result.intsize:=paralen;
result.def:=paradef;
{ empty record: skipped (explicitly defined by Apple ABI, undefined
by general ABI; libffi also skips them in all cases) }
if not is_special_array(paradef) and
(paradef.size=0) then
begin
paraloc:=result.add_location;
paraloc^.loc:=LOC_VOID;
paraloc^.def:=paradef;
paraloc^.size:=OS_NO;
exit;
end;
{ sufficient registers left? }
case loc of
LOC_REGISTER:
begin
{ In case of po_delphi_nested_cc, the parent frame pointer
is always passed on the stack. }
if isdelphinestedcc then
loc:=LOC_REFERENCE
else if curintreg+((paralen-1) shr 3)>RS_LAST_INT_PARAM_SUPREG then
begin
{ not enough integer registers left -> no more register
parameters, copy all to stack
}
curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
loc:=LOC_REFERENCE;
end;
end;
LOC_MMREGISTER:
begin;
{ every hfa element must be passed in a separate register }
if (assigned(hfabasedef) and
(curmmreg+(paralen div hfabasedef.size)>RS_LAST_MM_PARAM_SUPREG)) or
(curmmreg+((paralen-1) shr 3)>RS_LAST_MM_PARAM_SUPREG) then
begin
{ not enough mm registers left -> no more register
parameters, copy all to stack
}
curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
loc:=LOC_REFERENCE;
end;
end;
end;
{ allocate registers/stack locations }
firstparaloc:=true;
repeat
paraloc:=result.add_location;
{ set paraloc size/def }
if assigned(hfabasedef) then
begin
locsize:=def_cgsize(hfabasedef);
locdef:=hfabasedef;
end
{ make sure we don't lose whether or not the type is signed }
else if (loc=LOC_REGISTER) and
(paradef.typ<>orddef) then
begin
locsize:=int_cgsize(paralen);
locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
end
else
begin
locsize:=paracgsize;
locdef:=paradef;
end;
if locsize in [OS_NO,OS_128,OS_S128] then
begin
if paralen>4 then
begin
paraloc^.size:=OS_INT;
paraloc^.def:=u64inttype;
end
else
begin
{ for 3-byte records }
paraloc^.size:=OS_32;
paraloc^.def:=u32inttype;
end;
end
else
begin
paraloc^.size:=locsize;
paraloc^.def:=locdef;
end;
{ paraloc loc }
paraloc^.loc:=loc;
{ assign register/stack address }
case loc of
LOC_REGISTER:
begin
paraloc^.register:=newreg(R_INTREGISTER,curintreg,cgsize2subreg(R_INTREGISTER,paraloc^.size));
inc(curintreg);
dec(paralen,tcgsize2size[paraloc^.size]);
{ "The general ABI specifies that it is the callee's
responsibility to sign or zero-extend arguments having fewer
than 32 bits, and that unused bits in a register are
unspecified. In iOS, however, the caller must perform such
extensions, up to 32 bits." }
if (target_info.abi=abi_aarch64_darwin) and
(side=callerside) and
is_ordinal(paradef) and
(paradef.size<4) then
paraloc^.size:=OS_32;
{ in case it's a composite, "The argument is passed as though
it had been loaded into the registers from a double-word-
aligned address with an appropriate sequence of LDR
instructions loading consecutive registers from memory" ->
in case of big endian, values in not completely filled
registers must be shifted to the top bits }
if (target_info.endian=endian_big) and
not(paraloc^.size in [OS_64,OS_S64]) and
(paradef.typ in [setdef,recorddef,arraydef,objectdef]) then
paraloc^.shiftval:=-(8-tcgsize2size[paraloc^.size]);
end;
LOC_MMREGISTER:
begin
paraloc^.register:=newreg(R_MMREGISTER,curmmreg,cgsize2subreg(R_MMREGISTER,paraloc^.size));
inc(curmmreg);
dec(paralen,tcgsize2size[paraloc^.size]);
end;
LOC_REFERENCE:
begin
paraloc^.size:=paracgsize;
paraloc^.loc:=LOC_REFERENCE;
if side=callerside then
paraloc^.reference.index:=NR_STACK_POINTER_REG
else
paraloc^.reference.index:=NR_FRAME_POINTER_REG;
{ the current stack offset may not be properly aligned in
case we're on Darwin have allocated a non-variadic argument
< 8 bytes previously }
if target_info.abi=abi_aarch64_darwin then
curstackoffset:=align(curstackoffset,paraloc^.def.alignment);
{ on Darwin, non-variadic arguments take up their actual size
on the stack; on other platforms, they take up a multiple of
8 bytes }
if (target_info.abi=abi_aarch64_darwin) and
not isvariadic then
stackslotlen:=paralen
else
stackslotlen:=align(paralen,8);
{ from the ABI: if arguments occupy partial stack space, they
have to occupy the lowest significant bits of a register
containing that value which is then stored to memory ->
in case of big endian, skip the alignment bytes (if any) }
if target_info.endian=endian_little then
paraloc^.reference.offset:=curstackoffset
else
paraloc^.reference.offset:=curstackoffset+stackslotlen-paralen;
inc(curstackoffset,stackslotlen);
paralen:=0
end;
else
internalerror(2002071002);
end;
firstparaloc:=false;
{ <=0 for sign/zero-extended locations }
until paralen<=0;
end;
function taarch64paramanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;
begin
init_para_alloc_values;
create_paraloc_info_intern(p,side,p.paras,false);
result:=curstackoffset;
create_funcretloc_info(p,side);
end;
function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
var
cur_stack_offset: aword;
curintreg, curfloatreg, curmmreg: tsuperregister;
sparesinglereg:tregister;
function taarch64paramanager.create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;
begin
init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
init_para_alloc_values;
result:=create_paraloc_info_intern(p,callerside,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)
{ non-variadic parameters }
create_paraloc_info_intern(p,callerside,p.paras,false);
if p.proccalloption in cstylearrayofconst then
begin
{ on Darwin, we cannot use any registers for variadic parameters }
if target_info.abi=abi_aarch64_darwin then
begin
curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
end;
{ continue loading the parameters }
create_paraloc_info_intern(p,callerside,varargspara,true);
result:=curstackoffset;
end
else
internalerror(200410231);
end;