cpupara.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. {
  2. Copyright (c) 2013-2014 by Jonas Maebe, Florian Klaempfl and others
  3. AArch64 specific calling conventions
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { AArch64 specific calling conventions are handled by this unit
  18. }
  19. unit cpupara;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. globtype,globals,
  24. aasmtai,aasmdata,
  25. cpuinfo,cpubase,cgbase,cgutils,
  26. symconst,symbase,symtype,symdef,parabase,paramgr,armpara;
  27. type
  28. tcpuparamanager = class(tarmgenparamanager)
  29. function get_volatile_registers_int(calloption: tproccalloption): tcpuregisterset; override;
  30. function get_volatile_registers_fpu(calloption: tproccalloption): tcpuregisterset; override;
  31. function get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset; override;
  32. function get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray; override;
  33. function get_saved_registers_mm(calloption: tproccalloption): tcpuregisterarray; override;
  34. function push_addr_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean; override;
  35. function ret_in_param(def: tdef; pd: tabstractprocdef):boolean;override;
  36. function create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;override;
  37. function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist):longint;override;
  38. function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
  39. function param_use_paraloc(const cgpara: tcgpara): boolean; override;
  40. private
  41. curintreg,
  42. curmmreg: tsuperregister;
  43. curstackoffset: aword;
  44. procedure init_para_alloc_values;
  45. procedure alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
  46. function getparaloc(calloption: tproccalloption; p: tdef): tcgloc;
  47. procedure create_paraloc_info_intern(p: tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
  48. end;
  49. implementation
  50. uses
  51. verbose,systems,cutils,
  52. rgobj,
  53. defutil,symsym,symtable;
  54. const
  55. RS_FIRST_INT_PARAM_SUPREG = RS_X0;
  56. RS_LAST_INT_PARAM_SUPREG = RS_X7;
  57. { Q0/D0/S0/H0/B0 all have the same superregister number }
  58. RS_FIRST_MM_PARAM_SUPREG = RS_D0;
  59. RS_LAST_MM_PARAM_SUPREG = RS_D7;
  60. function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  61. begin
  62. result:=VOLATILE_INTREGISTERS
  63. end;
  64. function tcpuparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  65. begin
  66. result:=[];
  67. end;
  68. function tcpuparamanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
  69. begin
  70. result:=VOLATILE_MMREGISTERS;
  71. end;
  72. function tcpuparamanager.get_saved_registers_int(calloption: tproccalloption): tcpuregisterarray;
  73. const
  74. saved_regs : array[0..9] of tsuperregister =
  75. (RS_X19,RS_X20,RS_X21,RS_X22,RS_X23,RS_X24,RS_X25,RS_X26,RS_X27,RS_X28);
  76. begin
  77. result:=saved_regs;
  78. end;
  79. function tcpuparamanager.get_saved_registers_mm(calloption: tproccalloption): tcpuregisterarray;
  80. const
  81. saved_mm_regs : array[0..7] of tsuperregister = (RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15);
  82. begin
  83. result:=saved_mm_regs;
  84. end;
  85. function tcpuparamanager.getparaloc(calloption: tproccalloption; p: tdef): tcgloc;
  86. var
  87. hfabasedef: tdef;
  88. begin
  89. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  90. if push_addr_param for the def is true
  91. }
  92. case p.typ of
  93. orddef:
  94. getparaloc:=LOC_REGISTER;
  95. floatdef:
  96. getparaloc:=LOC_MMREGISTER;
  97. enumdef:
  98. getparaloc:=LOC_REGISTER;
  99. pointerdef:
  100. getparaloc:=LOC_REGISTER;
  101. formaldef:
  102. getparaloc:=LOC_REGISTER;
  103. classrefdef:
  104. getparaloc:=LOC_REGISTER;
  105. recorddef:
  106. if not is_hfa(p,hfabasedef) then
  107. getparaloc:=LOC_REGISTER
  108. else
  109. getparaloc:=LOC_MMREGISTER;
  110. objectdef:
  111. getparaloc:=LOC_REGISTER;
  112. stringdef:
  113. if is_shortstring(p) or is_longstring(p) then
  114. getparaloc:=LOC_REFERENCE
  115. else
  116. getparaloc:=LOC_REGISTER;
  117. procvardef:
  118. getparaloc:=LOC_REGISTER;
  119. filedef:
  120. getparaloc:=LOC_REGISTER;
  121. arraydef:
  122. if not is_hfa(p,hfabasedef) then
  123. getparaloc:=LOC_REGISTER
  124. else
  125. getparaloc:=LOC_MMREGISTER;
  126. setdef:
  127. getparaloc:=LOC_REGISTER;
  128. variantdef:
  129. getparaloc:=LOC_REGISTER;
  130. { avoid problems with errornous definitions }
  131. errordef:
  132. getparaloc:=LOC_REGISTER;
  133. else
  134. internalerror(2002071001);
  135. end;
  136. end;
  137. function tcpuparamanager.push_addr_param(varspez: tvarspez; def :tdef; calloption: tproccalloption): boolean;
  138. var
  139. hfabasedef: tdef;
  140. begin
  141. result:=false;
  142. if varspez in [vs_var,vs_out,vs_constref] then
  143. begin
  144. result:=true;
  145. exit;
  146. end;
  147. case def.typ of
  148. objectdef:
  149. result:=is_object(def);
  150. recorddef:
  151. { ABI: any composite > 16 bytes that not a hfa/hva
  152. Special case: MWPascal, which passes all const parameters by
  153. reference for compatibility reasons
  154. }
  155. result:=
  156. ((varspez=vs_const) and
  157. (calloption=pocall_mwpascal)) or
  158. (not is_hfa(def,hfabasedef) and
  159. (def.size>16));
  160. variantdef,
  161. formaldef:
  162. result:=true;
  163. { arrays are composites and hence treated the same as records by the
  164. ABI (watch out for C, where an array is a pointer)
  165. Also: all other platforms pass const arrays by reference. Do the
  166. same here, because there is too much hacky code out there that
  167. relies on this ("array[0..0] of x" passed as const parameter and
  168. then indexed beyond its bounds) }
  169. arraydef:
  170. result:=
  171. ((calloption in cdecl_pocalls) and
  172. not is_dynamic_array(def)) or
  173. is_open_array(def) or
  174. is_array_of_const(def) or
  175. is_array_constructor(def) or
  176. ((tarraydef(def).highrange>=tarraydef(def).lowrange) and
  177. ((varspez=vs_const) or
  178. (not is_hfa(def,hfabasedef) and
  179. (def.size>16))));
  180. setdef :
  181. result:=def.size>16;
  182. stringdef :
  183. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  184. else
  185. ;
  186. end;
  187. end;
  188. function tcpuparamanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
  189. begin
  190. if handle_common_ret_in_param(def,pd,result) then
  191. exit;
  192. { ABI: if the parameter would be passed in registers, it is returned
  193. in those registers; otherwise, it's returned by reference }
  194. result:=push_addr_param(vs_value,def,pd.proccalloption);
  195. end;
  196. procedure tcpuparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
  197. var
  198. hp: tparavarsym;
  199. i: longint;
  200. begin
  201. for i:=0 to paras.count-1 do
  202. begin
  203. hp:=tparavarsym(paras[i]);
  204. { hidden function result parameter is passed in X8 (doesn't have to
  205. be valid on return) according to the ABI
  206. -- don't follow the ABI for managed types, because
  207. a) they are passed in registers as parameters, so we should also
  208. return them in a register to be ABI-compliant (which we can't
  209. because the entire compiler is built around the idea that
  210. they are returned by reference, for ref-counting performance
  211. and Delphi-compatibility reasons)
  212. b) there are hacks in the system unit that expect that you can
  213. call
  214. function f: com_interface;
  215. as
  216. procedure p(out o: obj);
  217. That can only work in case we do not use x8 to return them
  218. from the function, but the regular first parameter register.
  219. As the ABI says this behaviour is ok for C++ classes with a
  220. non-trivial copy constructor or destructor, it seems reasonable
  221. for us to do this for managed types as well.}
  222. if (vo_is_funcret in hp.varoptions) and
  223. not is_managed_type(hp.vardef) then
  224. begin
  225. hp.paraloc[side].reset;
  226. hp.paraloc[side].size:=OS_ADDR;
  227. hp.paraloc[side].alignment:=voidpointertype.alignment;
  228. hp.paraloc[side].intsize:=voidpointertype.size;
  229. hp.paraloc[side].def:=cpointerdef.getreusable_no_free(hp.vardef);
  230. with hp.paraloc[side].add_location^ do
  231. begin
  232. size:=OS_ADDR;
  233. def:=hp.paraloc[side].def;
  234. loc:=LOC_REGISTER;
  235. register:=NR_X8;
  236. end
  237. end
  238. else
  239. alloc_para(hp.paraloc[side],p,hp.varspez,side,hp.vardef,isvariadic,
  240. (vo_is_parentfp in hp.varoptions) and
  241. (po_delphi_nested_cc in p.procoptions));
  242. end;
  243. end;
  244. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  245. var
  246. retcgsize: tcgsize;
  247. begin
  248. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  249. exit;
  250. { in this case, it must be returned in registers as if it were passed
  251. as the first parameter }
  252. init_para_alloc_values;
  253. alloc_para(result,p,vs_value,side,result.def,false,false);
  254. { sanity check (LOC_VOID for empty records) }
  255. if not assigned(result.location) or
  256. not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
  257. internalerror(2014113001);
  258. {
  259. According to ARM64 ABI: "If the size of the argument is less than 8 bytes then
  260. the size of the argument is set to 8 bytes. The effect is as if the argument
  261. was copied to the least significant bits of a 64-bit register and the remaining
  262. bits filled with unspecified values."
  263. Therefore at caller side force the ordinal result to be always 64-bit, so it
  264. will be stripped to the required size and uneeded bits are discarded.
  265. This is not required for iOS, where the result is zero/sign extended.
  266. }
  267. if (target_info.abi<>abi_aarch64_darwin) and
  268. (side=callerside) and (result.location^.loc = LOC_REGISTER) and
  269. (result.def.size<8) and is_ordinal(result.def) then
  270. begin
  271. result.location^.size:=OS_64;
  272. result.location^.def:=u64inttype;
  273. end;
  274. end;
  275. function tcpuparamanager.param_use_paraloc(const cgpara: tcgpara): boolean;
  276. begin
  277. { we always set up a stack frame -> we can always access the parameters
  278. this way }
  279. result:=
  280. (cgpara.location^.loc=LOC_REFERENCE) and
  281. not assigned(cgpara.location^.next);
  282. end;
  283. procedure tcpuparamanager.init_para_alloc_values;
  284. begin
  285. curintreg:=RS_FIRST_INT_PARAM_SUPREG;
  286. curmmreg:=RS_FIRST_MM_PARAM_SUPREG;
  287. curstackoffset:=0;
  288. end;
  289. procedure tcpuparamanager.alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
  290. var
  291. hfabasedef, locdef: tdef;
  292. paraloc: pcgparalocation;
  293. paralen, stackslotlen: asizeint;
  294. loc: tcgloc;
  295. paracgsize, locsize: tcgsize;
  296. firstparaloc: boolean;
  297. begin
  298. result.reset;
  299. { currently only support C-style array of const,
  300. there should be no location assigned to the vararg array itself }
  301. if (p.proccalloption in cstylearrayofconst) and
  302. is_array_of_const(paradef) then
  303. begin
  304. result.size:=OS_NO;
  305. result.def:=paradef;
  306. result.alignment:=std_param_align;
  307. result.intsize:=0;
  308. paraloc:=result.add_location;
  309. { hack: the paraloc must be valid, but is not actually used }
  310. paraloc^.loc:=LOC_REGISTER;
  311. paraloc^.register:=NR_X0;
  312. paraloc^.size:=OS_ADDR;
  313. paraloc^.def:=paradef;
  314. exit;
  315. end;
  316. if push_addr_param(varspez,paradef,p.proccalloption) then
  317. begin
  318. paradef:=cpointerdef.getreusable_no_free(paradef);
  319. loc:=LOC_REGISTER;
  320. paracgsize:=OS_ADDR;
  321. paralen:=tcgsize2size[OS_ADDR];
  322. end
  323. else
  324. begin
  325. if not is_special_array(paradef) then
  326. paralen:=paradef.size
  327. else
  328. paralen:=tcgsize2size[def_cgsize(paradef)];
  329. loc:=getparaloc(p.proccalloption,paradef);
  330. if (paradef.typ in [objectdef,arraydef,recorddef]) and
  331. not is_special_array(paradef) and
  332. (varspez in [vs_value,vs_const]) then
  333. paracgsize:=int_cgsize(paralen)
  334. else
  335. begin
  336. paracgsize:=def_cgsize(paradef);
  337. { for things like formaldef }
  338. if paracgsize=OS_NO then
  339. begin
  340. paracgsize:=OS_ADDR;
  341. paralen:=tcgsize2size[OS_ADDR];
  342. paradef:=voidpointertype;
  343. end;
  344. end
  345. end;
  346. { get hfa basedef if applicable }
  347. if not is_hfa(paradef,hfabasedef) then
  348. hfabasedef:=nil;
  349. result.size:=paracgsize;
  350. result.alignment:=std_param_align;
  351. result.intsize:=paralen;
  352. result.def:=paradef;
  353. { empty record: skipped (explicitly defined by Apple ABI, undefined
  354. by general ABI; libffi also skips them in all cases) }
  355. if not is_special_array(paradef) and
  356. (paradef.size=0) then
  357. begin
  358. paraloc:=result.add_location;
  359. paraloc^.loc:=LOC_VOID;
  360. paraloc^.def:=paradef;
  361. paraloc^.size:=OS_NO;
  362. exit;
  363. end;
  364. { sufficient registers left? }
  365. case loc of
  366. LOC_REGISTER:
  367. begin
  368. { In case of po_delphi_nested_cc, the parent frame pointer
  369. is always passed on the stack. }
  370. if isdelphinestedcc then
  371. loc:=LOC_REFERENCE
  372. else if curintreg+((paralen-1) shr 3)>RS_LAST_INT_PARAM_SUPREG then
  373. begin
  374. { not enough integer registers left -> no more register
  375. parameters, copy all to stack
  376. }
  377. curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
  378. loc:=LOC_REFERENCE;
  379. end;
  380. end;
  381. LOC_MMREGISTER:
  382. begin;
  383. { every hfa element must be passed in a separate register }
  384. if (assigned(hfabasedef) and
  385. (curmmreg+((paralen-1) div hfabasedef.size)>RS_LAST_MM_PARAM_SUPREG)) or
  386. (curmmreg+((paralen-1) shr 3)>RS_LAST_MM_PARAM_SUPREG) then
  387. begin
  388. { not enough mm registers left -> no more register
  389. parameters, copy all to stack
  390. }
  391. curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
  392. loc:=LOC_REFERENCE;
  393. end;
  394. end;
  395. else
  396. ;
  397. end;
  398. { allocate registers/stack locations }
  399. firstparaloc:=true;
  400. repeat
  401. paraloc:=result.add_location;
  402. { set paraloc size/def }
  403. if assigned(hfabasedef) then
  404. begin
  405. locsize:=def_cgsize(hfabasedef);
  406. locdef:=hfabasedef;
  407. end
  408. { make sure we don't lose whether or not the type is signed }
  409. else if (loc=LOC_REGISTER) and
  410. (paradef.typ<>orddef) then
  411. begin
  412. locsize:=int_cgsize(paralen);
  413. locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
  414. end
  415. else
  416. begin
  417. locsize:=paracgsize;
  418. locdef:=paradef;
  419. end;
  420. if locsize in [OS_NO,OS_128,OS_S128] then
  421. begin
  422. if paralen>4 then
  423. begin
  424. paraloc^.size:=OS_INT;
  425. paraloc^.def:=u64inttype;
  426. end
  427. else
  428. begin
  429. { for 3-byte records }
  430. paraloc^.size:=OS_32;
  431. paraloc^.def:=u32inttype;
  432. end;
  433. end
  434. else
  435. begin
  436. {$ifndef llvm}
  437. paraloc^.size:=locsize;
  438. paraloc^.def:=locdef;
  439. {$else llvm}
  440. case locsize of
  441. OS_8,OS_16,OS_32:
  442. begin
  443. paraloc^.size:=OS_64;
  444. paraloc^.def:=u64inttype;
  445. end;
  446. OS_S8,OS_S16,OS_S32:
  447. begin
  448. paraloc^.size:=OS_S64;
  449. paraloc^.def:=s64inttype;
  450. end;
  451. OS_F32:
  452. begin
  453. paraloc^.size:=OS_F32;
  454. paraloc^.def:=s32floattype;
  455. end;
  456. OS_F64:
  457. begin
  458. paraloc^.size:=OS_F64;
  459. paraloc^.def:=s64floattype;
  460. end;
  461. else
  462. begin
  463. if is_record(locdef) or
  464. ((locdef.typ=arraydef) and
  465. not is_special_array(locdef)) then
  466. begin
  467. paraloc^.size:=OS_64;
  468. paraloc^.def:=u64inttype;
  469. end
  470. else
  471. begin
  472. paraloc^.size:=locsize;
  473. paraloc^.def:=locdef;
  474. end;
  475. end;
  476. end;
  477. {$endif llvm}
  478. end;
  479. { paraloc loc }
  480. paraloc^.loc:=loc;
  481. { assign register/stack address }
  482. case loc of
  483. LOC_REGISTER:
  484. begin
  485. paraloc^.register:=newreg(R_INTREGISTER,curintreg,cgsize2subreg(R_INTREGISTER,paraloc^.size));
  486. inc(curintreg);
  487. dec(paralen,tcgsize2size[paraloc^.size]);
  488. { "The general ABI specifies that it is the callee's
  489. responsibility to sign or zero-extend arguments having fewer
  490. than 32 bits, and that unused bits in a register are
  491. unspecified. In iOS, however, the caller must perform such
  492. extensions, up to 32 bits."
  493. Zero extend an argument at caller side for iOS and
  494. ignore the argument's unspecified high bits at callee side for
  495. all other platforms. }
  496. if (paradef.size<4) and is_ordinal(paradef) then
  497. begin
  498. if target_info.abi=abi_aarch64_darwin then
  499. begin
  500. if side=callerside then
  501. begin
  502. paraloc^.size:=OS_32;
  503. paraloc^.def:=u32inttype;
  504. end;
  505. end
  506. else
  507. begin
  508. if side=calleeside then
  509. begin
  510. paraloc^.size:=OS_32;
  511. paraloc^.def:=u32inttype;
  512. end;
  513. end;
  514. end;
  515. { in case it's a composite, "The argument is passed as though
  516. it had been loaded into the registers from a double-word-
  517. aligned address with an appropriate sequence of LDR
  518. instructions loading consecutive registers from memory" ->
  519. in case of big endian, values in not completely filled
  520. registers must be shifted to the top bits }
  521. if (target_info.endian=endian_big) and
  522. not(paraloc^.size in [OS_64,OS_S64]) and
  523. (paradef.typ in [setdef,recorddef,arraydef,objectdef]) then
  524. paraloc^.shiftval:=-(8-tcgsize2size[paraloc^.size])*8;
  525. end;
  526. LOC_MMREGISTER:
  527. begin
  528. paraloc^.register:=newreg(R_MMREGISTER,curmmreg,cgsize2subreg(R_MMREGISTER,paraloc^.size));
  529. inc(curmmreg);
  530. dec(paralen,tcgsize2size[paraloc^.size]);
  531. end;
  532. LOC_REFERENCE:
  533. begin
  534. paraloc^.size:=paracgsize;
  535. paraloc^.loc:=LOC_REFERENCE;
  536. { the current stack offset may not be properly aligned in
  537. case we're on Darwin and have allocated a non-variadic argument
  538. < 8 bytes previously }
  539. if target_info.abi=abi_aarch64_darwin then
  540. curstackoffset:=align(curstackoffset,paraloc^.def.alignment);
  541. { on Darwin, non-variadic arguments take up their actual size
  542. on the stack; on other platforms, they take up a multiple of
  543. 8 bytes }
  544. if (target_info.abi=abi_aarch64_darwin) and
  545. not isvariadic then
  546. stackslotlen:=paralen
  547. else
  548. stackslotlen:=align(paralen,8);
  549. { from the ABI: if arguments occupy partial stack space, they
  550. have to occupy the lowest significant bits of a register
  551. containing that value which is then stored to memory ->
  552. in case of big endian, skip the alignment bytes (if any) }
  553. if target_info.endian=endian_little then
  554. paraloc^.reference.offset:=curstackoffset
  555. else
  556. paraloc^.reference.offset:=curstackoffset+stackslotlen-paralen;
  557. if side=callerside then
  558. paraloc^.reference.index:=NR_STACK_POINTER_REG
  559. else
  560. begin
  561. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  562. inc(paraloc^.reference.offset,16);
  563. end;
  564. inc(curstackoffset,stackslotlen);
  565. paralen:=0
  566. end;
  567. else
  568. internalerror(2002071002);
  569. end;
  570. firstparaloc:=false;
  571. { <=0 for sign/zero-extended locations }
  572. until paralen<=0;
  573. end;
  574. function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;
  575. begin
  576. init_para_alloc_values;
  577. create_paraloc_info_intern(p,side,p.paras,false);
  578. result:=curstackoffset;
  579. create_funcretloc_info(p,side);
  580. end;
  581. function tcpuparamanager.create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist):longint;
  582. begin
  583. init_para_alloc_values;
  584. { non-variadic parameters }
  585. create_paraloc_info_intern(p,side,p.paras,false);
  586. if p.proccalloption in cstylearrayofconst then
  587. begin
  588. { on Darwin, we cannot use any registers for variadic parameters }
  589. if target_info.abi=abi_aarch64_darwin then
  590. begin
  591. curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
  592. curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
  593. end;
  594. { continue loading the parameters }
  595. if assigned(varargspara) then
  596. begin
  597. if side=callerside then
  598. create_paraloc_info_intern(p,side,varargspara,true)
  599. else
  600. internalerror(2019021916);
  601. end;
  602. result:=curstackoffset;
  603. end
  604. else
  605. internalerror(200410231);
  606. create_funcretloc_info(p,side);
  607. end;
  608. begin
  609. paramanager:=tcpuparamanager.create;
  610. end.