cpupara.pas 26 KB

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