cpupara.pas 24 KB

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