ncgcal.pas 51 KB

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