ncgcal.pas 54 KB

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