ncgcal.pas 53 KB

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