ncgflw.pas 57 KB

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