ncgflw.pas 59 KB

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