ncgcal.pas 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368
  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. { Can't have a data copied to the stack, every location
  651. must contain a valid size field }
  652. if (ppn.tempcgpara.size=OS_NO) and
  653. not(ppn.tempcgpara.is_single_reference(tmpparaloc)) then
  654. internalerror(200501281);
  655. reference_reset_base(href,callerparaloc^.reference.index,callerparaloc^.reference.offset);
  656. { copy parameters in case they were moved to a temp. location because we've a fixed stack }
  657. case tmpparaloc^.loc of
  658. LOC_REFERENCE:
  659. begin
  660. reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset);
  661. { use concatcopy, because it can also be a float which fails when
  662. load_ref_ref is used }
  663. if (ppn.tempcgpara.size <> OS_NO) then
  664. cg.g_concatcopy(exprasmlist,htempref,href,tcgsize2size[tmpparaloc^.size])
  665. else
  666. cg.g_concatcopy(exprasmlist,htempref,href,sizeleft)
  667. end;
  668. LOC_REGISTER:
  669. cg.a_load_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
  670. LOC_FPUREGISTER:
  671. cg.a_loadfpu_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.register,href);
  672. LOC_MMREGISTER:
  673. cg.a_loadmm_reg_ref(exprasmlist,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href,mms_movescalar);
  674. else
  675. internalerror(200402081);
  676. end;
  677. {$endif cputargethasfixedstack}
  678. end;
  679. end;
  680. end;
  681. dec(sizeleft,tcgsize2size[tmpparaloc^.size]);
  682. callerparaloc:=callerparaloc^.next;
  683. tmpparaloc:=tmpparaloc^.next;
  684. end;
  685. end;
  686. ppn:=tcgcallparanode(ppn.right);
  687. end;
  688. end;
  689. procedure tcgcallnode.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. if (ppn.left.nodetype<>nothingn) then
  698. begin
  699. if
  700. {$ifdef PASS2INLINE}
  701. not assigned(inlinecode) or
  702. {$endif PASS2INLINE}
  703. (ppn.parasym.paraloc[callerside].location^.loc <> LOC_REFERENCE) then
  704. paramanager.freeparaloc(exprasmlist,ppn.parasym.paraloc[callerside]);
  705. end;
  706. ppn:=tcgcallparanode(ppn.right);
  707. end;
  708. end;
  709. procedure tcgcallnode.normal_pass_2;
  710. var
  711. regs_to_save_int,
  712. regs_to_save_fpu,
  713. regs_to_save_mm : Tcpuregisterset;
  714. href : treference;
  715. pop_size : longint;
  716. pvreg,
  717. vmtreg : tregister;
  718. oldaktcallnode : tcallnode;
  719. begin
  720. if not assigned(procdefinition) or
  721. not procdefinition.has_paraloc_info then
  722. internalerror(200305264);
  723. if resulttype.def.needs_inittable and
  724. not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) and
  725. not assigned(funcretnode) then
  726. begin
  727. tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
  728. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
  729. end;
  730. regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
  731. regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
  732. regs_to_save_mm:=paramanager.get_volatile_registers_mm(procdefinition.proccalloption);
  733. { Include Function result registers }
  734. if (not is_void(resulttype.def)) then
  735. begin
  736. case procdefinition.funcretloc[callerside].loc of
  737. LOC_REGISTER,
  738. LOC_CREGISTER:
  739. include(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
  740. LOC_FPUREGISTER,
  741. LOC_CFPUREGISTER:
  742. include(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
  743. LOC_MMREGISTER,
  744. LOC_CMMREGISTER:
  745. include(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
  746. LOC_REFERENCE,
  747. LOC_VOID:
  748. ;
  749. else
  750. internalerror(2004110213);
  751. end;
  752. end;
  753. { Process parameters, register parameters will be loaded
  754. in imaginary registers. The actual load to the correct
  755. register is done just before the call }
  756. oldaktcallnode:=aktcallnode;
  757. aktcallnode:=self;
  758. if assigned(left) then
  759. tcallparanode(left).secondcallparan;
  760. aktcallnode:=oldaktcallnode;
  761. { procedure variable or normal function call ? }
  762. if (right=nil) then
  763. begin
  764. { When methodpointer is typen we don't need (and can't) load
  765. a pointer. We can directly call the correct procdef (PFV) }
  766. if (po_virtualmethod in procdefinition.procoptions) and
  767. assigned(methodpointer) and
  768. (methodpointer.nodetype<>typen) then
  769. begin
  770. secondpass(methodpointer);
  771. location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
  772. { virtual methods require an index }
  773. if tprocdef(procdefinition).extnumber=$ffff then
  774. internalerror(200304021);
  775. { VMT should already be loaded in a register }
  776. if methodpointer.location.register=NR_NO then
  777. internalerror(200304022);
  778. { test validity of VMT }
  779. if not(is_interface(tprocdef(procdefinition)._class)) and
  780. not(is_cppclass(tprocdef(procdefinition)._class)) then
  781. cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
  782. vmtreg:=methodpointer.location.register;
  783. pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
  784. reference_reset_base(href,vmtreg,
  785. tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
  786. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,pvreg);
  787. { Load parameters that are in temporary registers in the
  788. correct parameter register }
  789. if assigned(left) then
  790. begin
  791. pushparas;
  792. { free the resources allocated for the parameters }
  793. freeparas;
  794. end;
  795. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  796. if cg.uses_registers(R_FPUREGISTER) then
  797. cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  798. if cg.uses_registers(R_MMREGISTER) then
  799. cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  800. { call method }
  801. extra_call_code;
  802. cg.a_call_reg(exprasmlist,pvreg);
  803. extra_post_call_code;
  804. end
  805. else
  806. begin
  807. { Load parameters that are in temporary registers in the
  808. correct parameter register }
  809. if assigned(left) then
  810. begin
  811. pushparas;
  812. { free the resources allocated for the parameters }
  813. freeparas;
  814. end;
  815. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  816. if cg.uses_registers(R_FPUREGISTER) then
  817. cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  818. if cg.uses_registers(R_MMREGISTER) then
  819. cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  820. if procdefinition.proccalloption=pocall_syscall then
  821. do_syscall
  822. else
  823. begin
  824. { Calling interrupt from the same code requires some
  825. extra code }
  826. if (po_interrupt in procdefinition.procoptions) then
  827. extra_interrupt_code;
  828. extra_call_code;
  829. cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
  830. extra_post_call_code;
  831. end;
  832. end;
  833. end
  834. else
  835. { now procedure variable case }
  836. begin
  837. secondpass(right);
  838. pvreg:=cg.getintregister(exprasmlist,OS_ADDR);
  839. { Only load OS_ADDR from the reference }
  840. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  841. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
  842. else
  843. cg.a_load_loc_reg(exprasmlist,OS_ADDR,right.location,pvreg);
  844. location_freetemp(exprasmlist,right.location);
  845. { Load parameters that are in temporary registers in the
  846. correct parameter register }
  847. if assigned(left) then
  848. begin
  849. pushparas;
  850. { free the resources allocated for the parameters }
  851. freeparas;
  852. end;
  853. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  854. if cg.uses_registers(R_FPUREGISTER) then
  855. cg.alloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  856. if cg.uses_registers(R_MMREGISTER) then
  857. cg.alloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  858. { Calling interrupt from the same code requires some
  859. extra code }
  860. if (po_interrupt in procdefinition.procoptions) then
  861. extra_interrupt_code;
  862. extra_call_code;
  863. cg.a_call_reg(exprasmlist,pvreg);
  864. extra_post_call_code;
  865. end;
  866. { Need to remove the parameters from the stack? }
  867. if (procdefinition.proccalloption in clearstack_pocalls) then
  868. begin
  869. pop_size:=pushedparasize;
  870. { for Cdecl functions we don't need to pop the funcret when it
  871. was pushed by para }
  872. if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
  873. dec(pop_size,sizeof(aint));
  874. { Remove parameters/alignment from the stack }
  875. pop_parasize(pop_size);
  876. end;
  877. { Release registers, but not the registers that contain the
  878. function result }
  879. if (not is_void(resulttype.def)) then
  880. begin
  881. case procdefinition.funcretloc[callerside].loc of
  882. LOC_REGISTER,
  883. LOC_CREGISTER:
  884. exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
  885. LOC_FPUREGISTER,
  886. LOC_CFPUREGISTER:
  887. exclude(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
  888. LOC_MMREGISTER,
  889. LOC_CMMREGISTER:
  890. exclude(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
  891. LOC_REFERENCE,
  892. LOC_VOID:
  893. ;
  894. else
  895. internalerror(2004110214);
  896. end;
  897. end;
  898. if cg.uses_registers(R_MMREGISTER) then
  899. cg.dealloccpuregisters(exprasmlist,R_MMREGISTER,regs_to_save_mm);
  900. if cg.uses_registers(R_FPUREGISTER) then
  901. cg.dealloccpuregisters(exprasmlist,R_FPUREGISTER,regs_to_save_fpu);
  902. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,regs_to_save_int);
  903. { handle function results }
  904. if (not is_void(resulttype.def)) then
  905. handle_return_value
  906. else
  907. location_reset(location,LOC_VOID,OS_NO);
  908. { perhaps i/o check ? }
  909. if (cs_check_io in aktlocalswitches) and
  910. (po_iocheck in procdefinition.procoptions) and
  911. not(po_iocheck in current_procinfo.procdef.procoptions) and
  912. { no IO check for methods and procedure variables }
  913. (right=nil) and
  914. not(po_virtualmethod in procdefinition.procoptions) then
  915. begin
  916. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  917. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  918. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  919. end;
  920. { release temps of paras }
  921. release_para_temps;
  922. end;
  923. {$ifdef PASS2INLINE}
  924. procedure tcgcallnode.inlined_pass_2;
  925. var
  926. oldaktcallnode : tcallnode;
  927. oldprocinfo : tprocinfo;
  928. oldinlining_procedure : boolean;
  929. inlineentrycode,inlineexitcode : TAAsmoutput;
  930. {$ifdef GDB}
  931. startlabel,endlabel : tasmlabel;
  932. pp : pchar;
  933. mangled_length : longint;
  934. {$endif GDB}
  935. begin
  936. if not(assigned(procdefinition) and (procdefinition.deftype=procdef)) then
  937. internalerror(200305262);
  938. oldinlining_procedure:=inlining_procedure;
  939. oldprocinfo:=current_procinfo;
  940. { we're inlining a procedure }
  941. inlining_procedure:=true;
  942. { Add inling start }
  943. {$ifdef GDB}
  944. exprasmlist.concat(Tai_force_line.Create);
  945. {$endif GDB}
  946. exprasmList.concat(Tai_Marker.Create(InlineStart));
  947. {$ifdef extdebug}
  948. exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc '+tprocdef(procdefinition).procsym.name)));
  949. {$endif extdebug}
  950. { calculate registers to pass the parameters }
  951. paramanager.create_inline_paraloc_info(procdefinition);
  952. { Allocate parameters and locals }
  953. gen_alloc_inline_parast(exprasmlist,tprocdef(procdefinition));
  954. gen_alloc_inline_funcret(exprasmlist,tprocdef(procdefinition));
  955. gen_alloc_symtable(exprasmlist,tprocdef(procdefinition).localst);
  956. { if we allocate the temp. location for ansi- or widestrings }
  957. { already here, we avoid later a push/pop }
  958. if resulttype.def.needs_inittable and
  959. not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
  960. begin
  961. tg.gettemptyped(exprasmlist,resulttype.def,tt_normal,refcountedtemp);
  962. cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp);
  963. end;
  964. { Push parameters, still use the old current_procinfo. This
  965. is required that have the correct information available like
  966. _class and nested procedure }
  967. oldaktcallnode:=aktcallnode;
  968. aktcallnode:=self;
  969. if assigned(left) then
  970. begin
  971. tcallparanode(left).secondcallparan;
  972. pushparas;
  973. end;
  974. aktcallnode:=oldaktcallnode;
  975. { create temp procinfo that will be used for the inlinecode tree }
  976. current_procinfo:=cprocinfo.create(nil);
  977. current_procinfo.procdef:=tprocdef(procdefinition);
  978. current_procinfo.flags:=oldprocinfo.flags;
  979. current_procinfo.aktlocaldata.destroy;
  980. current_procinfo.aktlocaldata:=oldprocinfo.aktlocaldata;
  981. { when the oldprocinfo is also being inlined reuse the
  982. inlining_procinfo }
  983. if assigned(oldprocinfo.inlining_procinfo) then
  984. current_procinfo.inlining_procinfo:=oldprocinfo.inlining_procinfo
  985. else
  986. current_procinfo.inlining_procinfo:=oldprocinfo;
  987. { takes care of local data initialization }
  988. inlineentrycode:=TAAsmoutput.Create;
  989. inlineexitcode:=TAAsmoutput.Create;
  990. {$ifdef GDB}
  991. if (cs_debuginfo in aktmoduleswitches) and
  992. not(cs_gdb_valgrind in aktglobalswitches) then
  993. begin
  994. objectlibrary.getaddrlabel(startlabel);
  995. objectlibrary.getaddrlabel(endlabel);
  996. cg.a_label(exprasmlist,startlabel);
  997. { Here we must include the para and local symtable info }
  998. procdefinition.concatstabto(withdebuglist);
  999. mangled_length:=length(current_procinfo.inlining_procinfo.procdef.mangledname);
  1000. getmem(pp,mangled_length+50);
  1001. strpcopy(pp,'192,0,0,'+startlabel.name);
  1002. if (target_info.use_function_relative_addresses) then
  1003. begin
  1004. strpcopy(strend(pp),'-');
  1005. strpcopy(strend(pp),current_procinfo.inlining_procinfo.procdef.mangledname);
  1006. end;
  1007. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1008. end;
  1009. {$endif GDB}
  1010. gen_load_para_value(inlineentrycode);
  1011. { now that we've loaded the para's, free them }
  1012. if assigned(left) then
  1013. freeparas;
  1014. gen_initialize_code(inlineentrycode);
  1015. if po_assembler in current_procinfo.procdef.procoptions then
  1016. inlineentrycode.insert(Tai_marker.Create(asmblockstart));
  1017. exprasmList.concatlist(inlineentrycode);
  1018. { process the inline code }
  1019. secondpass(inlinecode);
  1020. cg.a_label(exprasmlist,current_procinfo.aktexitlabel);
  1021. gen_finalize_code(inlineexitcode);
  1022. gen_load_return_value(inlineexitcode);
  1023. if po_assembler in current_procinfo.procdef.procoptions then
  1024. inlineexitcode.concat(Tai_marker.Create(asmblockend));
  1025. exprasmlist.concatlist(inlineexitcode);
  1026. inlineentrycode.free;
  1027. inlineexitcode.free;
  1028. {$ifdef extdebug}
  1029. exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
  1030. {$endif extdebug}
  1031. exprasmList.concat(Tai_Marker.Create(InlineEnd));
  1032. { handle function results }
  1033. if (not is_void(resulttype.def)) then
  1034. handle_return_value
  1035. else
  1036. location_reset(location,LOC_VOID,OS_NO);
  1037. { perhaps i/o check ? }
  1038. if (cs_check_io in aktlocalswitches) and
  1039. (po_iocheck in procdefinition.procoptions) and
  1040. not(po_iocheck in current_procinfo.procdef.procoptions) and
  1041. { no IO check for methods and procedure variables }
  1042. (right=nil) and
  1043. not(po_virtualmethod in procdefinition.procoptions) then
  1044. begin
  1045. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1046. cg.a_call_name(exprasmlist,'FPC_IOCHECK');
  1047. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1048. end;
  1049. { release temps of paras }
  1050. release_para_temps;
  1051. { if return value is not used }
  1052. if (not is_void(resulttype.def)) and
  1053. (not(cnf_return_value_used in callnodeflags)) then
  1054. begin
  1055. if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
  1056. begin
  1057. { data which must be finalized ? }
  1058. if (resulttype.def.needs_inittable) then
  1059. cg.g_finalize(exprasmlist,resulttype.def,location.reference);
  1060. { release unused temp }
  1061. tg.ungetiftemp(exprasmlist,location.reference)
  1062. end
  1063. else if location.loc=LOC_FPUREGISTER then
  1064. begin
  1065. {$ifdef x86}
  1066. { release FPU stack }
  1067. emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
  1068. {$endif x86}
  1069. end;
  1070. end;
  1071. { Release parameters and locals }
  1072. gen_free_symtable(exprasmlist,tparasymtable(current_procinfo.procdef.parast));
  1073. gen_free_symtable(exprasmlist,tlocalsymtable(current_procinfo.procdef.localst));
  1074. {$ifdef GDB}
  1075. if (cs_debuginfo in aktmoduleswitches) and
  1076. not(cs_gdb_valgrind in aktglobalswitches) then
  1077. begin
  1078. cg.a_label(exprasmlist,endlabel);
  1079. strpcopy(pp,'224,0,0,'+endlabel.name);
  1080. if (target_info.use_function_relative_addresses) then
  1081. begin
  1082. strpcopy(strend(pp),'-');
  1083. strpcopy(strend(pp),current_procinfo.inlining_procinfo.procdef.mangledname);
  1084. end;
  1085. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  1086. freemem(pp,mangled_length+50);
  1087. end;
  1088. {$endif GDB}
  1089. { restore }
  1090. current_procinfo.aktlocaldata:=nil;
  1091. current_procinfo.destroy;
  1092. current_procinfo:=oldprocinfo;
  1093. inlining_procedure:=oldinlining_procedure;
  1094. end;
  1095. {$endif PASS2INLINE}
  1096. procedure tcgcallnode.pass_2;
  1097. begin
  1098. if assigned(methodpointerinit) then
  1099. secondpass(methodpointerinit);
  1100. {$ifdef PASS2INLINE}
  1101. if assigned(inlinecode) then
  1102. inlined_pass_2
  1103. else
  1104. {$endif PASS2INLINE}
  1105. normal_pass_2;
  1106. if assigned(methodpointerdone) then
  1107. secondpass(methodpointerdone);
  1108. end;
  1109. begin
  1110. ccallparanode:=tcgcallparanode;
  1111. ccallnode:=tcgcallnode;
  1112. end.
  1113. {
  1114. $Log$
  1115. Revision 1.199 2005-01-30 21:51:57 jonas
  1116. * fixed darwin cycle
  1117. Revision 1.198 2005/01/29 11:36:52 peter
  1118. * update x86_64 with new cpupara
  1119. Revision 1.197 2005/01/20 17:47:01 peter
  1120. * remove copy_value_on_stack and a_param_copy_ref
  1121. Revision 1.196 2005/01/18 22:19:20 peter
  1122. * multiple location support for i386 a_param_ref
  1123. * remove a_param_copy_ref for i386
  1124. Revision 1.195 2005/01/12 10:02:22 florian
  1125. * removed ie20050111
  1126. Revision 1.194 2005/01/10 21:50:05 jonas
  1127. + support for passing records in registers under darwin
  1128. * tcgpara now also has an intsize field, which contains the size in
  1129. bytes of the whole parameter
  1130. Revision 1.193 2005/01/07 16:22:54 florian
  1131. + implemented abi compliant handling of strucutured functions results on sparc platform
  1132. Revision 1.192 2005/01/04 16:36:51 peter
  1133. * release temps in array constructor
  1134. Revision 1.191 2005/01/02 16:58:48 peter
  1135. * Don't release methodpointer. It is maybe still needed when we need to
  1136. convert the calln to loadn
  1137. Revision 1.190 2004/12/05 12:28:11 peter
  1138. * procvar handling for tp procvar mode fixed
  1139. * proc to procvar moved from addrnode to typeconvnode
  1140. * inlininginfo is now allocated only for inline routines that
  1141. can be inlined, introduced a new flag po_has_inlining_info
  1142. Revision 1.189 2004/12/02 19:26:15 peter
  1143. * disable pass2inline
  1144. Revision 1.188 2004/11/21 18:13:31 peter
  1145. * fixed funcretloc for sparc
  1146. Revision 1.187 2004/11/21 17:54:59 peter
  1147. * ttempcreatenode.create_reg merged into .create with parameter
  1148. whether a register is allowed
  1149. * funcret_paraloc renamed to funcretloc
  1150. Revision 1.186 2004/11/21 17:17:03 florian
  1151. * changed funcret location back to tlocation
  1152. Revision 1.185 2004/11/15 23:35:31 peter
  1153. * tparaitem removed, use tparavarsym instead
  1154. * parameter order is now calculated from paranr value in tparavarsym
  1155. Revision 1.184 2004/11/08 22:09:59 peter
  1156. * tvarsym splitted
  1157. Revision 1.183 2004/11/01 17:41:28 florian
  1158. * fixed arm compilation with cgutils
  1159. * ...
  1160. Revision 1.182 2004/10/31 21:45:03 peter
  1161. * generic tlocation
  1162. * move tlocation to cgutils
  1163. Revision 1.181 2004/10/24 20:01:08 peter
  1164. * remove saveregister calling convention
  1165. Revision 1.180 2004/10/24 11:53:45 peter
  1166. * fixed compilation with removed loadref
  1167. Revision 1.179 2004/10/24 11:44:28 peter
  1168. * small regvar fixes
  1169. * loadref parameter removed from concatcopy,incrrefcount,etc
  1170. Revision 1.178 2004/10/15 09:14:16 mazen
  1171. - remove $IFDEF DELPHI and related code
  1172. - remove $IFDEF FPCPROCVAR and related code
  1173. Revision 1.177 2004/10/10 20:21:18 peter
  1174. * passing a var parameter to var parameter is now also allowed
  1175. for register locations (=regvars)
  1176. Revision 1.176 2004/09/27 15:15:20 peter
  1177. * dealloc function result registers, register allocation is now
  1178. back at pre-paraloc level
  1179. Revision 1.175 2004/09/25 14:23:54 peter
  1180. * ungetregister is now only used for cpuregisters, renamed to
  1181. ungetcpuregister
  1182. * renamed (get|unget)explicitregister(s) to ..cpuregister
  1183. * removed location-release/reference_release
  1184. Revision 1.174 2004/09/21 17:25:12 peter
  1185. * paraloc branch merged
  1186. Revision 1.173.4.3 2004/09/20 20:46:34 peter
  1187. * register allocation optimized for 64bit loading of parameters
  1188. and return values
  1189. Revision 1.173.4.2 2004/09/17 17:19:26 peter
  1190. * fixed 64 bit unaryminus for sparc
  1191. * fixed 64 bit inlining
  1192. * signness of not operation
  1193. Revision 1.173.4.1 2004/08/31 20:43:06 peter
  1194. * paraloc patch
  1195. Revision 1.173 2004/07/12 10:47:42 michael
  1196. + Fix for bug 3207 from Peter
  1197. Revision 1.172 2004/07/11 19:01:13 peter
  1198. * comps are passed in int registers
  1199. Revision 1.171 2004/07/09 23:41:04 jonas
  1200. * support register parameters for inlined procedures + some inline
  1201. cleanups
  1202. Revision 1.170 2004/06/29 20:56:46 peter
  1203. * constructors don't return in parameter
  1204. Revision 1.169 2004/06/20 08:55:29 florian
  1205. * logs truncated
  1206. Revision 1.168 2004/06/16 20:07:08 florian
  1207. * dwarf branch merged
  1208. Revision 1.167 2004/05/23 18:28:41 peter
  1209. * methodpointer is loaded into a temp when it was a calln
  1210. Revision 1.166 2004/05/22 23:34:27 peter
  1211. tai_regalloc.allocation changed to ratype to notify rgobj of register size changes
  1212. Revision 1.165 2004/04/28 15:19:03 florian
  1213. + syscall directive support for MorphOS added
  1214. Revision 1.164.2.13 2004/06/12 17:01:01 florian
  1215. * fixed compilation of arm compiler
  1216. }