cpupara.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generates the argument location information for 680x0
  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. unit cpupara;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. cpubase,
  23. aasmdata,
  24. symconst,symtype,symdef,symsym,
  25. parabase,paramgr,cgbase,cgutils;
  26. type
  27. { Returns the location for the nr-st 32 Bit int parameter
  28. if every parameter before is an 32 Bit int parameter as well
  29. and if the calling conventions for the helper routines of the
  30. rtl are used.
  31. }
  32. tcpuparamanager = class(tparamanager)
  33. function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
  34. function param_use_paraloc(const cgpara:tcgpara):boolean;override;
  35. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  36. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  37. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
  38. procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
  39. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  40. function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;override;
  41. function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
  42. function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
  43. function get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;override;
  44. function get_para_align(calloption : tproccalloption):byte;override;
  45. private
  46. function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
  47. function create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  48. var cur_stack_offset: aword):longint;
  49. function create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  50. var cur_stack_offset: aword):longint;
  51. end;
  52. implementation
  53. uses
  54. verbose,
  55. globals,
  56. systems,
  57. cpuinfo,
  58. defutil,
  59. cutils,
  60. hlcgobj;
  61. const
  62. intparasupregs : array[0..1] of tsuperregister = (RS_D0,RS_D1);
  63. addrparasupregs : array[0..1] of tsuperregister = (RS_A0,RS_A1);
  64. floatparasupregs : array[0..1] of tsuperregister = (RS_FP0,RS_FP1);
  65. function tcpuparamanager.get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;
  66. begin
  67. { d0 and d1 are considered volatile }
  68. Result:=VOLATILE_INTREGISTERS;
  69. end;
  70. function tcpuparamanager.get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;
  71. begin
  72. { a0 and a1 are considered volatile }
  73. Result:=VOLATILE_ADDRESSREGISTERS;
  74. end;
  75. function tcpuparamanager.get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;
  76. begin
  77. { fp0 and fp1 are considered volatile }
  78. Result:=VOLATILE_FPUREGISTERS;
  79. end;
  80. function tcpuparamanager.get_para_align(calloption : tproccalloption):byte;
  81. begin
  82. result:=target_info.stackalign;
  83. end;
  84. function tcpuparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
  85. var
  86. paraloc : pcgparalocation;
  87. begin
  88. if not assigned(cgpara.location) then
  89. internalerror(200410102);
  90. result:=true;
  91. { All locations are LOC_REFERENCE }
  92. paraloc:=cgpara.location;
  93. while assigned(paraloc) do
  94. begin
  95. if (paraloc^.loc<>LOC_REFERENCE) then
  96. begin
  97. result:=false;
  98. exit;
  99. end;
  100. paraloc:=paraloc^.next;
  101. end;
  102. end;
  103. { TODO: copied from ppc cg, needs work}
  104. function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  105. begin
  106. result:=false;
  107. { var,out,constref always require address }
  108. if varspez in [vs_var,vs_out,vs_constref] then
  109. begin
  110. result:=true;
  111. exit;
  112. end;
  113. case def.typ of
  114. variantdef,
  115. formaldef :
  116. result:=true;
  117. recorddef:
  118. result:=(calloption in [pocall_register]) and
  119. (varspez in [vs_const]);
  120. arraydef:
  121. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  122. is_open_array(def) or
  123. is_array_of_const(def) or
  124. is_array_constructor(def);
  125. objectdef :
  126. result:=is_object(def);
  127. setdef :
  128. result:=not is_smallset(def);
  129. stringdef :
  130. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  131. procvardef :
  132. { Handling of methods must match that of records }
  133. result:=false;
  134. end;
  135. end;
  136. function tcpuparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
  137. begin
  138. if handle_common_ret_in_param(def,pd,result) then
  139. exit;
  140. case def.typ of
  141. recorddef:
  142. if def.size in [1,2,4] then
  143. begin
  144. result:=false;
  145. exit;
  146. end;
  147. end;
  148. result:=inherited ret_in_param(def,pd);
  149. end;
  150. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
  151. var
  152. paraloc : pcgparalocation;
  153. retcgsize : tcgsize;
  154. retregtype : tregistertype;
  155. begin
  156. if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
  157. exit;
  158. { always use the whole 32 bit register when returning values }
  159. if (side=calleeside) and
  160. (result.intsize>0) and
  161. (result.intsize<sizeof(aint)) then
  162. begin
  163. result.def:=sinttype;
  164. result.intsize:=sizeof(aint);
  165. retcgsize:=OS_SINT;
  166. result.size:=retcgsize;
  167. end;
  168. paraloc:=result.add_location;
  169. { Return in FPU register? }
  170. if not (cs_fp_emulation in current_settings.moduleswitches) and
  171. not (current_settings.fputype=fpu_soft) and (result.def.typ=floatdef) then
  172. begin
  173. paraloc^.loc:=LOC_FPUREGISTER;
  174. paraloc^.register:=NR_FPU_RESULT_REG;
  175. paraloc^.size:=retcgsize;
  176. paraloc^.def:=result.def;
  177. end
  178. else
  179. { Return in register }
  180. begin
  181. if retcgsize in [OS_64,OS_S64] then
  182. begin
  183. { low 32bits }
  184. paraloc^.loc:=LOC_REGISTER;
  185. paraloc^.size:=OS_32;
  186. paraloc^.def:=u32inttype;
  187. if side=callerside then
  188. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  189. else
  190. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  191. { high 32bits }
  192. paraloc:=result.add_location;
  193. paraloc^.loc:=LOC_REGISTER;
  194. paraloc^.size:=OS_32;
  195. paraloc^.def:=u32inttype;
  196. if side=calleeside then
  197. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  198. else
  199. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  200. end
  201. else
  202. begin
  203. paraloc^.loc:=LOC_REGISTER;
  204. paraloc^.size:=retcgsize;
  205. paraloc^.def:=result.def;
  206. { GCC (and SVR4 in general maybe?) requires a pointer result on the A0
  207. register, as well as D0. So we init the result to be A0, then copy
  208. it also to D0 in hlcg.gen_load_loc_function_result. This is not pretty,
  209. but we don't really have an architecture for funcretlocs in two
  210. separate locations.
  211. We also have to figure out a better switch for this, because this is
  212. now compiler and platform specific... (KB) }
  213. if (tprocdef(p).proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  214. (target_info.system in [system_m68k_linux]) and
  215. assigned(result.def) and
  216. (result.def.typ in [stringdef,pointerdef,classrefdef,objectdef,
  217. procvardef,procdef,arraydef,formaldef]) then
  218. retregtype:=R_ADDRESSREGISTER
  219. else
  220. retregtype:=R_INTREGISTER;
  221. if retregtype = R_ADDRESSREGISTER then
  222. begin
  223. if side=callerside then
  224. paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize))
  225. else
  226. paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize));
  227. end
  228. else
  229. begin
  230. if side=callerside then
  231. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  232. else
  233. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  234. end;
  235. end;
  236. end;
  237. end;
  238. function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  239. var
  240. cur_stack_offset: aword;
  241. begin
  242. cur_stack_offset:=0;
  243. case p.proccalloption of
  244. pocall_register :
  245. result:=create_register_paraloc_info(p,side,p.paras,cur_stack_offset);
  246. else
  247. result:=create_stdcall_paraloc_info(p,side,p.paras,cur_stack_offset);
  248. end;
  249. create_funcretloc_info(p,side);
  250. end;
  251. function tcpuparamanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
  252. var cur_stack_offset: aword):longint;
  253. var
  254. paraloc : pcgparalocation;
  255. hp : tparavarsym;
  256. paracgsize : tcgsize;
  257. paralen : aint;
  258. paradef : tdef;
  259. i : longint;
  260. firstparaloc : boolean;
  261. paraalign : shortint;
  262. begin
  263. result:=0;
  264. if paras.count=0 then
  265. exit;
  266. paraalign:=get_para_align(p.proccalloption);
  267. for i:=0 to paras.count-1 do
  268. begin
  269. hp:=tparavarsym(paras[i]);
  270. paradef:=hp.vardef;
  271. { syscall for AmigaOS can have already a paraloc set }
  272. if (vo_has_explicit_paraloc in hp.varoptions) then
  273. begin
  274. if not(vo_is_syscall_lib in hp.varoptions) then
  275. internalerror(200506051);
  276. continue;
  277. end;
  278. hp.paraloc[side].reset;
  279. { currently only support C-style array of const }
  280. if (p.proccalloption in cstylearrayofconst) and
  281. is_array_of_const(paradef) then
  282. begin
  283. paraloc:=hp.paraloc[side].add_location;
  284. { hack: the paraloc must be valid, but is not actually used }
  285. paraloc^.loc:=LOC_REGISTER;
  286. paraloc^.register:=NR_D0;
  287. paraloc^.size:=OS_ADDR;
  288. paraloc^.def:=voidpointertype;
  289. break;
  290. end;
  291. if push_addr_param(hp.varspez,paradef,p.proccalloption) then
  292. begin
  293. paradef:=cpointerdef.getreusable_no_free(paradef);
  294. paracgsize := OS_ADDR;
  295. paralen := tcgsize2size[OS_ADDR];
  296. end
  297. else
  298. begin
  299. if not is_special_array(paradef) then
  300. paralen:=paradef.size
  301. else
  302. paralen:=tcgsize2size[def_cgsize(paradef)];
  303. paracgsize:=def_cgsize(paradef);
  304. { for things like formaldef }
  305. if (paracgsize=OS_NO) and (paradef.typ<>recorddef) then
  306. begin
  307. paracgsize:=OS_ADDR;
  308. paralen := tcgsize2size[OS_ADDR];
  309. end;
  310. end;
  311. hp.paraloc[side].alignment:=paraalign;
  312. hp.paraloc[side].size:=paracgsize;
  313. hp.paraloc[side].intsize:=paralen;
  314. hp.paraloc[side].def:=paradef;
  315. if (paralen = 0) then
  316. if (paradef.typ = recorddef) then
  317. begin
  318. paraloc:=hp.paraloc[side].add_location;
  319. paraloc^.loc := LOC_VOID;
  320. end
  321. else
  322. internalerror(200506052);
  323. firstparaloc:=true;
  324. { can become < 0 for e.g. 3-byte records }
  325. while (paralen > 0) do
  326. begin
  327. paraloc:=hp.paraloc[side].add_location;
  328. paraloc^.def:=get_paraloc_def(paradef,paralen,firstparaloc);
  329. if (not (cs_fp_emulation in current_settings.moduleswitches)) and
  330. (paradef.typ=floatdef) then
  331. paraloc^.size:=int_float_cgsize(paralen)
  332. else
  333. paraloc^.size:=int_cgsize(paralen);
  334. { various m68k based C ABIs used in the Unix world use a register to
  335. return a struct by address. we will probably need some kind of a
  336. switch to support these various ABIs when generating cdecl calls (KB) }
  337. if ((vo_is_funcret in hp.varoptions) and
  338. (tprocdef(p).proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  339. (target_info.system in [system_m68k_linux]) and
  340. (tprocdef(p).returndef.typ = recorddef)) then
  341. begin
  342. paraloc^.loc:=LOC_REGISTER;
  343. paraloc^.register:=NR_M68K_STRUCT_RESULT_REG;
  344. paralen:=0;
  345. continue;
  346. end;
  347. paraloc^.loc:=LOC_REFERENCE;
  348. paraloc^.reference.offset:=cur_stack_offset;
  349. if (side = callerside) then
  350. paraloc^.reference.index:=NR_STACK_POINTER_REG
  351. else
  352. begin
  353. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  354. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  355. end;
  356. { M68K is a big-endian target }
  357. if (paralen<paraalign) then
  358. inc(paraloc^.reference.offset,paraalign-paralen);
  359. inc(cur_stack_offset,align(paralen,target_info.stackalign));
  360. paralen := 0;
  361. firstparaloc:=false;
  362. end;
  363. end;
  364. result:=cur_stack_offset;
  365. end;
  366. function tcpuparamanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  367. var cur_stack_offset: aword): longint;
  368. var
  369. hp : tparavarsym;
  370. paradef : tdef;
  371. paraloc : pcgparalocation;
  372. paracgsize : tcgsize;
  373. i : integer;
  374. l,
  375. paralen,
  376. parareg: longint;
  377. addrparareg: longint;
  378. floatparareg: longint;
  379. varalign : longint;
  380. paraalign : shortint;
  381. pass : byte;
  382. firstparaloc,
  383. pushaddr : boolean;
  384. rt: tregistertype;
  385. begin
  386. result:=0;
  387. if paras.count=0 then
  388. exit;
  389. parareg:=0;
  390. addrparareg:=0;
  391. floatparareg:=0;
  392. paraalign:=get_para_align(p.proccalloption);
  393. { clean up here so we can later detect properly if a parameter has been
  394. assigned or not
  395. }
  396. for i:=0 to paras.count-1 do
  397. tparavarsym(paras[i]).paraloc[side].reset;
  398. { Register parameters are assigned from left to right,
  399. stack parameters from right to left so assign first the
  400. register parameters in a first pass, in the second
  401. pass all unhandled parameters are done }
  402. for pass:=1 to 2 do
  403. begin
  404. if pass=1 then
  405. i:=0
  406. else
  407. i:=paras.count-1;
  408. while true do
  409. begin
  410. hp:=tparavarsym(paras[i]);
  411. paradef:=hp.vardef;
  412. if not(assigned(hp.paraloc[side].location)) then
  413. begin
  414. pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
  415. if pushaddr then
  416. begin
  417. paralen:=sizeof(aint);
  418. paracgsize:=OS_ADDR;
  419. paradef:=cpointerdef.getreusable_no_free(paradef);
  420. end
  421. else
  422. begin
  423. paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  424. paracgsize:=def_cgsize(hp.vardef);
  425. end;
  426. hp.paraloc[side].size:=paracgsize;
  427. hp.paraloc[side].intsize:=paralen;
  428. hp.paraloc[side].Alignment:=paraalign;
  429. hp.paraloc[side].def:=paradef;
  430. {
  431. In case of po_delphi_nested_cc, the parent frame pointer
  432. is also always passed on the stack.
  433. }
  434. rt:=chlcgobj.def2regtyp(paradef);
  435. if (rt=R_FPUREGISTER) and
  436. (floatparareg<=high(floatparasupregs)) and
  437. (not pushaddr) then
  438. begin
  439. if pass=1 then
  440. begin
  441. paraloc:=hp.paraloc[side].add_location;
  442. paraloc^.size:=paracgsize;
  443. paraloc^.def:=paradef;
  444. paraloc^.loc:=LOC_FPUREGISTER;
  445. paraloc^.register:=newreg(R_FPUREGISTER,floatparasupregs[floatparareg],R_SUBWHOLE);
  446. inc(floatparareg);
  447. end;
  448. end
  449. else
  450. if (((rt=R_INTREGISTER) and (parareg<=high(intparasupregs))) or
  451. ((rt=R_ADDRESSREGISTER) and (addrparareg<=high(addrparasupregs)))) and
  452. (paralen<=sizeof(aint)) and
  453. (not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
  454. pushaddr or
  455. is_dynamic_array(hp.vardef)) and
  456. (not(vo_is_parentfp in hp.varoptions) or
  457. not(po_delphi_nested_cc in p.procoptions)) then
  458. begin
  459. if pass=1 then
  460. begin
  461. paraloc:=hp.paraloc[side].add_location;
  462. paraloc^.size:=paracgsize;
  463. paraloc^.def:=paradef;
  464. paraloc^.loc:=LOC_REGISTER;
  465. if (rt=R_ADDRESSREGISTER) and (addrparareg<=high(addrparasupregs)) then
  466. begin
  467. paraloc^.register:=newreg(R_ADDRESSREGISTER,addrparasupregs[addrparareg],R_SUBWHOLE);
  468. inc(addrparareg);
  469. end
  470. else
  471. if (rt=R_INTREGISTER) and (parareg<=high(intparasupregs)) then
  472. begin
  473. paraloc^.register:=newreg(R_INTREGISTER,intparasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
  474. inc(parareg);
  475. end
  476. else
  477. internalerror(2016051801);
  478. end;
  479. end
  480. else
  481. if pass=2 then
  482. begin
  483. { Copy to stack? }
  484. if (use_fixed_stack) or
  485. (paracgsize=OS_NO) then
  486. begin
  487. paraloc:=hp.paraloc[side].add_location;
  488. paraloc^.loc:=LOC_REFERENCE;
  489. paraloc^.size:=paracgsize;
  490. paraloc^.def:=paradef;
  491. if side=callerside then
  492. paraloc^.reference.index:=NR_STACK_POINTER_REG
  493. else
  494. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  495. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  496. paraloc^.reference.offset:=cur_stack_offset;
  497. if (paralen<paraalign) then
  498. inc(paraloc^.reference.offset,paraalign-paralen);
  499. if side=calleeside then
  500. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  501. cur_stack_offset:=align(cur_stack_offset+paralen,varalign);
  502. end
  503. else
  504. begin
  505. if paralen=0 then
  506. internalerror(200501163);
  507. firstparaloc:=true;
  508. while (paralen>0) do
  509. begin
  510. paraloc:=hp.paraloc[side].add_location;
  511. paraloc^.loc:=LOC_REFERENCE;
  512. { Extended and double need a single location }
  513. if (paracgsize in [OS_F64,OS_F32]) then
  514. begin
  515. paraloc^.size:=paracgsize;
  516. paraloc^.def:=paradef;
  517. l:=paralen;
  518. end
  519. else
  520. begin
  521. { We can allocate at maximum 32 bits per location }
  522. if paralen>sizeof(aint) then
  523. begin
  524. l:=sizeof(aint);
  525. paraloc^.def:=uinttype;
  526. end
  527. else
  528. begin
  529. l:=paralen;
  530. paraloc^.def:=get_paraloc_def(paradef,l,firstparaloc);
  531. end;
  532. paraloc^.size:=int_cgsize(l);
  533. end;
  534. if side=callerside then
  535. paraloc^.reference.index:=NR_STACK_POINTER_REG
  536. else
  537. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  538. varalign:=used_align(size_2_align(l),paraalign,paraalign);
  539. paraloc^.reference.offset:=cur_stack_offset;
  540. { M68K is a big-endian target }
  541. if (paralen<paraalign) then
  542. inc(paraloc^.reference.offset,paraalign-paralen);
  543. if side=calleeside then
  544. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  545. cur_stack_offset:=align(cur_stack_offset+l,varalign);
  546. dec(paralen,l);
  547. firstparaloc:=false;
  548. end;
  549. end;
  550. end;
  551. end;
  552. case pass of
  553. 1:
  554. begin
  555. if i=paras.count-1 then
  556. break;
  557. inc(i);
  558. end;
  559. 2:
  560. begin
  561. if i=0 then
  562. break;
  563. dec(i);
  564. end;
  565. end;
  566. end;
  567. end;
  568. result:=cur_stack_offset;
  569. end;
  570. function tcpuparamanager.parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
  571. begin
  572. locreg:=std_regnum_search(lower(s));
  573. result:=(locreg <> NR_NO) and (locreg <> NR_SP);
  574. end;
  575. function tcpuparamanager.parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;
  576. begin
  577. case target_info.system of
  578. system_m68k_amiga:
  579. result:=parse_loc_string_to_register(p.exp_funcretloc, s);
  580. else
  581. internalerror(2005121801);
  582. end;
  583. end;
  584. procedure tcpuparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
  585. begin
  586. { Never a need for temps when value is pushed (calls inside parameters
  587. will simply allocate even more stack space for their parameters) }
  588. if not(use_fixed_stack) then
  589. can_use_final_stack_loc:=true;
  590. inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
  591. end;
  592. function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  593. var
  594. cur_stack_offset: aword;
  595. begin
  596. cur_stack_offset:=0;
  597. result:=create_stdcall_paraloc_info(p,callerside,p.paras,cur_stack_offset);
  598. if (p.proccalloption in cstylearrayofconst) then
  599. { just continue loading the parameters in the registers }
  600. result:=create_stdcall_paraloc_info(p,callerside,varargspara,cur_stack_offset)
  601. else
  602. internalerror(200410231);
  603. end;
  604. begin
  605. paramanager:=tcpuparamanager.create;
  606. end.