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