cpupara.pas 27 KB

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