cpupara.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generates the argument location information for i8086
  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. aasmtai,aasmdata,cpubase,cgbase,cgutils,
  23. symconst,symtype,symsym,symdef,
  24. parabase,paramgr;
  25. type
  26. tcpuparamanager = class(tparamanager)
  27. function param_use_paraloc(const cgpara:tcgpara):boolean;override;
  28. function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
  29. function asm_result_var(def:tdef;pd:tabstractprocdef):boolean;override;
  30. function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
  31. function get_para_align(calloption : tproccalloption):byte;override;
  32. function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
  33. function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
  34. function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
  35. { Returns the location for the nr-st 16 Bit int parameter
  36. if every parameter before is an 16 Bit int parameter as well
  37. and if the calling conventions for the helper routines of the
  38. rtl are used.
  39. TODO: This allocates 32-bit ints on other CPU architectures. Since
  40. we're small/tiny model only, for now we can get away with allocating
  41. always 16-bit int parameters, but in the future, when we implement
  42. other memory models, this mechanism has to be extended somehow to
  43. support 32-bit addresses on a 16-bit CPU.
  44. }
  45. procedure getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
  46. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  47. function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
  48. procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
  49. function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;override;
  50. private
  51. procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
  52. procedure create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parareg,parasize:longint);
  53. end;
  54. implementation
  55. uses
  56. cutils,
  57. systems,verbose,
  58. symtable,symcpu,
  59. defutil;
  60. const
  61. parasupregs : array[0..2] of tsuperregister = (RS_AX,RS_DX,RS_CX);
  62. {****************************************************************************
  63. tcpuparamanager
  64. ****************************************************************************}
  65. function tcpuparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
  66. var
  67. paraloc : pcgparalocation;
  68. begin
  69. if not assigned(cgpara.location) then
  70. internalerror(200410102);
  71. result:=true;
  72. { All locations are LOC_REFERENCE }
  73. paraloc:=cgpara.location;
  74. while assigned(paraloc) do
  75. begin
  76. if (paraloc^.loc<>LOC_REFERENCE) then
  77. begin
  78. result:=false;
  79. exit;
  80. end;
  81. paraloc:=paraloc^.next;
  82. end;
  83. end;
  84. function tcpuparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
  85. var
  86. size: longint;
  87. begin
  88. if handle_common_ret_in_param(def,pd,result) then
  89. exit;
  90. if (def.size > 8) and (def.typ <> floatdef) then
  91. begin
  92. result:=true;
  93. exit;
  94. end;
  95. result:=inherited ret_in_param(def,pd);
  96. end;
  97. function tcpuparamanager.asm_result_var(def:tdef;pd:tabstractprocdef):boolean;
  98. begin
  99. if not(po_assembler in pd.procoptions) then
  100. internalerror(2018021501);
  101. result:=ret_in_param(def,pd);
  102. end;
  103. function tcpuparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
  104. begin
  105. result:=false;
  106. { var,out,constref always require address }
  107. if varspez in [vs_var,vs_out,vs_constref] then
  108. begin
  109. result:=true;
  110. exit;
  111. end;
  112. { Only vs_const, vs_value here }
  113. case def.typ of
  114. variantdef :
  115. begin
  116. { variants are small enough to be passed by value except if
  117. required by the windows api
  118. variants are somethings very delphi/windows specific so do it like
  119. windows/delphi (FK)
  120. }
  121. if ((target_info.system=system_i386_win32) and
  122. (calloption in [pocall_stdcall,pocall_safecall]) and
  123. (varspez=vs_const)) or
  124. (calloption=pocall_register) then
  125. result:=true
  126. else
  127. result:=false;
  128. end;
  129. formaldef :
  130. result:=true;
  131. recorddef :
  132. begin
  133. { Delphi stdcall passes records on the stack for call by value }
  134. if (target_info.system=system_i386_win32) and
  135. (calloption=pocall_stdcall) and
  136. (varspez=vs_value) then
  137. result:=false
  138. else
  139. result:=
  140. (not(calloption in (cdecl_pocalls)) and
  141. (def.size>sizeof(aint))) or
  142. (((calloption = pocall_mwpascal) or (target_info.system=system_i386_wince)) and
  143. (varspez=vs_const));
  144. end;
  145. arraydef :
  146. begin
  147. { array of const values are pushed on the stack as
  148. well as dyn. arrays }
  149. if (calloption in cdecl_pocalls) then
  150. result:=not(is_array_of_const(def) or
  151. is_dynamic_array(def))
  152. else
  153. begin
  154. result:=(
  155. (tarraydef(def).highrange>=tarraydef(def).lowrange) and
  156. (def.size>sizeof(aint))
  157. ) or
  158. is_open_array(def) or
  159. is_array_of_const(def) or
  160. is_array_constructor(def);
  161. end;
  162. end;
  163. objectdef :
  164. result:=is_object(def);
  165. stringdef :
  166. result:= (tstringdef(def).stringtype in [st_shortstring,st_longstring]);
  167. procvardef :
  168. result:=not(calloption in cdecl_pocalls) and not tprocvardef(def).is_addressonly;
  169. setdef :
  170. result:=not(calloption in cdecl_pocalls) and (not is_smallset(def));
  171. end;
  172. end;
  173. function tcpuparamanager.get_para_align(calloption : tproccalloption):byte;
  174. begin
  175. result:=std_param_align;
  176. end;
  177. function tcpuparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
  178. begin
  179. case calloption of
  180. pocall_internproc :
  181. result:=[];
  182. pocall_register,
  183. pocall_safecall,
  184. pocall_stdcall,
  185. pocall_cdecl,
  186. pocall_cppdecl,
  187. pocall_mwpascal,
  188. pocall_far16,
  189. pocall_pascal,
  190. pocall_oldfpccall :
  191. result:=[RS_AX,RS_DX,RS_CX,RS_SI,RS_DI,RS_BX];
  192. else
  193. internalerror(200309071);
  194. end;
  195. end;
  196. function tcpuparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
  197. begin
  198. result:=[0..first_fpu_imreg-1];
  199. end;
  200. function tcpuparamanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
  201. begin
  202. result:=[0..first_mm_imreg-1];
  203. end;
  204. procedure tcpuparamanager.getintparaloc(list: TAsmList; pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
  205. var
  206. paraloc : pcgparalocation;
  207. psym: tparavarsym;
  208. pdef : tdef;
  209. begin
  210. psym:=tparavarsym(pd.paras[nr-1]);
  211. pdef:=psym.vardef;
  212. if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
  213. pdef:=cpointerdef.getreusable_no_free(pdef);
  214. cgpara.reset;
  215. cgpara.size:=def_cgsize(pdef);
  216. cgpara.intsize:=tcgsize2size[cgpara.size];
  217. cgpara.alignment:=get_para_align(pd.proccalloption);
  218. cgpara.def:=pdef;
  219. paraloc:=cgpara.add_location;
  220. with paraloc^ do
  221. begin
  222. size:=def_cgsize(pdef);
  223. def:=pdef;
  224. if pd.proccalloption=pocall_register then
  225. begin
  226. if (nr<=length(parasupregs)) then
  227. begin
  228. if nr=0 then
  229. internalerror(200309271);
  230. loc:=LOC_REGISTER;
  231. register:=newreg(R_INTREGISTER,parasupregs[nr-1],R_SUBWHOLE);
  232. end
  233. else
  234. begin
  235. loc:=LOC_REFERENCE;
  236. reference.index:=NR_STACK_POINTER_REG;
  237. { the previous parameters didn't take up room in memory }
  238. reference.offset:=sizeof(aint)*(nr-length(parasupregs)-1)
  239. end;
  240. end
  241. else
  242. begin
  243. loc:=LOC_REFERENCE;
  244. reference.index:=NR_STACK_POINTER_REG;
  245. reference.offset:=sizeof(aint)*nr;
  246. end;
  247. end;
  248. end;
  249. function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;
  250. var
  251. retcgsize : tcgsize;
  252. paraloc : pcgparalocation;
  253. sym: tfieldvarsym;
  254. usedef: tdef;
  255. handled: boolean;
  256. begin
  257. if not assigned(forcetempdef) then
  258. usedef:=p.returndef
  259. else
  260. usedef:=forcetempdef;
  261. handled:=set_common_funcretloc_info(p,usedef,retcgsize,result);
  262. { normally forcetempdef is passed straight through to
  263. set_common_funcretloc_info and that one will correctly determine whether
  264. the location is a temporary one, but that doesn't work here because we
  265. sometimes have to change the type }
  266. result.temporary:=assigned(forcetempdef);
  267. if handled then
  268. exit;
  269. { Return in FPU register? }
  270. if result.def.typ=floatdef then
  271. begin
  272. paraloc:=result.add_location;
  273. paraloc^.loc:=LOC_FPUREGISTER;
  274. paraloc^.register:=NR_FPU_RESULT_REG;
  275. paraloc^.size:=retcgsize;
  276. paraloc^.def:=result.def;
  277. end
  278. else
  279. { Return in register }
  280. begin
  281. paraloc:=result.add_location;
  282. paraloc^.loc:=LOC_REGISTER;
  283. if retcgsize in [OS_64,OS_S64] then
  284. begin
  285. { bits 0..15 }
  286. if side=callerside then
  287. paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
  288. else
  289. paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
  290. paraloc^.size:=OS_16;
  291. paraloc^.def:=u16inttype;
  292. { bits 16..31 }
  293. paraloc:=result.add_location;
  294. paraloc^.loc:=LOC_REGISTER;
  295. if side=callerside then
  296. paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
  297. else
  298. paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
  299. paraloc^.size:=OS_16;
  300. paraloc^.def:=u16inttype;
  301. { bits 32..47 }
  302. paraloc:=result.add_location;
  303. paraloc^.loc:=LOC_REGISTER;
  304. if side=callerside then
  305. paraloc^.register:=NR_FUNCTION_RESULT64_HIGHER_REG
  306. else
  307. paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
  308. paraloc^.size:=OS_16;
  309. paraloc^.def:=u16inttype;
  310. { bits 48..63 }
  311. paraloc:=result.add_location;
  312. paraloc^.loc:=LOC_REGISTER;
  313. if side=callerside then
  314. paraloc^.register:=NR_FUNCTION_RESULT64_HIGHEST_REG
  315. else
  316. paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
  317. paraloc^.size:=OS_16;
  318. paraloc^.def:=u16inttype;
  319. end
  320. else if retcgsize in [OS_32,OS_S32] then
  321. begin
  322. { low 16bits }
  323. if side=callerside then
  324. paraloc^.register:=NR_FUNCTION_RESULT32_LOW_REG
  325. else
  326. paraloc^.register:=NR_FUNCTION_RETURN32_LOW_REG;
  327. paraloc^.size:=OS_16;
  328. paraloc^.def:=u16inttype;
  329. { high 16bits }
  330. paraloc:=result.add_location;
  331. paraloc^.loc:=LOC_REGISTER;
  332. if side=callerside then
  333. paraloc^.register:=NR_FUNCTION_RESULT32_HIGH_REG
  334. else
  335. paraloc^.register:=NR_FUNCTION_RETURN32_HIGH_REG;
  336. paraloc^.size:=OS_16;
  337. paraloc^.def:=u16inttype;
  338. end
  339. else
  340. begin
  341. paraloc^.size:=retcgsize;
  342. paraloc^.def:=result.def;
  343. if side=callerside then
  344. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
  345. else
  346. paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
  347. end;
  348. end;
  349. end;
  350. procedure tcpuparamanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
  351. var
  352. i : integer;
  353. hp : tparavarsym;
  354. paradef : tdef;
  355. paraloc : pcgparalocation;
  356. l,
  357. paralen,
  358. varalign : longint;
  359. paraalign : shortint;
  360. paracgsize : tcgsize;
  361. firstparaloc,
  362. pushaddr : boolean;
  363. pushleftright: boolean;
  364. begin
  365. paraalign:=get_para_align(p.proccalloption);
  366. { interrupt routines need parameter fixup }
  367. if po_interrupt in p.procoptions then
  368. if is_proc_far(p) then
  369. dec(parasize,6)
  370. else
  371. dec(parasize,4);
  372. { Offset is calculated like:
  373. sub esp,12
  374. mov [esp+8],para3
  375. mov [esp+4],para2
  376. mov [esp],para1
  377. call function
  378. That means for pushes the para with the
  379. highest offset (see para3) needs to be pushed first
  380. }
  381. pushleftright:=(p.proccalloption in pushleftright_pocalls) or (po_interrupt in p.procoptions);
  382. if pushleftright then
  383. i:=paras.count-1
  384. else
  385. i:=0;
  386. while (pushleftright and (i>=0)) or
  387. (not(pushleftright) and (i<=paras.count-1)) do
  388. begin
  389. hp:=tparavarsym(paras[i]);
  390. paradef:=hp.vardef;
  391. pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
  392. if pushaddr then
  393. begin
  394. paralen:=voidpointertype.size;
  395. paracgsize:=int_cgsize(voidpointertype.size);
  396. paradef:=cpointerdef.getreusable_no_free(paradef);
  397. end
  398. else
  399. begin
  400. paralen:=push_size(hp.varspez,paradef,p.proccalloption);
  401. paracgsize:=def_cgsize(paradef);
  402. end;
  403. hp.paraloc[side].reset;
  404. hp.paraloc[side].size:=paracgsize;
  405. hp.paraloc[side].intsize:=paralen;
  406. hp.paraloc[side].def:=paradef;
  407. hp.paraloc[side].Alignment:=paraalign;
  408. { Copy to stack? }
  409. if (paracgsize=OS_NO) or
  410. (use_fixed_stack) then
  411. begin
  412. paraloc:=hp.paraloc[side].add_location;
  413. paraloc^.loc:=LOC_REFERENCE;
  414. paraloc^.size:=paracgsize;
  415. paraloc^.def:=paradef;
  416. if side=callerside then
  417. paraloc^.reference.index:=NR_STACK_POINTER_REG
  418. else
  419. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  420. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  421. paraloc^.reference.offset:=parasize;
  422. if side=calleeside then
  423. begin
  424. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  425. if is_proc_far(p) then
  426. inc(paraloc^.reference.offset,2);
  427. end;
  428. parasize:=align(parasize+paralen,varalign);
  429. end
  430. else
  431. begin
  432. if paralen=0 then
  433. internalerror(200501163);
  434. firstparaloc:=true;
  435. while (paralen>0) do
  436. begin
  437. paraloc:=hp.paraloc[side].add_location;
  438. paraloc^.loc:=LOC_REFERENCE;
  439. { single and double need a single location }
  440. if (paracgsize in [OS_F64,OS_F32]) then
  441. begin
  442. paraloc^.size:=paracgsize;
  443. paraloc^.def:=paradef;
  444. l:=paralen;
  445. end
  446. else
  447. begin
  448. { We can allocate at maximum 16 bits per location }
  449. if paralen>=sizeof(aint) then
  450. begin
  451. l:=sizeof(aint);
  452. paraloc^.def:=uinttype;
  453. end
  454. else
  455. begin
  456. l:=paralen;
  457. paraloc^.def:=get_paraloc_def(paradef,l,firstparaloc);
  458. end;
  459. paraloc^.size:=int_cgsize(l);
  460. end;
  461. if (side=callerside) or
  462. (po_nostackframe in p.procoptions) then
  463. paraloc^.reference.index:=NR_STACK_POINTER_REG
  464. else
  465. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  466. varalign:=used_align(size_2_align(l),paraalign,paraalign);
  467. paraloc^.reference.offset:=parasize;
  468. if side=calleeside then
  469. begin
  470. if not(po_nostackframe in p.procoptions) then
  471. inc(paraloc^.reference.offset,target_info.first_parm_offset)
  472. else
  473. { return addres }
  474. inc(paraloc^.reference.offset,2);
  475. if is_proc_far(p) then
  476. inc(paraloc^.reference.offset,2);
  477. end;
  478. parasize:=align(parasize+l,varalign);
  479. dec(paralen,l);
  480. firstparaloc:=false;
  481. end;
  482. end;
  483. if pushleftright then
  484. dec(i)
  485. else
  486. inc(i);
  487. end;
  488. end;
  489. procedure tcpuparamanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
  490. var parareg,parasize:longint);
  491. var
  492. hp : tparavarsym;
  493. paradef : tdef;
  494. paraloc : pcgparalocation;
  495. paracgsize : tcgsize;
  496. i : integer;
  497. l,
  498. paralen,
  499. varalign : longint;
  500. pushaddr : boolean;
  501. paraalign : shortint;
  502. pass : byte;
  503. firstparaloc : boolean;
  504. begin
  505. if paras.count=0 then
  506. exit;
  507. paraalign:=get_para_align(p.proccalloption);
  508. { clean up here so we can later detect properly if a parameter has been
  509. assigned or not
  510. }
  511. for i:=0 to paras.count-1 do
  512. tparavarsym(paras[i]).paraloc[side].reset;
  513. { Register parameters are assigned from left to right,
  514. stack parameters from right to left so assign first the
  515. register parameters in a first pass, in the second
  516. pass all unhandled parameters are done }
  517. for pass:=1 to 2 do
  518. begin
  519. if pass=1 then
  520. i:=0
  521. else
  522. i:=paras.count-1;
  523. while true do
  524. begin
  525. hp:=tparavarsym(paras[i]);
  526. paradef:=hp.vardef;
  527. if not(assigned(hp.paraloc[side].location)) then
  528. begin
  529. pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
  530. if pushaddr then
  531. begin
  532. paralen:=voidpointertype.size;
  533. paracgsize:=int_cgsize(voidpointertype.size);
  534. paradef:=cpointerdef.getreusable_no_free(paradef);
  535. end
  536. else
  537. begin
  538. paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
  539. paracgsize:=def_cgsize(hp.vardef);
  540. end;
  541. hp.paraloc[side].size:=paracgsize;
  542. hp.paraloc[side].intsize:=paralen;
  543. hp.paraloc[side].Alignment:=paraalign;
  544. hp.paraloc[side].def:=paradef;
  545. {
  546. EAX
  547. EDX
  548. ECX
  549. Stack
  550. Stack
  551. 64bit values,floats,arrays and records are always
  552. on the stack.
  553. In case of po_delphi_nested_cc, the parent frame pointer
  554. is also always passed on the stack.
  555. }
  556. if (parareg<=high(parasupregs)) and
  557. (paralen<=sizeof(aint)) and
  558. (not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
  559. pushaddr or
  560. is_dynamic_array(hp.vardef)) and
  561. (not(vo_is_parentfp in hp.varoptions) or
  562. not(po_delphi_nested_cc in p.procoptions)) then
  563. begin
  564. if pass=1 then
  565. begin
  566. paraloc:=hp.paraloc[side].add_location;
  567. paraloc^.size:=paracgsize;
  568. paraloc^.def:=paradef;
  569. paraloc^.loc:=LOC_REGISTER;
  570. paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
  571. inc(parareg);
  572. end;
  573. end
  574. else
  575. if pass=2 then
  576. begin
  577. { Copy to stack? }
  578. if (use_fixed_stack) or
  579. (paracgsize=OS_NO) then
  580. begin
  581. paraloc:=hp.paraloc[side].add_location;
  582. paraloc^.loc:=LOC_REFERENCE;
  583. paraloc^.size:=paracgsize;
  584. paraloc^.def:=paradef;
  585. if side=callerside then
  586. paraloc^.reference.index:=NR_STACK_POINTER_REG
  587. else
  588. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  589. varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
  590. paraloc^.reference.offset:=parasize;
  591. if side=calleeside then
  592. begin
  593. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  594. if is_proc_far(p) then
  595. inc(paraloc^.reference.offset,2);
  596. end;
  597. parasize:=align(parasize+paralen,varalign);
  598. end
  599. else
  600. begin
  601. if paralen=0 then
  602. internalerror(200501163);
  603. firstparaloc:=true;
  604. while (paralen>0) do
  605. begin
  606. paraloc:=hp.paraloc[side].add_location;
  607. paraloc^.loc:=LOC_REFERENCE;
  608. { Extended and double need a single location }
  609. if (paracgsize in [OS_F64,OS_F32]) then
  610. begin
  611. paraloc^.size:=paracgsize;
  612. paraloc^.def:=paradef;
  613. l:=paralen;
  614. end
  615. else
  616. begin
  617. { We can allocate at maximum 16 bits per location }
  618. if paralen>=sizeof(aint) then
  619. begin
  620. l:=sizeof(aint);
  621. paraloc^.def:=uinttype;
  622. end
  623. else
  624. begin
  625. l:=paralen;
  626. paraloc^.def:=get_paraloc_def(paradef,l,firstparaloc);
  627. end;
  628. paraloc^.size:=int_cgsize(l);
  629. end;
  630. if side=callerside then
  631. paraloc^.reference.index:=NR_STACK_POINTER_REG
  632. else
  633. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  634. varalign:=used_align(size_2_align(l),paraalign,paraalign);
  635. paraloc^.reference.offset:=parasize;
  636. if side=calleeside then
  637. begin
  638. inc(paraloc^.reference.offset,target_info.first_parm_offset);
  639. if is_proc_far(p) then
  640. inc(paraloc^.reference.offset,2);
  641. end;
  642. parasize:=align(parasize+l,varalign);
  643. dec(paralen,l);
  644. firstparaloc:=false;
  645. end;
  646. end;
  647. end;
  648. end;
  649. case pass of
  650. 1:
  651. begin
  652. if i=paras.count-1 then
  653. break;
  654. inc(i);
  655. end;
  656. 2:
  657. begin
  658. if i=0 then
  659. break;
  660. dec(i);
  661. end;
  662. end;
  663. end;
  664. end;
  665. end;
  666. function tcpuparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  667. var
  668. parasize,
  669. parareg : longint;
  670. begin
  671. parasize:=0;
  672. parareg:=0;
  673. case p.proccalloption of
  674. pocall_register :
  675. create_register_paraloc_info(p,side,p.paras,parareg,parasize);
  676. pocall_internproc :
  677. begin
  678. { Use default calling }
  679. {$warnings off}
  680. if (pocall_default=pocall_register) then
  681. create_register_paraloc_info(p,side,p.paras,parareg,parasize)
  682. else
  683. create_stdcall_paraloc_info(p,side,p.paras,parasize);
  684. {$warnings on}
  685. end;
  686. else
  687. create_stdcall_paraloc_info(p,side,p.paras,parasize);
  688. end;
  689. create_funcretloc_info(p,side);
  690. result:=parasize;
  691. end;
  692. function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
  693. var
  694. parasize : longint;
  695. begin
  696. parasize:=0;
  697. { calculate the registers for the normal parameters }
  698. create_stdcall_paraloc_info(p,callerside,p.paras,parasize);
  699. { append the varargs }
  700. create_stdcall_paraloc_info(p,callerside,varargspara,parasize);
  701. result:=parasize;
  702. end;
  703. procedure tcpuparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
  704. begin
  705. { Never a need for temps when value is pushed (calls inside parameters
  706. will simply allocate even more stack space for their parameters) }
  707. if not(use_fixed_stack) then
  708. can_use_final_stack_loc:=true;
  709. inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
  710. end;
  711. begin
  712. paramanager:=tcpuparamanager.create;
  713. end.