ncgflw.pas 65 KB

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