cpupara.pas 27 KB

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