cpupara.pas 27 KB

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