ncgcal.pas 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for call nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgcal;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cpubase,
  23. globtype,
  24. parabase,cgutils,
  25. symdef,node,ncal;
  26. type
  27. tcgcallparanode = class(tcallparanode)
  28. private
  29. tempcgpara : tcgpara;
  30. procedure push_addr_para;
  31. procedure push_value_para;
  32. public
  33. constructor create(expr,next : tnode);override;
  34. destructor destroy;override;
  35. procedure secondcallparan;override;
  36. end;
  37. tcgcallnode = class(tcallnode)
  38. private
  39. procedure release_para_temps;
  40. procedure normal_pass_2;
  41. {$ifdef PASS2INLINE}
  42. procedure inlined_pass_2;
  43. {$endif PASS2INLINE}
  44. procedure pushparas;
  45. procedure freeparas;
  46. protected
  47. framepointer_paraloc : tcgpara;
  48. refcountedtemp : treference;
  49. procedure handle_return_value;
  50. {# This routine is used to push the current frame pointer
  51. on the stack. This is used in nested routines where the
  52. value of the frame pointer is always pushed as an extra
  53. parameter.
  54. The default handling is the standard handling used on
  55. most stack based machines, where the frame pointer is
  56. the first invisible parameter.
  57. }
  58. procedure pop_parasize(pop_size:longint);virtual;
  59. procedure extra_interrupt_code;virtual;
  60. procedure extra_call_code;virtual;
  61. procedure extra_post_call_code;virtual;
  62. procedure do_syscall;virtual;abstract;
  63. public
  64. procedure pass_2;override;
  65. end;
  66. implementation
  67. uses
  68. systems,
  69. cutils,verbose,globals,
  70. symconst,symtable,defutil,paramgr,
  71. {$ifdef GDB}
  72. strings,
  73. gdb,
  74. {$endif GDB}
  75. cgbase,pass_2,
  76. aasmbase,aasmtai,
  77. nbas,nmem,nld,ncnv,nutils,
  78. {$ifdef x86}
  79. cga,cgx86,
  80. {$endif x86}
  81. ncgutil,
  82. cgobj,tgobj,
  83. procinfo;
  84. {*****************************************************************************
  85. TCGCALLPARANODE
  86. *****************************************************************************}
  87. constructor tcgcallparanode.create(expr,next : tnode);
  88. begin
  89. inherited create(expr,next);
  90. tempcgpara.init;
  91. end;
  92. destructor tcgcallparanode.destroy;
  93. begin
  94. tempcgpara.done;
  95. inherited destroy;
  96. end;
  97. procedure tcgcallparanode.push_addr_para;
  98. begin
  99. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  100. internalerror(200304235);
  101. cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempcgpara);
  102. end;
  103. procedure tcgcallparanode.push_value_para;
  104. {$ifdef i386}
  105. var
  106. cgsize : tcgsize;
  107. href : treference;
  108. size : longint;
  109. {$endif i386}
  110. begin
  111. { we've nothing to push when the size of the parameter is 0 }
  112. if left.resulttype.def.size=0 then
  113. exit;
  114. { Move flags and jump in register to make it less complex }
  115. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  116. location_force_reg(exprasmlist,left.location,def_cgsize(left.resulttype.def),false);
  117. { Handle Floating point types differently }
  118. if left.resulttype.def.deftype=floatdef then
  119. begin
  120. {$ifdef i386}
  121. if tempcgpara.location^.loc<>LOC_REFERENCE then
  122. internalerror(200309291);
  123. case left.location.loc of
  124. LOC_FPUREGISTER,
  125. LOC_CFPUREGISTER:
  126. begin
  127. size:=align(TCGSize2Size[left.location.size],tempcgpara.alignment);
  128. if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
  129. begin
  130. cg.g_stackpointer_alloc(exprasmlist,size);
  131. reference_reset_base(href,NR_STACK_POINTER_REG,0);
  132. end
  133. else
  134. reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
  135. cg.a_loadfpu_reg_ref(exprasmlist,left.location.size,left.location.register,href);
  136. end;
  137. LOC_MMREGISTER,
  138. LOC_CMMREGISTER:
  139. begin
  140. size:=align(tfloatdef(left.resulttype.def).size,tempcgpara.alignment);
  141. if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
  142. begin
  143. cg.g_stackpointer_alloc(exprasmlist,size);
  144. reference_reset_base(href,NR_STACK_POINTER_REG,0);
  145. end
  146. else
  147. reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
  148. cg.a_loadmm_reg_ref(exprasmlist,left.location.size,left.location.size,left.location.register,href,mms_movescalar);
  149. end;
  150. LOC_REFERENCE,
  151. LOC_CREFERENCE :
  152. begin
  153. size:=align(left.resulttype.def.size,tempcgpara.alignment);
  154. if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
  155. cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
  156. else
  157. begin
  158. reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
  159. cg.g_concatcopy(exprasmlist,left.location.reference,href,size);
  160. end;
  161. end;
  162. else
  163. internalerror(2002042430);
  164. end;
  165. {$else i386}
  166. case left.location.loc of
  167. LOC_MMREGISTER,
  168. LOC_CMMREGISTER:
  169. case tempcgpara.location^.loc of
  170. LOC_REFERENCE,
  171. LOC_CREFERENCE,
  172. LOC_MMREGISTER,
  173. LOC_CMMREGISTER:
  174. cg.a_parammm_reg(exprasmlist,left.location.size,left.location.register,tempcgpara,mms_movescalar);
  175. LOC_FPUREGISTER,
  176. LOC_CFPUREGISTER:
  177. begin
  178. location_force_fpureg(exprasmlist,left.location,false);
  179. cg.a_paramfpu_reg(exprasmlist,left.location.size,left.location.register,tempcgpara);
  180. end;
  181. else
  182. internalerror(2002042433);
  183. end;
  184. LOC_FPUREGISTER,
  185. LOC_CFPUREGISTER:
  186. case tempcgpara.location^.loc of
  187. LOC_MMREGISTER,
  188. LOC_CMMREGISTER:
  189. begin
  190. location_force_mmregscalar(exprasmlist,left.location,false);
  191. cg.a_parammm_reg(exprasmlist,left.location.size,left.location.register,tempcgpara,mms_movescalar);
  192. end;
  193. {$ifdef x86_64}
  194. { x86_64 pushes s64comp in normal register }
  195. LOC_REGISTER,
  196. LOC_CREGISTER :
  197. begin
  198. location_force_mem(exprasmlist,left.location);
  199. { force integer size }
  200. left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
  201. cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
  202. end;
  203. {$endif x86_64}
  204. {$ifdef sparc}
  205. { sparc pushes floats in normal registers }
  206. LOC_REGISTER,
  207. LOC_CREGISTER,
  208. {$endif sparc}
  209. LOC_REFERENCE,
  210. LOC_CREFERENCE,
  211. LOC_FPUREGISTER,
  212. LOC_CFPUREGISTER:
  213. cg.a_paramfpu_reg(exprasmlist,left.location.size,left.location.register,tempcgpara);
  214. else
  215. internalerror(2002042433);
  216. end;
  217. LOC_REFERENCE,
  218. LOC_CREFERENCE:
  219. case tempcgpara.location^.loc of
  220. LOC_MMREGISTER,
  221. LOC_CMMREGISTER:
  222. cg.a_parammm_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara,mms_movescalar);
  223. {$ifdef x86_64}
  224. { x86_64 pushes s64comp in normal register }
  225. LOC_REGISTER,
  226. LOC_CREGISTER :
  227. begin
  228. { force integer size }
  229. left.location.size:=int_cgsize(tcgsize2size[left.location.size]);
  230. cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
  231. end;
  232. {$endif x86_64}
  233. {$ifdef sparc}
  234. { sparc pushes floats in normal registers }
  235. LOC_REGISTER,
  236. LOC_CREGISTER,
  237. {$endif sparc}
  238. LOC_REFERENCE,
  239. LOC_CREFERENCE,
  240. LOC_FPUREGISTER,
  241. LOC_CFPUREGISTER:
  242. cg.a_paramfpu_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara);
  243. else
  244. internalerror(2002042431);
  245. end;
  246. else
  247. internalerror(2002042432);
  248. end;
  249. {$endif i386}
  250. end
  251. else
  252. begin
  253. case left.location.loc of
  254. LOC_CONSTANT,
  255. LOC_REGISTER,
  256. LOC_CREGISTER,
  257. LOC_REFERENCE,
  258. LOC_CREFERENCE :
  259. begin
  260. {$ifndef cpu64bit}
  261. { use cg64 only for int64, not for 8 byte records }
  262. if is_64bit(left.resulttype.def) then
  263. cg64.a_param64_loc(exprasmlist,left.location,tempcgpara)
  264. else
  265. {$endif cpu64bit}
  266. cg.a_param_loc(exprasmlist,left.location,tempcgpara);
  267. end;
  268. {$ifdef SUPPORT_MMX}
  269. LOC_MMXREGISTER,
  270. LOC_CMMXREGISTER:
  271. cg.a_parammm_reg(exprasmlist,left.location.register);
  272. {$endif SUPPORT_MMX}
  273. else
  274. internalerror(200204241);
  275. end;
  276. end;
  277. end;
  278. procedure tcgcallparanode.secondcallparan;
  279. var
  280. otlabel,
  281. oflabel : tasmlabel;
  282. begin
  283. if not(assigned(parasym)) then
  284. internalerror(200304242);
  285. { Skip nothingn nodes which are used after disabling
  286. a parameter }
  287. if (left.nodetype<>nothingn) then
  288. begin
  289. otlabel:=truelabel;
  290. oflabel:=falselabel;
  291. objectlibrary.getlabel(truelabel);
  292. objectlibrary.getlabel(falselabel);
  293. secondpass(left);
  294. {$ifdef PASS2INLINE}
  295. if assigned(aktcallnode.inlinecode) then
  296. paramanager.duplicateparaloc(exprasmlist,aktcallnode.procdefinition.proccalloption,parasym,tempcgpara)
  297. else
  298. {$endif PASS2INLINE}
  299. paramanager.createtempparaloc(exprasmlist,aktcallnode.procdefinition.proccalloption,parasym,tempcgpara);
  300. { handle varargs first, because parasym is not valid }
  301. if (cpf_varargs_para in callparaflags) then
  302. begin
  303. if paramanager.push_addr_param(vs_value,left.resulttype.def,
  304. aktcallnode.procdefinition.proccalloption) then
  305. push_addr_para
  306. else
  307. push_value_para;
  308. end
  309. { hidden parameters }
  310. else if (vo_is_hidden_para in parasym.varoptions) then
  311. begin
  312. { don't push a node that already generated a pointer type
  313. by address for implicit hidden parameters }
  314. if (vo_is_funcret in parasym.varoptions) or
  315. (not(left.resulttype.def.deftype in [pointerdef,classrefdef]) and
  316. paramanager.push_addr_param(parasym.varspez,parasym.vartype.def,
  317. aktcallnode.procdefinition.proccalloption)) then
  318. push_addr_para
  319. else
  320. push_value_para;
  321. end
  322. { formal def }
  323. else if (parasym.vartype.def.deftype=formaldef) then
  324. begin
  325. { allow passing of a constant to a const formaldef }
  326. if (parasym.varspez=vs_const) and
  327. (left.location.loc=LOC_CONSTANT) then
  328. location_force_mem(exprasmlist,left.location);
  329. push_addr_para;
  330. end
  331. { Normal parameter }
  332. else
  333. begin
  334. { don't push a node that already generated a pointer type
  335. by address for implicit hidden parameters }
  336. if (not(
  337. (vo_is_hidden_para in parasym.varoptions) and
  338. (left.resulttype.def.deftype in [pointerdef,classrefdef])
  339. ) and
  340. paramanager.push_addr_param(parasym.varspez,parasym.vartype.def,
  341. aktcallnode.procdefinition.proccalloption)) then
  342. begin
  343. { Passing a var parameter to a var parameter, we can
  344. just push the address transparently }
  345. if (left.nodetype=loadn) and
  346. (tloadnode(left).is_addr_param_load) then
  347. begin
  348. if (left.location.reference.index<>NR_NO) or
  349. (left.location.reference.offset<>0) then
  350. internalerror(200410107);
  351. cg.a_param_reg(exprasmlist,OS_ADDR,left.location.reference.base,tempcgpara)
  352. end
  353. else
  354. begin
  355. { Check for passing a constant to var,out parameter }
  356. if (parasym.varspez in [vs_var,vs_out]) and
  357. (left.location.loc<>LOC_REFERENCE) then
  358. begin
  359. { passing self to a var parameter is allowed in
  360. TP and delphi }
  361. if not((left.location.loc=LOC_CREFERENCE) and
  362. is_self_node(left)) then
  363. internalerror(200106041);
  364. end;
  365. { Force to be in memory }
  366. if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  367. location_force_mem(exprasmlist,left.location);
  368. push_addr_para;
  369. end;
  370. end
  371. else
  372. push_value_para;
  373. end;
  374. truelabel:=otlabel;
  375. falselabel:=oflabel;
  376. { update return location in callnode when this is the function
  377. result }
  378. if assigned(parasym) and
  379. (vo_is_funcret in parasym.varoptions) then
  380. location_copy(aktcallnode.location,left.location);
  381. end;
  382. { next parameter }
  383. if assigned(right) then
  384. tcallparanode(right).secondcallparan;
  385. end;
  386. {*****************************************************************************
  387. TCGCALLNODE
  388. *****************************************************************************}
  389. procedure tcgcallnode.extra_interrupt_code;
  390. begin
  391. end;
  392. procedure tcgcallnode.extra_call_code;
  393. begin
  394. end;
  395. procedure tcgcallnode.extra_post_call_code;
  396. begin
  397. end;
  398. procedure tcgcallnode.pop_parasize(pop_size:longint);
  399. begin
  400. end;
  401. procedure tcgcallnode.handle_return_value;
  402. var
  403. cgsize : tcgsize;
  404. retloc : tlocation;
  405. hregister : tregister;
  406. tempnode : tnode;
  407. begin
  408. cgsize:=procdefinition.funcretloc[callerside].size;
  409. { structured results are easy to handle....
  410. needed also when result_no_used !! }
  411. if (procdefinition.proctypeoption<>potype_constructor) and
  412. paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  413. begin
  414. { Location should be setup by the funcret para }
  415. if location.loc<>LOC_REFERENCE then
  416. internalerror(200304241);
  417. end
  418. else
  419. { ansi/widestrings must be registered, so we can dispose them }
  420. if resulttype.def.needs_inittable then
  421. begin
  422. if procdefinition.funcretloc[callerside].loc<>LOC_REGISTER then
  423. internalerror(200409261);
  424. { the FUNCTION_RESULT_REG is already allocated }
  425. if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
  426. cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
  427. if not assigned(funcretnode) then
  428. begin
  429. { reg_ref could generate two instrcutions and allocate a register so we've to
  430. save the result first before releasing it }
  431. hregister:=cg.getaddressregister(exprasmlist);
  432. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,procdefinition.funcretloc[callerside].register,hregister);
  433. location_reset(location,LOC_REFERENCE,OS_ADDR);
  434. location.reference:=refcountedtemp;
  435. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  436. end
  437. else
  438. begin
  439. hregister := cg.getaddressregister(exprasmlist);
  440. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,procdefinition.funcretloc[callerside].register,hregister);
  441. { in case of a regular funcretnode with ret_in_param, the }
  442. { original funcretnode isn't touched -> make sure it's }
  443. { the same here (not sure if it's necessary) }
  444. tempnode := funcretnode.getcopy;
  445. tempnode.pass_2;
  446. location := tempnode.location;
  447. tempnode.free;
  448. cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference);
  449. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  450. end;
  451. end
  452. else
  453. { normal (ordinal,float,pointer) result value }
  454. begin
  455. { we have only to handle the result if it is used }
  456. if (cnf_return_value_used in callnodeflags) then
  457. begin
  458. location.loc:=procdefinition.funcretloc[callerside].loc;
  459. case procdefinition.funcretloc[callerside].loc of
  460. LOC_FPUREGISTER:
  461. begin
  462. location_reset(location,LOC_FPUREGISTER,cgsize);
  463. location.register:=procdefinition.funcretloc[callerside].register;
  464. {$ifdef x86}
  465. tcgx86(cg).inc_fpu_stack;
  466. {$else x86}
  467. if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
  468. cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
  469. hregister:=cg.getfpuregister(exprasmlist,location.size);
  470. cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
  471. location.register:=hregister;
  472. {$endif x86}
  473. end;
  474. LOC_REGISTER:
  475. begin
  476. if cgsize<>OS_NO then
  477. begin
  478. location_reset(location,LOC_REGISTER,cgsize);
  479. {$ifndef cpu64bit}
  480. if cgsize in [OS_64,OS_S64] then
  481. begin
  482. retloc:=procdefinition.funcretloc[callerside];
  483. if retloc.loc<>LOC_REGISTER then
  484. internalerror(200409141);
  485. { the function result registers are already allocated }
  486. if getsupreg(retloc.register64.reglo)<first_int_imreg then
  487. cg.ungetcpuregister(exprasmlist,retloc.register64.reglo);
  488. location.register64.reglo:=cg.getintregister(exprasmlist,OS_32);
  489. cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
  490. if getsupreg(retloc.register64.reghi)<first_int_imreg then
  491. cg.ungetcpuregister(exprasmlist,retloc.register64.reghi);
  492. location.register64.reghi:=cg.getintregister(exprasmlist,OS_32);
  493. cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
  494. end
  495. else
  496. {$endif cpu64bit}
  497. begin
  498. { change register size after the unget because the
  499. getregister was done for the full register
  500. def_cgsize(resulttype.def) is used here because
  501. it could be a constructor call }
  502. if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
  503. cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
  504. location.register:=cg.getintregister(exprasmlist,def_cgsize(resulttype.def));
  505. cg.a_load_reg_reg(exprasmlist,cgsize,def_cgsize(resulttype.def),procdefinition.funcretloc[callerside].register,location.register);
  506. end;
  507. end
  508. else
  509. begin
  510. if resulttype.def.size>0 then
  511. internalerror(200305131);
  512. end;
  513. end;
  514. LOC_MMREGISTER:
  515. begin
  516. location_reset(location,LOC_MMREGISTER,cgsize);
  517. if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
  518. cg.ungetcpuregister(exprasmlist,procdefinition.funcretloc[callerside].register);
  519. location.register:=cg.getmmregister(exprasmlist,cgsize);
  520. cg.a_loadmm_reg_reg(exprasmlist,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
  521. end;
  522. else
  523. internalerror(200405023);
  524. end;
  525. end
  526. else
  527. begin
  528. {$ifdef x86}
  529. { release FPU stack }
  530. if procdefinition.funcretloc[callerside].loc=LOC_FPUREGISTER then
  531. emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
  532. {$endif x86}
  533. if cgsize<>OS_NO then
  534. location_free(exprasmlist,procdefinition.funcretloc[callerside]);
  535. location_reset(location,LOC_VOID,OS_NO);
  536. end;
  537. end;
  538. { When the result is not used we need to finalize the result and
  539. can release the temp }
  540. if not(cnf_return_value_used in callnodeflags) then
  541. begin
  542. if location.loc=LOC_REFERENCE then
  543. begin
  544. if resulttype.def.needs_inittable then
  545. cg.g_finalize(exprasmlist,resulttype.def,location.reference);
  546. tg.ungetiftemp(exprasmlist,location.reference)
  547. end;
  548. end;
  549. end;
  550. procedure tcgcallnode.release_para_temps;
  551. var
  552. hp : tnode;
  553. ppn : tcallparanode;
  554. begin
  555. { Release temps from parameters }
  556. ppn:=tcallparanode(left);
  557. while assigned(ppn) do
  558. begin
  559. if assigned(ppn.left) then
  560. begin
  561. { don't release the funcret temp }
  562. if not(assigned(ppn.parasym)) or
  563. not(vo_is_funcret in ppn.parasym.varoptions) then
  564. location_freetemp(exprasmlist,ppn.left.location);
  565. { process also all nodes of an array of const }
  566. hp:=ppn.left;
  567. while (hp.nodetype=typeconvn) do
  568. hp:=ttypeconvnode(hp).left;
  569. if (hp.nodetype=arrayconstructorn) and
  570. assigned(tarrayconstructornode(hp).left) then
  571. begin
  572. while assigned(hp) do
  573. begin
  574. location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
  575. hp:=tarrayconstructornode(hp).right;
  576. end;
  577. end;
  578. end;
  579. ppn:=tcallparanode(ppn.right);
  580. end;
  581. end;
  582. procedure tcgcallnode.pushparas;
  583. var
  584. ppn : tcgcallparanode;
  585. callerparaloc,
  586. tmpparaloc : pcgparalocation;
  587. sizeleft: aint;
  588. {$ifdef cputargethasfixedstack}
  589. htempref,
  590. href : treference;
  591. {$endif cputargethasfixedstack}
  592. begin
  593. { copy all resources to the allocated registers }
  594. ppn:=tcgcallparanode(left);
  595. while assigned(ppn) do
  596. begin
  597. if (ppn.left.nodetype<>nothingn) then
  598. begin
  599. { better check for the real location of the parameter here, when stack passed parameters
  600. are saved temporary in registers, checking for the tmpparaloc.loc is wrong
  601. }
  602. {$ifdef PASS2INLINE}
  603. if not assigned(inlinecode) then
  604. {$endif PASS2INLINE}
  605. paramanager.freeparaloc(exprasmlist,ppn.tempcgpara);
  606. tmpparaloc:=ppn.tempcgpara.location;
  607. sizeleft:=ppn.tempcgpara.intsize;
  608. callerparaloc:=ppn.parasym.paraloc[callerside].location;
  609. while assigned(callerparaloc) do
  610. begin
  611. { Every paraloc must have a matching tmpparaloc }
  612. if not assigned(tmpparaloc) then
  613. internalerror(200408224);
  614. if callerparaloc^.size<>tmpparaloc^.size then
  615. internalerror(200408225);
  616. case callerparaloc^.loc of
  617. LOC_REGISTER:
  618. begin
  619. if tmpparaloc^.loc<>LOC_REGISTER then
  620. internalerror(200408221);
  621. if getsupreg(callerparaloc^.register)<first_int_imreg then
  622. cg.getcpuregister(exprasmlist,callerparaloc^.register);
  623. cg.a_load_reg_reg(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,
  624. tmpparaloc^.register,callerparaloc^.register);
  625. end;
  626. LOC_FPUREGISTER:
  627. begin
  628. if tmpparaloc^.loc<>LOC_FPUREGISTER then
  629. internalerror(200408222);
  630. if getsupreg(callerparaloc^.register)<first_fpu_imreg then
  631. cg.getcpuregister(exprasmlist,callerparaloc^.register);
  632. cg.a_loadfpu_reg_reg(exprasmlist,ppn.tempcgpara.size,tmpparaloc^.register,callerparaloc^.register);
  633. end;
  634. LOC_MMREGISTER:
  635. begin
  636. if tmpparaloc^.loc<>LOC_MMREGISTER then
  637. internalerror(200408223);
  638. if getsupreg(callerparaloc^.register)<first_mm_imreg then
  639. cg.getcpuregister(exprasmlist,callerparaloc^.register);
  640. cg.a_loadmm_reg_reg(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,
  641. tmpparaloc^.register,callerparaloc^.register,mms_movescalar);
  642. end;
  643. LOC_REFERENCE:
  644. begin
  645. {$ifdef PASS2INLINE}
  646. if not assigned(inlinecode) then
  647. {$endif PASS2INLINE}
  648. begin
  649. {$ifdef cputargethasfixedstack}
  650. { Can't have a data copied to the stack, every location
  651. must contain a valid size field }
  652. if (ppn.tempcgpara.size=OS_NO) and
  653. ((tmpparaloc^.loc<>LOC_REFERENCE) or
  654. assigned(tmpparaloc^.next)) then
  655. internalerror(200501281);
  656. reference_reset_base(href,callerparaloc^.reference.index,callerparaloc^.reference.offset);
  657. { copy parameters in case they were moved to a temp. location because we've a fixed stack }
  658. case tmpparaloc^.loc of
  659. LOC_REFERENCE:
  660. begin
  661. reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset);
  662. { use concatcopy, because it can also be a float which fails when
  663. load_ref_ref is used }
  664. if (ppn.tempcgpara.size <> OS_NO) then
  665. cg.g_concatcopy(exprasmlist,htempref,href,tcgsize2size[tmpparaloc^.size])
  666. else
  667. cg.g_concatcopy(exprasmlist,htempref,href,sizeleft)
  668. end;
  669. LOC_REGISTER:
  670. cg.a_load_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
  671. LOC_FPUREGISTER:
  672. cg.a_loadfpu_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.register,href);
  673. LOC_MMREGISTER:
  674. cg.a_loadmm_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href,mms_movescalar);
  675. else
  676. internalerror(200402081);
  677. end;
  678. {$endif cputargethasfixedstack}
  679. end;
  680. end;
  681. end;
  682. dec(sizeleft,tcgsize2size[tmpparaloc^.size]);
  683. callerparaloc:=callerparaloc^.next;
  684. tmpparaloc:=tmpparaloc^.next;
  685. end;
  686. end;
  687. ppn:=tcgcallparanode(ppn.right);
  688. end;
  689. end;
  690. procedure tcgcallnode.freeparas;
  691. var
  692. ppn : tcgcallparanode;
  693. begin
  694. { free the resources allocated for the parameters }
  695. ppn:=tcgcallparanode(left);
  696. while assigned(ppn) do
  697. begin
  698. if (ppn.left.nodetype<>nothingn) then
  699. begin
  700. if
  701. {$ifdef PASS2INLINE}
  702. not assigned(inlinecode) or
  703. {$endif PASS2INLINE}
  704. (ppn.parasym.paraloc[callerside].location^.loc <> LOC_REFERENCE) then
  705. paramanager.freeparaloc(exprasmlist,ppn.parasym.paraloc[callerside]);
  706. end;
  707. ppn:=tcgcallparanode(ppn.right);
  708. end;
  709. end;
  710. procedure tcgcallnode.normal_pass_2;
  711. var
  712. regs_to_save_int,
  713. regs_to_save_fpu,
  714. regs_to_save_mm : Tcpuregisterset;
  715. href : treference;
  716. pop_size : longint;
  717. pvreg,
  718. vmtreg : tregister;
  719. oldaktcallnode : tcallnode;
  720. begin
  721. if not assigned(procdefinition) or
  722. not procdefinition.has_paraloc_info then
  723. internalerror(200305264);
  724. if resulttype.def.needs_inittable and
  725. not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) and
  726. not assigned(funcretnode) then
  727. begin
  728. tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
  729. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
  730. end;
  731. regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
  732. regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
  733. regs_to_save_mm:=paramanager.get_volatile_registers_mm(procdefinition.proccalloption);
  734. { Include Function result registers }
  735. if (not is_void(resulttype.def)) then
  736. begin
  737. case procdefinition.funcretloc[callerside].loc of
  738. LOC_REGISTER,
  739. LOC_CREGISTER:
  740. include(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
  741. LOC_FPUREGISTER,
  742. LOC_CFPUREGISTER:
  743. include(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
  744. LOC_MMREGISTER,
  745. LOC_CMMREGISTER:
  746. include(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
  747. LOC_REFERENCE,
  748. LOC_VOID:
  749. ;
  750. else
  751. internalerror(2004110213);
  752. end;
  753. end;
  754. { Process parameters, register parameters will be loaded
  755. in imaginary registers. The actual load to the correct
  756. register is done just before the call }
  757. oldaktcallnode:=aktcallnode;
  758. aktcallnode:=self;
  759. if assigned(left) then
  760. tcallparanode(left).secondcallparan;
  761. aktcallnode:=oldaktcallnode;
  762. { procedure variable or normal function call ? }
  763. if (right=nil) then
  764. begin
  765. { When methodpointer is typen we don't need (and can't) load
  766. a pointer. We can directly call the correct procdef (PFV) }
  767. if (po_virtualmethod in procdefinition.procoptions) and
  768. assigned(methodpointer) and
  769. (methodpointer.nodetype<>typen) then
  770. begin
  771. secondpass(methodpointer);
  772. location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
  773. { virtual methods require an index }
  774. if tprocdef(procdefinition).extnumber=$ffff then
  775. internalerror(200304021);
  776. { VMT should already be loaded in a register }
  777. if methodpointer.location.register=NR_NO then
  778. internalerror(200304022);
  779. { test validity of VMT }
  780. if not(is_interface(tprocdef(procdefinition)._class)) and
  781. not(is_cppclass(tprocdef(procdefinition)._class)) then
  782. cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
  783. vmtreg:=methodpointer.location.register;
  784. pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
  785. reference_reset_base(href,vmtreg,
  786. tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
  787. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,pvreg);
  788. { Load parameters that are in temporary registers in the
  789. correct parameter register }
  790. if assigned(left) then
  791. begin
  792. pushparas;
  793. { free the resources allocated for the parameters }
  794. freeparas;
  795. end;
  796. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  797. if cg.uses_registers(R_FPUREGISTER) then
  798. cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  799. if cg.uses_registers(R_MMREGISTER) then
  800. cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  801. { call method }
  802. extra_call_code;
  803. cg.a_call_reg(exprasmlist,pvreg);
  804. extra_post_call_code;
  805. end
  806. else
  807. begin
  808. { Load parameters that are in temporary registers in the
  809. correct parameter register }
  810. if assigned(left) then
  811. begin
  812. pushparas;
  813. { free the resources allocated for the parameters }
  814. freeparas;
  815. end;
  816. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  817. if cg.uses_registers(R_FPUREGISTER) then
  818. cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  819. if cg.uses_registers(R_MMREGISTER) then
  820. cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  821. if procdefinition.proccalloption=pocall_syscall then
  822. do_syscall
  823. else
  824. begin
  825. { Calling interrupt from the same code requires some
  826. extra code }
  827. if (po_interrupt in procdefinition.procoptions) then
  828. extra_interrupt_code;
  829. extra_call_code;
  830. cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
  831. extra_post_call_code;
  832. end;
  833. end;
  834. end
  835. else
  836. { now procedure variable case }
  837. begin
  838. secondpass(right);
  839. pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
  840. { Only load OS_ADDR from the reference }
  841. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  842. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
  843. else
  844. cg.a_load_loc_reg(exprasmlist,OS_ADDR,right.location,pvreg);
  845. location_freetemp(exprasmlist,right.location);
  846. { Load parameters that are in temporary registers in the
  847. correct parameter register }
  848. if assigned(left) then
  849. begin
  850. pushparas;
  851. { free the resources allocated for the parameters }
  852. freeparas;
  853. end;
  854. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  855. if cg.uses_registers(R_FPUREGISTER) then
  856. cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  857. if cg.uses_registers(R_MMREGISTER) then
  858. cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  859. { Calling interrupt from the same code requires some
  860. extra code }
  861. if (po_interrupt in procdefinition.procoptions) then
  862. extra_interrupt_code;
  863. extra_call_code;
  864. cg.a_call_reg(exprasmlist,pvreg);
  865. extra_post_call_code;
  866. end;
  867. { Need to remove the parameters from the stack? }
  868. if (procdefinition.proccalloption in clearstack_pocalls) then
  869. begin
  870. pop_size:=pushedparasize;
  871. { for Cdecl functions we don't need to pop the funcret when it
  872. was pushed by para }
  873. if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
  874. dec(pop_size,sizeof(aint));
  875. { Remove parameters/alignment from the stack }
  876. pop_parasize(pop_size);
  877. end;
  878. { Release registers, but not the registers that contain the
  879. function result }
  880. if (not is_void(resulttype.def)) then
  881. begin
  882. case procdefinition.funcretloc[callerside].loc of
  883. LOC_REGISTER,
  884. LOC_CREGISTER:
  885. exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
  886. LOC_FPUREGISTER,
  887. LOC_CFPUREGISTER:
  888. exclude(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
  889. LOC_MMREGISTER,
  890. LOC_CMMREGISTER:
  891. exclude(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
  892. LOC_REFERENCE,
  893. LOC_VOID:
  894. ;
  895. else
  896. internalerror(2004110214);
  897. end;
  898. end;
  899. if cg.uses_registers(R_MMREGISTER) then
  900. cg.dealloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  901. if cg.uses_registers(R_FPUREGISTER) then
  902. cg.dealloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  903. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  904. { handle function results }
  905. if (not is_void(resulttype.def)) then
  906. handle_return_value
  907. else
  908. location_reset(location,LOC_VOID,OS_NO);
  909. { perhaps i/o check ? }
  910. if (cs_check_io in aktlocalswitches) and
  911. (po_iocheck in procdefinition.procoptions) and
  912. not(po_iocheck in current_procinfo.procdef.procoptions) and
  913. { no IO check for methods and procedure variables }
  914. (right=nil) and
  915. not(po_virtualmethod in procdefinition.procoptions) then
  916. begin
  917. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  918. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  919. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  920. end;
  921. { release temps of paras }
  922. release_para_temps;
  923. end;
  924. {$ifdef PASS2INLINE}
  925. procedure tcgcallnode.inlined_pass_2;
  926. var
  927. oldaktcallnode : tcallnode;
  928. oldprocinfo : tprocinfo;
  929. oldinlining_procedure : boolean;
  930. inlineentrycode,inlineexitcode : TAAsmoutput;
  931. {$ifdef GDB}
  932. startlabel,endlabel : tasmlabel;
  933. pp : pchar;
  934. mangled_length : longint;
  935. {$endif GDB}
  936. begin
  937. if not(assigned(procdefinition) and (procdefinition.deftype=procdef)) then
  938. internalerror(200305262);
  939. oldinlining_procedure:=inlining_procedure;
  940. oldprocinfo:=current_procinfo;
  941. { we're inlining a procedure }
  942. inlining_procedure:=true;
  943. { Add inling start }
  944. {$ifdef GDB}
  945. exprasmlist.concat(Tai_force_line.Create);
  946. {$endif GDB}
  947. exprasmList.concat(Tai_Marker.Create(InlineStart));
  948. {$ifdef extdebug}
  949. exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc '+tprocdef(procdefinition).procsym.name)));
  950. {$endif extdebug}
  951. { calculate registers to pass the parameters }
  952. paramanager.create_inline_paraloc_info(procdefinition);
  953. { Allocate parameters and locals }
  954. gen_alloc_inline_parast(exprasmlist,tprocdef(procdefinition));
  955. gen_alloc_inline_funcret(exprasmlist,tprocdef(procdefinition));
  956. gen_alloc_symtable(exprasmlist,tprocdef(procdefinition).localst);
  957. { if we allocate the temp. location for ansi- or widestrings }
  958. { already here, we avoid later a push/pop }
  959. if resulttype.def.needs_inittable and
  960. not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  961. begin
  962. tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
  963. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
  964. end;
  965. { Push parameters, still use the old current_procinfo. This
  966. is required that have the correct information available like
  967. _class and nested procedure }
  968. oldaktcallnode:=aktcallnode;
  969. aktcallnode:=self;
  970. if assigned(left) then
  971. begin
  972. tcallparanode(left).secondcallparan;
  973. pushparas;
  974. end;
  975. aktcallnode:=oldaktcallnode;
  976. { create temp procinfo that will be used for the inlinecode tree }
  977. current_procinfo:=cprocinfo.create(nil);
  978. current_procinfo.procdef:=tprocdef(procdefinition);
  979. current_procinfo.flags:=oldprocinfo.flags;
  980. current_procinfo.aktlocaldata.destroy;
  981. current_procinfo.aktlocaldata:=oldprocinfo.aktlocaldata;
  982. { when the oldprocinfo is also being inlined reuse the
  983. inlining_procinfo }
  984. if assigned(oldprocinfo.inlining_procinfo) then
  985. current_procinfo.inlining_procinfo:=oldprocinfo.inlining_procinfo
  986. else
  987. current_procinfo.inlining_procinfo:=oldprocinfo;
  988. { takes care of local data initialization }
  989. inlineentrycode:=TAAsmoutput.Create;
  990. inlineexitcode:=TAAsmoutput.Create;
  991. {$ifdef GDB}
  992. if (cs_debuginfo in aktmoduleswitches) and
  993. not(cs_gdb_valgrind in aktglobalswitches) then
  994. begin
  995. objectlibrary.getaddrlabel(startlabel);
  996. objectlibrary.getaddrlabel(endlabel);
  997. cg.a_label(exprasmlist,startlabel);
  998. { Here we must include the para and local symtable info }
  999. procdefinition.concatstabto(withdebuglist);
  1000. mangled_length:=length(current_procinfo.inlining_procinfo.procdef.mangledname);
  1001. getmem(pp,mangled_length+50);
  1002. strpcopy(pp,'192,0,0,'+startlabel.name);
  1003. if (target_info.use_function_relative_addresses) then
  1004. begin
  1005. strpcopy(strend(pp),'-');
  1006. strpcopy(strend(pp),current_procinfo.inlining_procinfo.procdef.mangledname);
  1007. end;
  1008. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1009. end;
  1010. {$endif GDB}
  1011. gen_load_para_value(inlineentrycode);
  1012. { now that we've loaded the para's, free them }
  1013. if assigned(left) then
  1014. freeparas;
  1015. gen_initialize_code(inlineentrycode);
  1016. if po_assembler in current_procinfo.procdef.procoptions then
  1017. inlineentrycode.insert(Tai_marker.Create(asmblockstart));
  1018. exprasmList.concatlist(inlineentrycode);
  1019. { process the inline code }
  1020. secondpass(inlinecode);
  1021. cg.a_label(exprasmlist,current_procinfo.aktexitlabel);
  1022. gen_finalize_code(inlineexitcode);
  1023. gen_load_return_value(inlineexitcode);
  1024. if po_assembler in current_procinfo.procdef.procoptions then
  1025. inlineexitcode.concat(Tai_marker.Create(asmblockend));
  1026. exprasmlist.concatlist(inlineexitcode);
  1027. inlineentrycode.free;
  1028. inlineexitcode.free;
  1029. {$ifdef extdebug}
  1030. exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
  1031. {$endif extdebug}
  1032. exprasmList.concat(Tai_Marker.Create(InlineEnd));
  1033. { handle function results }
  1034. if (not is_void(resulttype.def)) then
  1035. handle_return_value
  1036. else
  1037. location_reset(location,LOC_VOID,OS_NO);
  1038. { perhaps i/o check ? }
  1039. if (cs_check_io in aktlocalswitches) and
  1040. (po_iocheck in procdefinition.procoptions) and
  1041. not(po_iocheck in current_procinfo.procdef.procoptions) and
  1042. { no IO check for methods and procedure variables }
  1043. (right=nil) and
  1044. not(po_virtualmethod in procdefinition.procoptions) then
  1045. begin
  1046. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1047. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  1048. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1049. end;
  1050. { release temps of paras }
  1051. release_para_temps;
  1052. { if return value is not used }
  1053. if (not is_void(resulttype.def)) and
  1054. (not(cnf_return_value_used in callnodeflags)) then
  1055. begin
  1056. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  1057. begin
  1058. { data which must be finalized ? }
  1059. if (resulttype.def.needs_inittable) then
  1060. cg.g_finalize(exprasmlist,resulttype.def,location.reference);
  1061. { release unused temp }
  1062. tg.ungetiftemp(exprasmlist,location.reference)
  1063. end
  1064. else if location.loc=LOC_FPUREGISTER then
  1065. begin
  1066. {$ifdef x86}
  1067. { release FPU stack }
  1068. emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
  1069. {$endif x86}
  1070. end;
  1071. end;
  1072. { Release parameters and locals }
  1073. gen_free_symtable(exprasmlist,tparasymtable(current_procinfo.procdef.parast));
  1074. gen_free_symtable(exprasmlist,tlocalsymtable(current_procinfo.procdef.localst));
  1075. {$ifdef GDB}
  1076. if (cs_debuginfo in aktmoduleswitches) and
  1077. not(cs_gdb_valgrind in aktglobalswitches) then
  1078. begin
  1079. cg.a_label(exprasmlist,endlabel);
  1080. strpcopy(pp,'224,0,0,'+endlabel.name);
  1081. if (target_info.use_function_relative_addresses) then
  1082. begin
  1083. strpcopy(strend(pp),'-');
  1084. strpcopy(strend(pp),current_procinfo.inlining_procinfo.procdef.mangledname);
  1085. end;
  1086. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1087. freemem(pp,mangled_length+50);
  1088. end;
  1089. {$endif GDB}
  1090. { restore }
  1091. current_procinfo.aktlocaldata:=nil;
  1092. current_procinfo.destroy;
  1093. current_procinfo:=oldprocinfo;
  1094. inlining_procedure:=oldinlining_procedure;
  1095. end;
  1096. {$endif PASS2INLINE}
  1097. procedure tcgcallnode.pass_2;
  1098. begin
  1099. if assigned(methodpointerinit) then
  1100. secondpass(methodpointerinit);
  1101. {$ifdef PASS2INLINE}
  1102. if assigned(inlinecode) then
  1103. inlined_pass_2
  1104. else
  1105. {$endif PASS2INLINE}
  1106. normal_pass_2;
  1107. if assigned(methodpointerdone) then
  1108. secondpass(methodpointerdone);
  1109. end;
  1110. begin
  1111. ccallparanode:=tcgcallparanode;
  1112. ccallnode:=tcgcallnode;
  1113. end.
  1114. {
  1115. $Log$
  1116. Revision 1.201 2005-02-15 21:39:48 peter
  1117. * remove is_single_reference
  1118. * revert loading of ref-to-ref para valu
  1119. Revision 1.200 2005/02/14 17:13:06 peter
  1120. * truncate log
  1121. Revision 1.199 2005/01/30 21:51:57 jonas
  1122. * fixed darwin cycle
  1123. Revision 1.198 2005/01/29 11:36:52 peter
  1124. * update x86_64 with new cpupara
  1125. Revision 1.197 2005/01/20 17:47:01 peter
  1126. * remove copy_value_on_stack and a_param_copy_ref
  1127. Revision 1.196 2005/01/18 22:19:20 peter
  1128. * multiple location support for i386 a_param_ref
  1129. * remove a_param_copy_ref for i386
  1130. Revision 1.195 2005/01/12 10:02:22 florian
  1131. * removed ie20050111
  1132. Revision 1.194 2005/01/10 21:50:05 jonas
  1133. + support for passing records in registers under darwin
  1134. * tcgpara now also has an intsize field, which contains the size in
  1135. bytes of the whole parameter
  1136. Revision 1.193 2005/01/07 16:22:54 florian
  1137. + implemented abi compliant handling of strucutured functions results on sparc platform
  1138. Revision 1.192 2005/01/04 16:36:51 peter
  1139. * release temps in array constructor
  1140. Revision 1.191 2005/01/02 16:58:48 peter
  1141. * Don't release methodpointer. It is maybe still needed when we need to
  1142. convert the calln to loadn
  1143. }