ncgcal.pas 52 KB

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