ncgflw.pas 65 KB

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