cpupara.pas 29 KB

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