ncgflw.pas 55 KB

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