ncgcal.pas 53 KB

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