ncgcal.pas 52 KB

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