2
0

ncgflw.pas 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for nodes that influence the flow which are
  5. the same for all (most?) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgflw;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,nflw;
  24. type
  25. tcgwhilerepeatnode = class(twhilerepeatnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgifnode = class(tifnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgfornode = class(tfornode)
  32. procedure pass_2;override;
  33. end;
  34. tcgexitnode = class(texitnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgbreaknode = class(tbreaknode)
  38. procedure pass_2;override;
  39. end;
  40. tcgcontinuenode = class(tcontinuenode)
  41. procedure pass_2;override;
  42. end;
  43. tcggotonode = class(tgotonode)
  44. procedure pass_2;override;
  45. end;
  46. tcglabelnode = class(tlabelnode)
  47. procedure pass_2;override;
  48. end;
  49. tcgfailnode = class(tfailnode)
  50. procedure pass_2;override;
  51. end;
  52. tcgraisenode = class(traisenode)
  53. procedure pass_2;override;
  54. end;
  55. tcgtryexceptnode = class(ttryexceptnode)
  56. procedure pass_2;override;
  57. end;
  58. tcgtryfinallynode = class(ttryfinallynode)
  59. procedure pass_2;override;
  60. end;
  61. tcgonnode = class(tonnode)
  62. procedure pass_2;override;
  63. end;
  64. implementation
  65. uses
  66. verbose,globals,systems,globtype,
  67. symconst,symsym,aasmbase,aasmtai,aasmcpu,defutil,
  68. cginfo,cgbase,pass_2,
  69. cpubase,cpuinfo,
  70. nld,ncon,
  71. ncgutil,
  72. tgobj,rgobj,paramgr,
  73. regvars,cgobj,cgcpu
  74. {$ifndef cpu64bit}
  75. ,cg64f32
  76. {$endif cpu64bit}
  77. ;
  78. const
  79. EXCEPT_BUF_SIZE = 12;
  80. {*****************************************************************************
  81. Second_While_RepeatN
  82. *****************************************************************************}
  83. procedure tcgwhilerepeatnode.pass_2;
  84. var
  85. lcont,lbreak,lloop,
  86. oldclabel,oldblabel : tasmlabel;
  87. otlabel,oflabel : tasmlabel;
  88. begin
  89. objectlibrary.getlabel(lloop);
  90. objectlibrary.getlabel(lcont);
  91. objectlibrary.getlabel(lbreak);
  92. { arrange continue and breaklabels: }
  93. oldclabel:=aktcontinuelabel;
  94. oldblabel:=aktbreaklabel;
  95. load_all_regvars(exprasmlist);
  96. { handling code at the end as it is much more efficient, and makes
  97. while equal to repeat loop, only the end true/false is swapped (PFV) }
  98. if lnf_testatbegin in loopflags then
  99. cg.a_jmp_always(exprasmlist,lcont);
  100. if not(cs_littlesize in aktglobalswitches) then
  101. { align loop target }
  102. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  103. cg.a_label(exprasmlist,lloop);
  104. aktcontinuelabel:=lcont;
  105. aktbreaklabel:=lbreak;
  106. rg.cleartempgen;
  107. if assigned(right) then
  108. secondpass(right);
  109. load_all_regvars(exprasmlist);
  110. cg.a_label(exprasmlist,lcont);
  111. otlabel:=truelabel;
  112. oflabel:=falselabel;
  113. if lnf_checknegate in loopflags then
  114. begin
  115. truelabel:=lbreak;
  116. falselabel:=lloop;
  117. end
  118. else
  119. begin
  120. truelabel:=lloop;
  121. falselabel:=lbreak;
  122. end;
  123. rg.cleartempgen;
  124. secondpass(left);
  125. maketojumpbool(exprasmlist,left,lr_load_regvars);
  126. cg.a_label(exprasmlist,lbreak);
  127. truelabel:=otlabel;
  128. falselabel:=oflabel;
  129. aktcontinuelabel:=oldclabel;
  130. aktbreaklabel:=oldblabel;
  131. { a break/continue in a while/repeat block can't be seen outside }
  132. flowcontrol:=flowcontrol-[fc_break,fc_continue];
  133. end;
  134. {*****************************************************************************
  135. tcgIFNODE
  136. *****************************************************************************}
  137. procedure tcgifnode.pass_2;
  138. var
  139. hl,otlabel,oflabel : tasmlabel;
  140. org_regvar_loaded,
  141. then_regvar_loaded,
  142. else_regvar_loaded : regvar_booleanarray;
  143. org_list,
  144. then_list,
  145. else_list : taasmoutput;
  146. begin
  147. otlabel:=truelabel;
  148. oflabel:=falselabel;
  149. objectlibrary.getlabel(truelabel);
  150. objectlibrary.getlabel(falselabel);
  151. rg.cleartempgen;
  152. secondpass(left);
  153. { save regvars loaded in the beginning so that we can restore them }
  154. { when processing the else-block }
  155. if cs_regalloc in aktglobalswitches then
  156. begin
  157. org_list := exprasmlist;
  158. exprasmlist := taasmoutput.create;
  159. end;
  160. maketojumpbool(exprasmlist,left,lr_dont_load_regvars);
  161. if cs_regalloc in aktglobalswitches then
  162. org_regvar_loaded := rg.regvar_loaded;
  163. if assigned(right) then
  164. begin
  165. cg.a_label(exprasmlist,truelabel);
  166. rg.cleartempgen;
  167. secondpass(right);
  168. end;
  169. { save current asmlist (previous instructions + then-block) and }
  170. { loaded regvar state and create new clean ones }
  171. if cs_regalloc in aktglobalswitches then
  172. begin
  173. then_regvar_loaded := rg.regvar_loaded;
  174. rg.regvar_loaded := org_regvar_loaded;
  175. then_list := exprasmlist;
  176. exprasmlist := taasmoutput.create;
  177. end;
  178. if assigned(t1) then
  179. begin
  180. if assigned(right) then
  181. begin
  182. objectlibrary.getlabel(hl);
  183. { do go back to if line !! }
  184. if not(cs_regalloc in aktglobalswitches) then
  185. aktfilepos:=exprasmList.getlasttaifilepos^
  186. else
  187. aktfilepos:=then_list.getlasttaifilepos^;
  188. cg.a_jmp_always(exprasmlist,hl);
  189. end;
  190. cg.a_label(exprasmlist,falselabel);
  191. rg.cleartempgen;
  192. secondpass(t1);
  193. { save current asmlist (previous instructions + else-block) }
  194. { and loaded regvar state and create a new clean list }
  195. if cs_regalloc in aktglobalswitches then
  196. begin
  197. else_regvar_loaded := rg.regvar_loaded;
  198. else_list := exprasmlist;
  199. exprasmlist := taasmoutput.create;
  200. end;
  201. if assigned(right) then
  202. cg.a_label(exprasmlist,hl);
  203. end
  204. else
  205. begin
  206. if cs_regalloc in aktglobalswitches then
  207. begin
  208. else_regvar_loaded := rg.regvar_loaded;
  209. else_list := exprasmlist;
  210. exprasmlist := taasmoutput.create;
  211. end;
  212. cg.a_label(exprasmlist,falselabel);
  213. end;
  214. if not(assigned(right)) then
  215. begin
  216. cg.a_label(exprasmlist,truelabel);
  217. end;
  218. if cs_regalloc in aktglobalswitches then
  219. begin
  220. { add loads of regvars at the end of the then- and else-blocks }
  221. { so that at the end of both blocks the same regvars are loaded }
  222. { no else block? }
  223. if not assigned(t1) then
  224. sync_regvars(org_list,then_list,org_regvar_loaded,
  225. then_regvar_loaded)
  226. { no then block? }
  227. else if not assigned(right) then
  228. sync_regvars(org_list,else_list,org_regvar_loaded,
  229. else_regvar_loaded)
  230. { both else and then blocks }
  231. else
  232. sync_regvars(then_list,else_list,then_regvar_loaded,
  233. else_regvar_loaded);
  234. { add all lists together }
  235. org_list.concatlist(then_list);
  236. then_list.free;
  237. org_list.concatlist(else_list);
  238. else_list.free;
  239. org_list.concatlist(exprasmlist);
  240. exprasmlist.free;
  241. exprasmlist := org_list;
  242. end;
  243. truelabel:=otlabel;
  244. falselabel:=oflabel;
  245. end;
  246. {*****************************************************************************
  247. SecondFor
  248. *****************************************************************************}
  249. procedure tcgfornode.pass_2;
  250. var
  251. l3,oldclabel,oldblabel : tasmlabel;
  252. temptovalue : boolean;
  253. hs : byte;
  254. temp1 : treference;
  255. hop : topcg;
  256. hcond : topcmp;
  257. opsize : tcgsize;
  258. count_var_is_signed,do_loopvar_at_end : boolean;
  259. cmp_const:Tconstexprint;
  260. begin
  261. oldclabel:=aktcontinuelabel;
  262. oldblabel:=aktbreaklabel;
  263. objectlibrary.getlabel(aktcontinuelabel);
  264. objectlibrary.getlabel(aktbreaklabel);
  265. objectlibrary.getlabel(l3);
  266. { only calculate reference }
  267. rg.cleartempgen;
  268. secondpass(t2);
  269. hs := t2.resulttype.def.size;
  270. opsize := def_cgsize(t2.resulttype.def);
  271. { first set the to value
  272. because the count var can be in the expression !! }
  273. rg.cleartempgen;
  274. do_loopvar_at_end:=lnf_dont_mind_loopvar_on_exit in loopflags;
  275. secondpass(right);
  276. { calculate pointer value and check if changeable and if so }
  277. { load into temporary variable }
  278. if right.nodetype<>ordconstn then
  279. begin
  280. do_loopvar_at_end:=false;
  281. tg.GetTemp(exprasmlist,hs,tt_normal,temp1);
  282. temptovalue:=true;
  283. if (right.location.loc=LOC_REGISTER) or
  284. (right.location.loc=LOC_CREGISTER) then
  285. begin
  286. cg.a_load_reg_ref(exprasmlist,opsize,
  287. right.location.register,temp1);
  288. rg.ungetregisterint(exprasmlist,right.location.register);
  289. end
  290. else
  291. cg.g_concatcopy(exprasmlist,right.location.reference,temp1,
  292. hs,true,false);
  293. end
  294. else
  295. temptovalue:=false;
  296. { produce start assignment }
  297. rg.cleartempgen;
  298. secondpass(left);
  299. count_var_is_signed:=is_signed(t2.resulttype.def);
  300. if lnf_backward in loopflags then
  301. if count_var_is_signed then
  302. hcond:=OC_LT
  303. else
  304. hcond:=OC_B
  305. else
  306. if count_var_is_signed then
  307. hcond:=OC_GT
  308. else
  309. hcond:=OC_A;
  310. load_all_regvars(exprasmlist);
  311. if temptovalue then
  312. begin
  313. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,
  314. temp1,t2.location,aktbreaklabel);
  315. end
  316. else
  317. begin
  318. if lnf_testatbegin in loopflags then
  319. begin
  320. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  321. aword(tordconstnode(right).value),
  322. t2.location,aktbreaklabel);
  323. end;
  324. end;
  325. {If the loopvar doesn't mind on exit, we avoid this ugly
  326. dec instruction and do the loopvar inc/dec after the loop
  327. body.}
  328. if not do_loopvar_at_end then
  329. begin
  330. if lnf_backward in loopflags then
  331. hop:=OP_ADD
  332. else
  333. hop:=OP_SUB;
  334. cg.a_op_const_loc(exprasmlist,hop,1,t2.location);
  335. end;
  336. if not(cs_littlesize in aktglobalswitches) then
  337. { align loop target }
  338. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  339. cg.a_label(exprasmlist,l3);
  340. {If the loopvar doesn't mind on exit, we avoid the loopvar inc/dec
  341. after the loop body instead of here.}
  342. if not do_loopvar_at_end then
  343. begin
  344. { according to count direction DEC or INC... }
  345. if lnf_backward in loopflags then
  346. hop:=OP_SUB
  347. else
  348. hop:=OP_ADD;
  349. cg.a_op_const_loc(exprasmlist,hop,1,t2.location);
  350. end;
  351. { help register must not be in instruction block }
  352. rg.cleartempgen;
  353. if assigned(t1) then
  354. begin
  355. secondpass(t1);
  356. load_all_regvars(exprasmlist);
  357. end;
  358. {If the loopvar doesn't mind on exit, we do the loopvar inc/dec
  359. after the loop body instead of here.}
  360. if do_loopvar_at_end then
  361. begin
  362. { according to count direction DEC or INC... }
  363. if lnf_backward in loopflags then
  364. hop:=OP_SUB
  365. else
  366. hop:=OP_ADD;
  367. cg.a_op_const_loc(exprasmlist,hop,1,t2.location);
  368. end;
  369. cg.a_label(exprasmlist,aktcontinuelabel);
  370. { makes no problems there }
  371. rg.cleartempgen;
  372. if do_loopvar_at_end then
  373. if lnf_backward in loopflags then
  374. if count_var_is_signed then
  375. hcond:=OC_GTE
  376. else
  377. hcond:=OC_AE
  378. else
  379. if count_var_is_signed then
  380. hcond:=OC_LTE
  381. else
  382. hcond:=OC_BE
  383. else
  384. if lnf_backward in loopflags then
  385. if count_var_is_signed then
  386. hcond:=OC_GT
  387. else
  388. hcond:=OC_A
  389. else
  390. if count_var_is_signed then
  391. hcond:=OC_LT
  392. else
  393. hcond:=OC_B;
  394. load_all_regvars(exprasmlist);
  395. cmp_const:=aword(Tordconstnode(right).value);
  396. if do_loopvar_at_end then
  397. begin
  398. {Watch out for wrap around 255 -> 0.}
  399. {Ugly: This code is way to long... Use tables?}
  400. case opsize of
  401. OS_8:
  402. begin
  403. if lnf_backward in loopflags then
  404. begin
  405. if byte(cmp_const)=low(byte) then
  406. begin
  407. hcond:=OC_NE;
  408. cmp_const:=high(byte);
  409. end
  410. end
  411. else
  412. begin
  413. if byte(cmp_const)=high(byte) then
  414. begin
  415. hcond:=OC_NE;
  416. cmp_const:=low(byte);
  417. end
  418. end
  419. end;
  420. OS_16:
  421. begin
  422. if lnf_backward in loopflags then
  423. begin
  424. if word(cmp_const)=high(word) then
  425. begin
  426. hcond:=OC_NE;
  427. cmp_const:=low(word);
  428. end
  429. end
  430. else
  431. begin
  432. if word(cmp_const)=low(word) then
  433. begin
  434. hcond:=OC_NE;
  435. cmp_const:=high(word);
  436. end
  437. end
  438. end;
  439. OS_32:
  440. begin
  441. if lnf_backward in loopflags then
  442. begin
  443. if cardinal(cmp_const)=high(cardinal) then
  444. begin
  445. hcond:=OC_NE;
  446. cmp_const:=low(cardinal);
  447. end
  448. end
  449. else
  450. begin
  451. if cardinal(cmp_const)=low(cardinal) then
  452. begin
  453. hcond:=OC_NE;
  454. cmp_const:=high(cardinal);
  455. end
  456. end
  457. end;
  458. OS_64:
  459. begin
  460. if lnf_backward in loopflags then
  461. begin
  462. if qword(cmp_const)=high(qword) then
  463. begin
  464. hcond:=OC_NE;
  465. cmp_const:=low(qword);
  466. end
  467. end
  468. else
  469. begin
  470. if qword(cmp_const)=low(qword) then
  471. begin
  472. hcond:=OC_NE;
  473. cmp_const:=high(qword);
  474. end
  475. end
  476. end;
  477. OS_S8:
  478. begin
  479. if lnf_backward in loopflags then
  480. begin
  481. if shortint(cmp_const)=low(shortint) then
  482. begin
  483. hcond:=OC_NE;
  484. cmp_const:=high(shortint);
  485. end
  486. end
  487. else
  488. begin
  489. if shortint(cmp_const)=high(shortint) then
  490. begin
  491. hcond:=OC_NE;
  492. cmp_const:=low(shortint);
  493. end
  494. end
  495. end;
  496. OS_S16:
  497. begin
  498. if lnf_backward in loopflags then
  499. begin
  500. if integer(cmp_const)=high(integer) then
  501. begin
  502. hcond:=OC_NE;
  503. cmp_const:=low(integer);
  504. end
  505. end
  506. else
  507. begin
  508. if integer(cmp_const)=low(integer) then
  509. begin
  510. hcond:=OC_NE;
  511. cmp_const:=high(integer);
  512. end
  513. end
  514. end;
  515. OS_S32:
  516. begin
  517. if lnf_backward in loopflags then
  518. begin
  519. if longint(cmp_const)=high(longint) then
  520. begin
  521. hcond:=OC_NE;
  522. cmp_const:=low(longint);
  523. end
  524. end
  525. else
  526. begin
  527. if longint(cmp_const)=low(longint) then
  528. begin
  529. hcond:=OC_NE;
  530. cmp_const:=high(longint);
  531. end
  532. end
  533. end;
  534. OS_S64:
  535. begin
  536. if lnf_backward in loopflags then
  537. begin
  538. if int64(cmp_const)=high(int64) then
  539. begin
  540. hcond:=OC_NE;
  541. cmp_const:=low(int64);
  542. end
  543. end
  544. else
  545. begin
  546. if int64(cmp_const)=low(int64) then
  547. begin
  548. hcond:=OC_NE;
  549. cmp_const:=high(int64);
  550. end
  551. end
  552. end;
  553. else
  554. internalerror(200201021);
  555. end;
  556. end;
  557. { produce comparison and the corresponding }
  558. { jump }
  559. if temptovalue then
  560. begin
  561. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,temp1,
  562. t2.location,l3);
  563. end
  564. else
  565. begin
  566. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  567. cmp_const,t2.location,l3);
  568. end;
  569. if temptovalue then
  570. tg.ungetiftemp(exprasmlist,temp1);
  571. { this is the break label: }
  572. cg.a_label(exprasmlist,aktbreaklabel);
  573. aktcontinuelabel:=oldclabel;
  574. aktbreaklabel:=oldblabel;
  575. { a break/continue in a for block can't be seen outside }
  576. flowcontrol:=flowcontrol-[fc_break,fc_continue];
  577. end;
  578. {*****************************************************************************
  579. SecondExitN
  580. *****************************************************************************}
  581. procedure tcgexitnode.pass_2;
  582. var
  583. {op : tasmop;
  584. s : topsize;}
  585. otlabel,oflabel : tasmlabel;
  586. cgsize : tcgsize;
  587. r,hreg : tregister;
  588. allocated_acc,
  589. allocated_acchigh: boolean;
  590. label
  591. do_jmp;
  592. begin
  593. include(flowcontrol,fc_exit);
  594. if assigned(left) then
  595. begin
  596. if onlyassign then
  597. begin
  598. { just do a normal assignment followed by exit }
  599. secondpass(left);
  600. cg.a_jmp_always(exprasmlist,aktexitlabel);
  601. end
  602. else
  603. begin
  604. allocated_acc := false;
  605. allocated_acchigh := false;
  606. otlabel:=truelabel;
  607. oflabel:=falselabel;
  608. objectlibrary.getlabel(truelabel);
  609. objectlibrary.getlabel(falselabel);
  610. secondpass(left);
  611. { increment reference counter, this is
  612. useless for string constants }
  613. if (left.resulttype.def.needs_inittable) and
  614. (left.nodetype<>stringconstn) then
  615. cg.g_incrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  616. { the result of left is not needed anymore after this
  617. node }
  618. location_freetemp(exprasmlist,left.location);
  619. location_release(exprasmlist,left.location);
  620. case left.location.loc of
  621. LOC_FPUREGISTER :
  622. goto do_jmp;
  623. {$ifdef cpuflags}
  624. LOC_FLAGS :
  625. begin
  626. r.enum:=R_INTREGISTER;
  627. r.number:=NR_ACCUMULATOR;
  628. cg.a_reg_alloc(exprasmlist,r);
  629. allocated_acc := true;
  630. cg.g_flags2reg(exprasmlist,OS_INT,left.location.resflags,r);
  631. goto do_jmp;
  632. end;
  633. {$endif cpuflags}
  634. LOC_JUMP :
  635. begin
  636. r.enum:=R_INTREGISTER;
  637. r.number:=(RS_ACCUMULATOR shl 8) or R_SUBL;
  638. cg.a_reg_alloc(exprasmlist,r);
  639. { get an 8-bit register }
  640. allocated_acc := true;
  641. cg.a_label(exprasmlist,truelabel);
  642. cg.a_load_const_reg(exprasmlist,OS_8,1,r);
  643. cg.a_jmp_always(exprasmlist,aktexit2label);
  644. cg.a_label(exprasmlist,falselabel);
  645. cg.a_load_const_reg(exprasmlist,OS_8,0,r);
  646. goto do_jmp;
  647. end;
  648. end;
  649. case aktprocdef.rettype.def.deftype of
  650. pointerdef,
  651. procvardef :
  652. begin
  653. r.enum:=R_INTREGISTER;
  654. r.number:=NR_ACCUMULATOR;
  655. cg.a_reg_alloc(exprasmlist,r);
  656. allocated_acc := true;
  657. cg.a_load_loc_reg(exprasmlist,left.location,r);
  658. end;
  659. floatdef :
  660. begin
  661. {$ifdef cpufpemu}
  662. if cs_fp_emulation in aktmoduleswitches then
  663. r.enum := accumulator
  664. else
  665. {$endif cpufpemu}
  666. r.enum:=fpu_result_reg;
  667. {$ifndef i386}
  668. cg.a_reg_alloc(exprasmlist,r);
  669. {$endif not i386}
  670. cg.a_loadfpu_loc_reg(exprasmlist,left.location,r);
  671. end;
  672. else
  673. begin
  674. cgsize:=def_cgsize(aktprocdef.rettype.def);
  675. allocated_acc := true;
  676. {$ifndef cpu64bit}
  677. if cgsize in [OS_64,OS_S64] then
  678. begin
  679. r.enum:=R_INTREGISTER;
  680. r.number:=NR_ACCUMULATOR;
  681. hreg.enum:=R_INTREGISTER;
  682. hreg.number:=NR_ACCUMULATORHIGH;
  683. cg.a_reg_alloc(exprasmlist,r);
  684. cg.a_reg_alloc(exprasmlist,hreg);
  685. allocated_acchigh := true;
  686. cg64.a_load64_loc_reg(exprasmlist,left.location,
  687. joinreg64(r,hreg));
  688. end
  689. else
  690. {$endif cpu64bit}
  691. begin
  692. r.enum:=R_INTREGISTER;
  693. r.number:=(RS_ACCUMULATOR shl 8) or cgsize2subreg(cgsize);
  694. cg.a_reg_alloc(exprasmlist,r);
  695. cg.a_load_loc_reg(exprasmlist,left.location,r);
  696. end;
  697. end;
  698. end;
  699. do_jmp:
  700. truelabel:=otlabel;
  701. falselabel:=oflabel;
  702. cg.a_jmp_always(exprasmlist,aktexit2label);
  703. r.enum:=R_INTREGISTER;
  704. r.number:=NR_ACCUMULATOR;
  705. hreg.enum:=R_INTREGISTER;
  706. hreg.number:=NR_ACCUMULATORHIGH;
  707. if allocated_acc then
  708. cg.a_reg_dealloc(exprasmlist,r);
  709. {$ifndef cpu64bit}
  710. if allocated_acchigh then
  711. cg.a_reg_dealloc(exprasmlist,hreg);
  712. {$endif cpu64bit}
  713. {$ifndef i386}
  714. r.enum:=fpu_result_reg;
  715. if (aktprocdef.rettype.def.deftype = floatdef) then
  716. cg.a_reg_dealloc(exprasmlist,r);
  717. {$endif not i386}
  718. end;
  719. end
  720. else
  721. cg.a_jmp_always(exprasmlist,aktexitlabel);
  722. end;
  723. {*****************************************************************************
  724. SecondBreakN
  725. *****************************************************************************}
  726. procedure tcgbreaknode.pass_2;
  727. begin
  728. include(flowcontrol,fc_break);
  729. if aktbreaklabel<>nil then
  730. begin
  731. load_all_regvars(exprasmlist);
  732. cg.a_jmp_always(exprasmlist,aktbreaklabel)
  733. end
  734. else
  735. CGMessage(cg_e_break_not_allowed);
  736. end;
  737. {*****************************************************************************
  738. SecondContinueN
  739. *****************************************************************************}
  740. procedure tcgcontinuenode.pass_2;
  741. begin
  742. include(flowcontrol,fc_continue);
  743. if aktcontinuelabel<>nil then
  744. begin
  745. load_all_regvars(exprasmlist);
  746. cg.a_jmp_always(exprasmlist,aktcontinuelabel)
  747. end
  748. else
  749. CGMessage(cg_e_continue_not_allowed);
  750. end;
  751. {*****************************************************************************
  752. SecondGoto
  753. *****************************************************************************}
  754. procedure tcggotonode.pass_2;
  755. begin
  756. load_all_regvars(exprasmlist);
  757. cg.a_jmp_always(exprasmlist,labsym.lab)
  758. end;
  759. {*****************************************************************************
  760. SecondLabel
  761. *****************************************************************************}
  762. procedure tcglabelnode.pass_2;
  763. begin
  764. load_all_regvars(exprasmlist);
  765. cg.a_label(exprasmlist,labelnr);
  766. rg.cleartempgen;
  767. secondpass(left);
  768. end;
  769. {*****************************************************************************
  770. SecondFail
  771. *****************************************************************************}
  772. procedure tcgfailnode.pass_2;
  773. begin
  774. cg.a_jmp_always(exprasmlist,faillabel);
  775. end;
  776. {*****************************************************************************
  777. SecondRaise
  778. *****************************************************************************}
  779. procedure tcgraisenode.pass_2;
  780. var
  781. a : tasmlabel;
  782. href2: treference;
  783. r:Tregister;
  784. begin
  785. if assigned(left) then
  786. begin
  787. { multiple parameters? }
  788. if assigned(right) then
  789. begin
  790. { push frame }
  791. if assigned(frametree) then
  792. begin
  793. secondpass(frametree);
  794. if codegenerror then
  795. exit;
  796. cg.a_param_loc(exprasmlist,frametree.location,paramanager.getintparaloc(2));
  797. end
  798. else
  799. cg.a_param_const(exprasmlist,OS_INT,0,paramanager.getintparaloc(2));
  800. { push address }
  801. secondpass(right);
  802. if codegenerror then
  803. exit;
  804. cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(1));
  805. end
  806. else
  807. begin
  808. { get current address }
  809. objectlibrary.getaddrlabel(a);
  810. cg.a_label(exprasmlist,a);
  811. reference_reset_symbol(href2,a,0);
  812. { push current frame }
  813. r.enum:=R_INTREGISTER;
  814. r.number:=NR_FRAME_POINTER_REG;
  815. cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(2));
  816. { push current address }
  817. cg.a_paramaddr_ref(exprasmlist,href2,paramanager.getintparaloc(1));
  818. end;
  819. { push object }
  820. secondpass(left);
  821. if codegenerror then
  822. exit;
  823. cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(1));
  824. cg.a_call_name(exprasmlist,'FPC_RAISEEXCEPTION');
  825. end
  826. else
  827. begin
  828. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  829. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  830. end;
  831. end;
  832. {*****************************************************************************
  833. SecondTryExcept
  834. *****************************************************************************}
  835. var
  836. endexceptlabel : tasmlabel;
  837. procedure try_new_exception(list : taasmoutput;var jmpbuf,envbuf, href : treference;
  838. a : aword; exceptlabel : tasmlabel);
  839. begin
  840. tg.GetTemp(list,EXCEPT_BUF_SIZE,tt_persistant,envbuf);
  841. tg.GetTemp(list,JMP_BUF_SIZE,tt_persistant,jmpbuf);
  842. tg.GetTemp(list,sizeof(aword),tt_persistant,href);
  843. new_exception(list, jmpbuf,envbuf, href, a, exceptlabel);
  844. end;
  845. procedure try_free_exception(list : taasmoutput;var jmpbuf, envbuf, href : treference;
  846. a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
  847. begin
  848. free_exception(list, jmpbuf, envbuf, href, a, endexceptlabel, onlyfree);
  849. tg.ungettemp(list,href);
  850. tg.Ungettemp(list,jmpbuf);
  851. tg.ungettemp(list,envbuf);
  852. end;
  853. { does the necessary things to clean up the object stack }
  854. { in the except block }
  855. procedure cleanupobjectstack;
  856. var r:Tregister;
  857. begin
  858. cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK');
  859. r.enum:=R_INTREGISTER;
  860. r.number:=NR_ACCUMULATOR;
  861. cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(1));
  862. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  863. end;
  864. procedure tcgtryexceptnode.pass_2;
  865. var
  866. exceptlabel,doexceptlabel,oldendexceptlabel,
  867. lastonlabel,
  868. exitexceptlabel,
  869. continueexceptlabel,
  870. breakexceptlabel,
  871. exittrylabel,
  872. continuetrylabel,
  873. breaktrylabel,
  874. doobjectdestroy,
  875. doobjectdestroyandreraise,
  876. oldaktexitlabel,
  877. oldaktexit2label,
  878. oldaktcontinuelabel,
  879. oldaktbreaklabel : tasmlabel;
  880. oldflowcontrol,tryflowcontrol,
  881. exceptflowcontrol : tflowcontrol;
  882. tempbuf,tempaddr : treference;
  883. href : treference;
  884. r:Tregister;
  885. label
  886. errorexit;
  887. begin
  888. oldflowcontrol:=flowcontrol;
  889. flowcontrol:=[];
  890. { this can be called recursivly }
  891. oldendexceptlabel:=endexceptlabel;
  892. { save the old labels for control flow statements }
  893. oldaktexitlabel:=aktexitlabel;
  894. oldaktexit2label:=aktexit2label;
  895. if assigned(aktbreaklabel) then
  896. begin
  897. oldaktcontinuelabel:=aktcontinuelabel;
  898. oldaktbreaklabel:=aktbreaklabel;
  899. end;
  900. { get new labels for the control flow statements }
  901. objectlibrary.getlabel(exittrylabel);
  902. objectlibrary.getlabel(exitexceptlabel);
  903. if assigned(aktbreaklabel) then
  904. begin
  905. objectlibrary.getlabel(breaktrylabel);
  906. objectlibrary.getlabel(continuetrylabel);
  907. objectlibrary.getlabel(breakexceptlabel);
  908. objectlibrary.getlabel(continueexceptlabel);
  909. end;
  910. objectlibrary.getlabel(exceptlabel);
  911. objectlibrary.getlabel(doexceptlabel);
  912. objectlibrary.getlabel(endexceptlabel);
  913. objectlibrary.getlabel(lastonlabel);
  914. try_new_exception(exprasmlist,tempbuf,tempaddr,href,1,exceptlabel);
  915. { try block }
  916. { set control flow labels for the try block }
  917. aktexitlabel:=exittrylabel;
  918. aktexit2label:=exittrylabel;
  919. if assigned(oldaktbreaklabel) then
  920. begin
  921. aktcontinuelabel:=continuetrylabel;
  922. aktbreaklabel:=breaktrylabel;
  923. end;
  924. flowcontrol:=[];
  925. secondpass(left);
  926. tryflowcontrol:=flowcontrol;
  927. if codegenerror then
  928. goto errorexit;
  929. cg.a_label(exprasmlist,exceptlabel);
  930. try_free_exception(exprasmlist,tempbuf,tempaddr,href,0,endexceptlabel,false);
  931. cg.a_label(exprasmlist,doexceptlabel);
  932. { set control flow labels for the except block }
  933. { and the on statements }
  934. aktexitlabel:=exitexceptlabel;
  935. aktexit2label:=exitexceptlabel;
  936. if assigned(oldaktbreaklabel) then
  937. begin
  938. aktcontinuelabel:=continueexceptlabel;
  939. aktbreaklabel:=breakexceptlabel;
  940. end;
  941. flowcontrol:=[];
  942. { on statements }
  943. if assigned(right) then
  944. secondpass(right);
  945. cg.a_label(exprasmlist,lastonlabel);
  946. { default handling except handling }
  947. if assigned(t1) then
  948. begin
  949. { FPC_CATCHES must be called with
  950. 'default handler' flag (=-1)
  951. }
  952. cg.a_param_const(exprasmlist,OS_ADDR,aword(-1),paramanager.getintparaloc(1));
  953. cg.a_call_name(exprasmlist,'FPC_CATCHES');
  954. { the destruction of the exception object must be also }
  955. { guarded by an exception frame }
  956. objectlibrary.getlabel(doobjectdestroy);
  957. objectlibrary.getlabel(doobjectdestroyandreraise);
  958. try_new_exception(exprasmlist,tempbuf,tempaddr,href,1,doobjectdestroyandreraise);
  959. { here we don't have to reset flowcontrol }
  960. { the default and on flowcontrols are handled equal }
  961. secondpass(t1);
  962. exceptflowcontrol:=flowcontrol;
  963. cg.a_label(exprasmlist,doobjectdestroyandreraise);
  964. try_free_exception(exprasmlist,tempbuf,tempaddr,href,0,doobjectdestroy,false);
  965. cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
  966. r.enum:=R_INTREGISTER;
  967. r.number:=NR_ACCUMULATOR;
  968. cg.a_param_reg(exprasmlist, OS_ADDR, r, paramanager.getintparaloc(1));
  969. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  970. { we don't need to restore esi here because reraise never }
  971. { returns }
  972. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  973. cg.a_label(exprasmlist,doobjectdestroy);
  974. cleanupobjectstack;
  975. cg.a_jmp_always(exprasmlist,endexceptlabel);
  976. end
  977. else
  978. begin
  979. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  980. exceptflowcontrol:=flowcontrol;
  981. end;
  982. if fc_exit in exceptflowcontrol then
  983. begin
  984. { do some magic for exit in the try block }
  985. cg.a_label(exprasmlist,exitexceptlabel);
  986. { we must also destroy the address frame which guards }
  987. { exception object }
  988. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  989. cg.g_exception_reason_load(exprasmlist,href);
  990. cleanupobjectstack;
  991. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  992. end;
  993. if fc_break in exceptflowcontrol then
  994. begin
  995. cg.a_label(exprasmlist,breakexceptlabel);
  996. { we must also destroy the address frame which guards }
  997. { exception object }
  998. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  999. cg.g_exception_reason_load(exprasmlist,href);
  1000. cleanupobjectstack;
  1001. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  1002. end;
  1003. if fc_continue in exceptflowcontrol then
  1004. begin
  1005. cg.a_label(exprasmlist,continueexceptlabel);
  1006. { we must also destroy the address frame which guards }
  1007. { exception object }
  1008. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  1009. cg.g_exception_reason_load(exprasmlist,href);
  1010. cleanupobjectstack;
  1011. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  1012. end;
  1013. if fc_exit in tryflowcontrol then
  1014. begin
  1015. { do some magic for exit in the try block }
  1016. cg.a_label(exprasmlist,exittrylabel);
  1017. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  1018. cg.g_exception_reason_load(exprasmlist,href);
  1019. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  1020. end;
  1021. if fc_break in tryflowcontrol then
  1022. begin
  1023. cg.a_label(exprasmlist,breaktrylabel);
  1024. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  1025. cg.g_exception_reason_load(exprasmlist,href);
  1026. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  1027. end;
  1028. if fc_continue in tryflowcontrol then
  1029. begin
  1030. cg.a_label(exprasmlist,continuetrylabel);
  1031. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  1032. cg.g_exception_reason_load(exprasmlist,href);
  1033. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  1034. end;
  1035. cg.a_label(exprasmlist,endexceptlabel);
  1036. errorexit:
  1037. { restore all saved labels }
  1038. endexceptlabel:=oldendexceptlabel;
  1039. { restore the control flow labels }
  1040. aktexitlabel:=oldaktexitlabel;
  1041. aktexit2label:=oldaktexit2label;
  1042. if assigned(oldaktbreaklabel) then
  1043. begin
  1044. aktcontinuelabel:=oldaktcontinuelabel;
  1045. aktbreaklabel:=oldaktbreaklabel;
  1046. end;
  1047. { return all used control flow statements }
  1048. flowcontrol:=oldflowcontrol+exceptflowcontrol+
  1049. tryflowcontrol;
  1050. end;
  1051. procedure tcgonnode.pass_2;
  1052. var
  1053. nextonlabel,
  1054. exitonlabel,
  1055. continueonlabel,
  1056. breakonlabel,
  1057. oldaktexitlabel,
  1058. oldaktexit2label,
  1059. oldaktcontinuelabel,
  1060. doobjectdestroyandreraise,
  1061. doobjectdestroy,
  1062. oldaktbreaklabel : tasmlabel;
  1063. ref : treference;
  1064. oldflowcontrol : tflowcontrol;
  1065. tempbuf,tempaddr : treference;
  1066. href : treference;
  1067. href2: treference;
  1068. r:Tregister;
  1069. begin
  1070. r.enum:=R_INTREGISTER;
  1071. r.number:=NR_ACCUMULATOR;
  1072. oldflowcontrol:=flowcontrol;
  1073. flowcontrol:=[];
  1074. objectlibrary.getlabel(nextonlabel);
  1075. { send the vmt parameter }
  1076. reference_reset_symbol(href2,objectlibrary.newasmsymboldata(excepttype.vmt_mangledname),0);
  1077. cg.a_paramaddr_ref(exprasmlist,href2,paramanager.getintparaloc(1));
  1078. cg.a_call_name(exprasmlist,'FPC_CATCHES');
  1079. { is it this catch? No. go to next onlabel }
  1080. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,r,nextonlabel);
  1081. ref.symbol:=nil;
  1082. tg.GetTemp(exprasmlist,pointer_size,tt_normal,ref);
  1083. { what a hack ! }
  1084. if assigned(exceptsymtable) then
  1085. tvarsym(exceptsymtable.symindex.first).address:=ref.offset;
  1086. cg.a_load_reg_ref(exprasmlist, OS_ADDR, r, ref);
  1087. { in the case that another exception is risen }
  1088. { we've to destroy the old one }
  1089. objectlibrary.getlabel(doobjectdestroyandreraise);
  1090. { call setjmp, and jump to finally label on non-zero result }
  1091. try_new_exception(exprasmlist,tempbuf,tempaddr,href,1,doobjectdestroyandreraise);
  1092. if assigned(right) then
  1093. begin
  1094. oldaktexitlabel:=aktexitlabel;
  1095. oldaktexit2label:=aktexit2label;
  1096. objectlibrary.getlabel(exitonlabel);
  1097. aktexitlabel:=exitonlabel;
  1098. aktexit2label:=exitonlabel;
  1099. if assigned(aktbreaklabel) then
  1100. begin
  1101. oldaktcontinuelabel:=aktcontinuelabel;
  1102. oldaktbreaklabel:=aktbreaklabel;
  1103. objectlibrary.getlabel(breakonlabel);
  1104. objectlibrary.getlabel(continueonlabel);
  1105. aktcontinuelabel:=continueonlabel;
  1106. aktbreaklabel:=breakonlabel;
  1107. end;
  1108. secondpass(right);
  1109. end;
  1110. objectlibrary.getlabel(doobjectdestroy);
  1111. cg.a_label(exprasmlist,doobjectdestroyandreraise);
  1112. try_free_exception(exprasmlist,tempbuf,tempaddr,href,0,doobjectdestroy,false);
  1113. cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
  1114. cg.a_param_reg(exprasmlist, OS_ADDR, r, paramanager.getintparaloc(1));
  1115. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  1116. { we don't need to restore esi here because reraise never }
  1117. { returns }
  1118. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  1119. cg.a_label(exprasmlist,doobjectdestroy);
  1120. cleanupobjectstack;
  1121. { clear some stuff }
  1122. tg.ungetiftemp(exprasmlist,ref);
  1123. cg.a_jmp_always(exprasmlist,endexceptlabel);
  1124. if assigned(right) then
  1125. begin
  1126. { special handling for control flow instructions }
  1127. if fc_exit in flowcontrol then
  1128. begin
  1129. { the address and object pop does secondtryexcept }
  1130. cg.a_label(exprasmlist,exitonlabel);
  1131. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  1132. end;
  1133. if fc_break in flowcontrol then
  1134. begin
  1135. { the address and object pop does secondtryexcept }
  1136. cg.a_label(exprasmlist,breakonlabel);
  1137. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  1138. end;
  1139. if fc_continue in flowcontrol then
  1140. begin
  1141. { the address and object pop does secondtryexcept }
  1142. cg.a_label(exprasmlist,continueonlabel);
  1143. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  1144. end;
  1145. aktexitlabel:=oldaktexitlabel;
  1146. aktexit2label:=oldaktexit2label;
  1147. if assigned(oldaktbreaklabel) then
  1148. begin
  1149. aktcontinuelabel:=oldaktcontinuelabel;
  1150. aktbreaklabel:=oldaktbreaklabel;
  1151. end;
  1152. end;
  1153. cg.a_label(exprasmlist,nextonlabel);
  1154. flowcontrol:=oldflowcontrol+flowcontrol;
  1155. { next on node }
  1156. if assigned(left) then
  1157. begin
  1158. rg.cleartempgen;
  1159. secondpass(left);
  1160. end;
  1161. end;
  1162. {*****************************************************************************
  1163. SecondTryFinally
  1164. *****************************************************************************}
  1165. procedure tcgtryfinallynode.pass_2;
  1166. var
  1167. reraiselabel,
  1168. finallylabel,
  1169. endfinallylabel,
  1170. exitfinallylabel,
  1171. continuefinallylabel,
  1172. breakfinallylabel,
  1173. oldaktexitlabel,
  1174. oldaktexit2label,
  1175. oldaktcontinuelabel,
  1176. oldaktbreaklabel : tasmlabel;
  1177. oldflowcontrol,tryflowcontrol : tflowcontrol;
  1178. decconst : longint;
  1179. tempbuf,tempaddr : treference;
  1180. href : treference;
  1181. r:Tregister;
  1182. begin
  1183. { check if child nodes do a break/continue/exit }
  1184. oldflowcontrol:=flowcontrol;
  1185. flowcontrol:=[];
  1186. objectlibrary.getlabel(finallylabel);
  1187. objectlibrary.getlabel(endfinallylabel);
  1188. objectlibrary.getlabel(reraiselabel);
  1189. { the finally block must catch break, continue and exit }
  1190. { statements }
  1191. oldaktexitlabel:=aktexitlabel;
  1192. oldaktexit2label:=aktexit2label;
  1193. objectlibrary.getlabel(exitfinallylabel);
  1194. aktexitlabel:=exitfinallylabel;
  1195. aktexit2label:=exitfinallylabel;
  1196. if assigned(aktbreaklabel) then
  1197. begin
  1198. oldaktcontinuelabel:=aktcontinuelabel;
  1199. oldaktbreaklabel:=aktbreaklabel;
  1200. objectlibrary.getlabel(breakfinallylabel);
  1201. objectlibrary.getlabel(continuefinallylabel);
  1202. aktcontinuelabel:=continuefinallylabel;
  1203. aktbreaklabel:=breakfinallylabel;
  1204. end;
  1205. { call setjmp, and jump to finally label on non-zero result }
  1206. try_new_exception(exprasmlist,tempbuf,tempaddr,href,1,finallylabel);
  1207. { try code }
  1208. if assigned(left) then
  1209. begin
  1210. secondpass(left);
  1211. tryflowcontrol:=flowcontrol;
  1212. if codegenerror then
  1213. exit;
  1214. end;
  1215. cg.a_label(exprasmlist,finallylabel);
  1216. { just free the frame information }
  1217. try_free_exception(exprasmlist,tempbuf,tempaddr,href,1,finallylabel,true);
  1218. { finally code }
  1219. flowcontrol:=[];
  1220. secondpass(right);
  1221. if flowcontrol<>[] then
  1222. CGMessage(cg_e_control_flow_outside_finally);
  1223. if codegenerror then
  1224. exit;
  1225. { the value should now be in the exception handler }
  1226. cg.g_exception_reason_load(exprasmlist,href);
  1227. r.enum:=R_INTREGISTER;
  1228. r.number:=NR_ACCUMULATOR;
  1229. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,endfinallylabel);
  1230. cg.a_op_const_reg(exprasmlist,OP_SUB,1,r);
  1231. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,reraiselabel);
  1232. if fc_exit in tryflowcontrol then
  1233. begin
  1234. cg.a_op_const_reg(exprasmlist,OP_SUB,1,r);
  1235. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,oldaktexitlabel);
  1236. decconst:=1;
  1237. end
  1238. else
  1239. decconst:=2;
  1240. if fc_break in tryflowcontrol then
  1241. begin
  1242. cg.a_op_const_reg(exprasmlist,OP_SUB,decconst,r);
  1243. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,oldaktbreaklabel);
  1244. decconst:=1;
  1245. end
  1246. else
  1247. inc(decconst);
  1248. if fc_continue in tryflowcontrol then
  1249. begin
  1250. cg.a_op_const_reg(exprasmlist,OP_SUB,decconst,r);
  1251. cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,oldaktcontinuelabel);
  1252. end;
  1253. cg.a_label(exprasmlist,reraiselabel);
  1254. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  1255. { do some magic for exit,break,continue in the try block }
  1256. if fc_exit in tryflowcontrol then
  1257. begin
  1258. cg.a_label(exprasmlist,exitfinallylabel);
  1259. cg.g_exception_reason_load(exprasmlist,href);
  1260. cg.g_exception_reason_save_const(exprasmlist,href,2);
  1261. cg.a_jmp_always(exprasmlist,finallylabel);
  1262. end;
  1263. if fc_break in tryflowcontrol then
  1264. begin
  1265. cg.a_label(exprasmlist,breakfinallylabel);
  1266. cg.g_exception_reason_load(exprasmlist,href);
  1267. cg.g_exception_reason_save_const(exprasmlist,href,3);
  1268. cg.a_jmp_always(exprasmlist,finallylabel);
  1269. end;
  1270. if fc_continue in tryflowcontrol then
  1271. begin
  1272. cg.a_label(exprasmlist,continuefinallylabel);
  1273. cg.g_exception_reason_load(exprasmlist,href);
  1274. cg.g_exception_reason_save_const(exprasmlist,href,4);
  1275. cg.a_jmp_always(exprasmlist,finallylabel);
  1276. end;
  1277. cg.a_label(exprasmlist,endfinallylabel);
  1278. aktexitlabel:=oldaktexitlabel;
  1279. aktexit2label:=oldaktexit2label;
  1280. if assigned(aktbreaklabel) then
  1281. begin
  1282. aktcontinuelabel:=oldaktcontinuelabel;
  1283. aktbreaklabel:=oldaktbreaklabel;
  1284. end;
  1285. flowcontrol:=oldflowcontrol+tryflowcontrol;
  1286. end;
  1287. begin
  1288. cwhilerepeatnode:=tcgwhilerepeatnode;
  1289. cifnode:=tcgifnode;
  1290. cfornode:=tcgfornode;
  1291. cexitnode:=tcgexitnode;
  1292. cbreaknode:=tcgbreaknode;
  1293. ccontinuenode:=tcgcontinuenode;
  1294. cgotonode:=tcggotonode;
  1295. clabelnode:=tcglabelnode;
  1296. cfailnode:=tcgfailnode;
  1297. craisenode:=tcgraisenode;
  1298. ctryexceptnode:=tcgtryexceptnode;
  1299. ctryfinallynode:=tcgtryfinallynode;
  1300. connode:=tcgonnode;
  1301. end.
  1302. {
  1303. $Log$
  1304. Revision 1.53 2003-04-06 21:11:23 olle
  1305. * changed newasmsymbol to newasmsymboldata for data symbols
  1306. Revision 1.52 2003/03/28 19:16:56 peter
  1307. * generic constructor working for i386
  1308. * remove fixed self register
  1309. * esi added as address register for i386
  1310. Revision 1.51 2003/02/19 22:00:14 daniel
  1311. * Code generator converted to new register notation
  1312. - Horribily outdated todo.txt removed
  1313. Revision 1.50 2003/02/15 22:17:38 carl
  1314. * bugfix of FPU emulation code
  1315. Revision 1.49 2003/01/08 18:43:56 daniel
  1316. * Tregister changed into a record
  1317. Revision 1.48 2003/01/03 09:51:58 daniel
  1318. * Compiler now cycles with var_notification
  1319. Revision 1.47 2003/01/02 15:29:25 daniel
  1320. * Some debugging on for loop optimization
  1321. Revision 1.46 2002/12/31 09:55:58 daniel
  1322. + Notification implementation complete
  1323. + Add for loop code optimization using notifications
  1324. results in 1.5-1.9% speed improvement in nestloop benchmark
  1325. Optimization incomplete, compiler does not cycle yet with
  1326. notifications enabled.
  1327. Revision 1.45 2002/11/28 11:17:01 florian
  1328. * loop node flags from node flags splitted
  1329. Revision 1.44 2002/11/25 17:43:17 peter
  1330. * splitted defbase in defutil,symutil,defcmp
  1331. * merged isconvertable and is_equal into compare_defs(_ext)
  1332. * made operator search faster by walking the list only once
  1333. Revision 1.43 2002/09/30 07:00:45 florian
  1334. * fixes to common code to get the alpha compiler compiled applied
  1335. Revision 1.42 2002/09/07 15:25:02 peter
  1336. * old logs removed and tabs fixed
  1337. Revision 1.41 2002/09/01 18:47:00 peter
  1338. * assignn check in exitnode changed to use a separate boolean as the
  1339. assignn can be changed to a calln
  1340. Revision 1.40 2002/09/01 14:41:47 peter
  1341. * increase refcount in exit(arg) for arg
  1342. Revision 1.39 2002/08/24 18:41:52 peter
  1343. * fixed wrong label in jump of except block (was also in n386flw wrong)
  1344. * fixed wrong pushing of raise parameters
  1345. * fixed wrong compare in finally
  1346. Revision 1.38 2002/08/23 16:14:48 peter
  1347. * tempgen cleanup
  1348. * tt_noreuse temp type added that will be used in genentrycode
  1349. Revision 1.37 2002/08/19 19:36:43 peter
  1350. * More fixes for cross unit inlining, all tnodes are now implemented
  1351. * Moved pocall_internconst to po_internconst because it is not a
  1352. calling type at all and it conflicted when inlining of these small
  1353. functions was requested
  1354. Revision 1.36 2002/08/15 15:15:55 carl
  1355. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  1356. * more generic nodes for maths
  1357. * several fixes for better m68k support
  1358. Revision 1.35 2002/08/13 18:01:52 carl
  1359. * rename swatoperands to swapoperands
  1360. + m68k first compilable version (still needs a lot of testing):
  1361. assembler generator, system information , inline
  1362. assembler reader.
  1363. Revision 1.34 2002/08/11 14:32:26 peter
  1364. * renamed current_library to objectlibrary
  1365. Revision 1.33 2002/08/11 13:24:11 peter
  1366. * saving of asmsymbols in ppu supported
  1367. * asmsymbollist global is removed and moved into a new class
  1368. tasmlibrarydata that will hold the info of a .a file which
  1369. corresponds with a single module. Added librarydata to tmodule
  1370. to keep the library info stored for the module. In the future the
  1371. objectfiles will also be stored to the tasmlibrarydata class
  1372. * all getlabel/newasmsymbol and friends are moved to the new class
  1373. Revision 1.32 2002/08/09 19:10:59 carl
  1374. * fixed generic exception management
  1375. Revision 1.31 2002/08/04 19:06:41 carl
  1376. + added generic exception support (still does not work!)
  1377. + more documentation
  1378. Revision 1.30 2002/07/27 19:53:51 jonas
  1379. + generic implementation of tcg.g_flags2ref()
  1380. * tcg.flags2xxx() now also needs a size parameter
  1381. Revision 1.29 2002/07/25 17:56:29 carl
  1382. + FPURESULTREG -> FPU_RESULT_REG
  1383. Revision 1.28 2002/07/21 06:58:49 daniel
  1384. * Changed booleans into flags
  1385. Revision 1.27 2002/07/20 12:54:53 daniel
  1386. * Optimized the code generated for for nodes. The shootout/nestloop benchmark
  1387. now runs 5% faster on my computer.
  1388. Revision 1.26 2002/07/20 11:57:54 florian
  1389. * types.pas renamed to defbase.pas because D6 contains a types
  1390. unit so this would conflicts if D6 programms are compiled
  1391. + Willamette/SSE2 instructions to assembler added
  1392. Revision 1.25 2002/07/20 11:15:51 daniel
  1393. * The for node does a check if the first comparision can be skipped. I moved
  1394. the check from the second pass to the resulttype pass. The advantage is
  1395. that the state tracker can now decide to skip the first comparision too.
  1396. Revision 1.24 2002/07/20 08:14:24 daniel
  1397. * Loops should not be aligned when optimizing for size
  1398. Revision 1.23 2002/07/19 11:41:35 daniel
  1399. * State tracker work
  1400. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1401. allows the state tracker to change while nodes automatically into
  1402. repeat nodes.
  1403. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1404. 'not(a>b)' is optimized into 'a<=b'.
  1405. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1406. by removing the notn and later switchting the true and falselabels. The
  1407. same is done with 'repeat until not a'.
  1408. Revision 1.22 2002/07/04 20:43:01 florian
  1409. * first x86-64 patches
  1410. }