ncgflw.pas 57 KB

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