ncgflw.pas 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for nodes that influence the flow which are
  4. the same for all (most?) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgflw;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. aasmbase,node,nflw;
  23. type
  24. tcgwhilerepeatnode = class(twhilerepeatnode)
  25. procedure pass_2;override;
  26. end;
  27. tcgifnode = class(tifnode)
  28. procedure pass_2;override;
  29. end;
  30. tcgfornode = class(tfornode)
  31. procedure pass_2;override;
  32. end;
  33. tcgexitnode = class(texitnode)
  34. procedure pass_2;override;
  35. end;
  36. tcgbreaknode = class(tbreaknode)
  37. procedure pass_2;override;
  38. end;
  39. tcgcontinuenode = class(tcontinuenode)
  40. procedure pass_2;override;
  41. end;
  42. tcggotonode = class(tgotonode)
  43. procedure pass_2;override;
  44. end;
  45. tcglabelnode = class(tlabelnode)
  46. private
  47. asmlabel : tasmlabel;
  48. public
  49. function getasmlabel : tasmlabel;
  50. procedure pass_2;override;
  51. end;
  52. tcgraisenode = class(traisenode)
  53. procedure pass_2;override;
  54. end;
  55. tcgtryexceptnode = class(ttryexceptnode)
  56. procedure pass_2;override;
  57. end;
  58. tcgtryfinallynode = class(ttryfinallynode)
  59. procedure pass_2;override;
  60. end;
  61. tcgonnode = class(tonnode)
  62. procedure pass_2;override;
  63. end;
  64. implementation
  65. uses
  66. verbose,globals,systems,globtype,
  67. symconst,symdef,symsym,aasmtai,aasmcpu,defutil,
  68. procinfo,cgbase,pass_2,parabase,
  69. cpubase,cpuinfo,
  70. nld,ncon,
  71. ncgutil,
  72. tgobj,paramgr,
  73. regvars,
  74. cgutils,cgobj
  75. ;
  76. {*****************************************************************************
  77. Second_While_RepeatN
  78. *****************************************************************************}
  79. procedure tcgwhilerepeatnode.pass_2;
  80. var
  81. lcont,lbreak,lloop,
  82. oldclabel,oldblabel : tasmlabel;
  83. otlabel,oflabel : tasmlabel;
  84. oldflowcontrol : tflowcontrol;
  85. begin
  86. location_reset(location,LOC_VOID,OS_NO);
  87. objectlibrary.getjumplabel(lloop);
  88. objectlibrary.getjumplabel(lcont);
  89. objectlibrary.getjumplabel(lbreak);
  90. { arrange continue and breaklabels: }
  91. oldflowcontrol:=flowcontrol;
  92. oldclabel:=aktcontinuelabel;
  93. oldblabel:=aktbreaklabel;
  94. {$ifdef OLDREGVARS}
  95. load_all_regvars(exprasmlist);
  96. {$endif OLDREGVARS}
  97. { handling code at the end as it is much more efficient, and makes
  98. while equal to repeat loop, only the end true/false is swapped (PFV) }
  99. if lnf_testatbegin in loopflags then
  100. cg.a_jmp_always(exprasmlist,lcont);
  101. if not(cs_littlesize in aktglobalswitches) then
  102. { align loop target }
  103. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  104. cg.a_label(exprasmlist,lloop);
  105. aktcontinuelabel:=lcont;
  106. aktbreaklabel:=lbreak;
  107. if assigned(right) then
  108. secondpass(right);
  109. {$ifdef OLDREGVARS}
  110. load_all_regvars(exprasmlist);
  111. {$endif OLDREGVARS}
  112. cg.a_label(exprasmlist,lcont);
  113. otlabel:=truelabel;
  114. oflabel:=falselabel;
  115. if lnf_checknegate in loopflags then
  116. begin
  117. truelabel:=lbreak;
  118. falselabel:=lloop;
  119. end
  120. else
  121. begin
  122. truelabel:=lloop;
  123. falselabel:=lbreak;
  124. end;
  125. secondpass(left);
  126. maketojumpbool(exprasmlist,left,lr_load_regvars);
  127. cg.a_label(exprasmlist,lbreak);
  128. truelabel:=otlabel;
  129. falselabel:=oflabel;
  130. aktcontinuelabel:=oldclabel;
  131. aktbreaklabel:=oldblabel;
  132. { a break/continue in a while/repeat block can't be seen outside }
  133. flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
  134. end;
  135. {*****************************************************************************
  136. tcgIFNODE
  137. *****************************************************************************}
  138. procedure tcgifnode.pass_2;
  139. var
  140. hl,otlabel,oflabel : tasmlabel;
  141. (*
  142. org_regvar_loaded_other,
  143. then_regvar_loaded_other,
  144. else_regvar_loaded_other : regvarother_booleanarray;
  145. org_regvar_loaded_int,
  146. then_regvar_loaded_int,
  147. else_regvar_loaded_int : Tsuperregisterset;
  148. org_list,
  149. then_list,
  150. else_list : taasmoutput;
  151. *)
  152. begin
  153. location_reset(location,LOC_VOID,OS_NO);
  154. otlabel:=truelabel;
  155. oflabel:=falselabel;
  156. objectlibrary.getjumplabel(truelabel);
  157. objectlibrary.getjumplabel(falselabel);
  158. secondpass(left);
  159. (*
  160. { save regvars loaded in the beginning so that we can restore them }
  161. { when processing the else-block }
  162. if cs_regvars in aktglobalswitches then
  163. begin
  164. org_list := exprasmlist;
  165. exprasmlist := taasmoutput.create;
  166. end;
  167. *)
  168. maketojumpbool(exprasmlist,left,lr_dont_load_regvars);
  169. (*
  170. if cs_regvars in aktglobalswitches then
  171. begin
  172. org_regvar_loaded_int := rg.regvar_loaded_int;
  173. org_regvar_loaded_other := rg.regvar_loaded_other;
  174. end;
  175. *)
  176. if assigned(right) then
  177. begin
  178. cg.a_label(exprasmlist,truelabel);
  179. secondpass(right);
  180. end;
  181. { save current asmlist (previous instructions + then-block) and }
  182. { loaded regvar state and create new clean ones }
  183. if cs_regvars in aktglobalswitches then
  184. begin
  185. { then_regvar_loaded_int := rg.regvar_loaded_int;
  186. then_regvar_loaded_other := rg.regvar_loaded_other;
  187. rg.regvar_loaded_int := org_regvar_loaded_int;
  188. rg.regvar_loaded_other := org_regvar_loaded_other;
  189. then_list := exprasmlist;
  190. exprasmlist := taasmoutput.create;}
  191. end;
  192. if assigned(t1) then
  193. begin
  194. if assigned(right) then
  195. begin
  196. objectlibrary.getjumplabel(hl);
  197. { do go back to if line !! }
  198. (*
  199. if not(cs_regvars in aktglobalswitches) then
  200. *)
  201. aktfilepos:=exprasmList.getlasttaifilepos^
  202. (*
  203. else
  204. aktfilepos:=then_list.getlasttaifilepos^
  205. *)
  206. ;
  207. cg.a_jmp_always(exprasmlist,hl);
  208. end;
  209. cg.a_label(exprasmlist,falselabel);
  210. secondpass(t1);
  211. (*
  212. { save current asmlist (previous instructions + else-block) }
  213. { and loaded regvar state and create a new clean list }
  214. if cs_regvars in aktglobalswitches then
  215. begin
  216. { else_regvar_loaded_int := rg.regvar_loaded_int;
  217. else_regvar_loaded_other := rg.regvar_loaded_other;}
  218. else_list := exprasmlist;
  219. exprasmlist := taasmoutput.create;
  220. end;
  221. *)
  222. if assigned(right) then
  223. cg.a_label(exprasmlist,hl);
  224. end
  225. else
  226. begin
  227. (*
  228. if cs_regvars in aktglobalswitches then
  229. begin
  230. { else_regvar_loaded_int := rg.regvar_loaded_int;
  231. else_regvar_loaded_other := rg.regvar_loaded_other;}
  232. else_list := exprasmlist;
  233. exprasmlist := taasmoutput.create;
  234. end;
  235. *)
  236. cg.a_label(exprasmlist,falselabel);
  237. end;
  238. if not(assigned(right)) then
  239. begin
  240. cg.a_label(exprasmlist,truelabel);
  241. end;
  242. (*
  243. if cs_regvars in aktglobalswitches then
  244. begin
  245. { add loads of regvars at the end of the then- and else-blocks }
  246. { so that at the end of both blocks the same regvars are loaded }
  247. { no else block? }
  248. if not assigned(t1) then
  249. begin
  250. sync_regvars_int(org_list,then_list,org_regvar_loaded_int,then_regvar_loaded_int);
  251. sync_regvars_other(org_list,then_list,org_regvar_loaded_other,then_regvar_loaded_other);
  252. end
  253. { no then block? }
  254. else if not assigned(right) then
  255. begin
  256. sync_regvars_int(org_list,else_list,org_regvar_loaded_int,else_regvar_loaded_int);
  257. sync_regvars_other(org_list,else_list,org_regvar_loaded_other,else_regvar_loaded_other);
  258. end
  259. { both else and then blocks }
  260. else
  261. begin
  262. sync_regvars_int(then_list,else_list,then_regvar_loaded_int,else_regvar_loaded_int);
  263. sync_regvars_other(then_list,else_list,then_regvar_loaded_other,else_regvar_loaded_other);
  264. end;
  265. { add all lists together }
  266. org_list.concatlist(then_list);
  267. then_list.free;
  268. org_list.concatlist(else_list);
  269. else_list.free;
  270. org_list.concatlist(exprasmlist);
  271. exprasmlist.free;
  272. exprasmlist := org_list;
  273. end;
  274. *)
  275. truelabel:=otlabel;
  276. falselabel:=oflabel;
  277. end;
  278. {*****************************************************************************
  279. SecondFor
  280. *****************************************************************************}
  281. procedure tcgfornode.pass_2;
  282. var
  283. l3,oldclabel,oldblabel : tasmlabel;
  284. temptovalue : boolean;
  285. temp1 : treference;
  286. hop : topcg;
  287. hcond : topcmp;
  288. opsize : tcgsize;
  289. count_var_is_signed,do_loopvar_at_end : boolean;
  290. cmp_const:Tconstexprint;
  291. oldflowcontrol : tflowcontrol;
  292. begin
  293. location_reset(location,LOC_VOID,OS_NO);
  294. oldflowcontrol:=flowcontrol;
  295. oldclabel:=aktcontinuelabel;
  296. oldblabel:=aktbreaklabel;
  297. objectlibrary.getjumplabel(aktcontinuelabel);
  298. objectlibrary.getjumplabel(aktbreaklabel);
  299. objectlibrary.getjumplabel(l3);
  300. { only calculate reference }
  301. opsize := def_cgsize(left.resulttype.def);
  302. count_var_is_signed:=is_signed(left.resulttype.def);
  303. { first set the to value
  304. because the count var can be in the expression ! }
  305. do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags)
  306. { if the loop is unrolled and there is a jump into the loop,
  307. then we can't do the trick with incrementing the loop var only at the
  308. end
  309. }
  310. and not(assigned(entrylabel));
  311. secondpass(t1);
  312. { calculate pointer value and check if changeable and if so }
  313. { load into temporary variable }
  314. if t1.nodetype<>ordconstn then
  315. begin
  316. do_loopvar_at_end:=false;
  317. tg.GetTemp(exprasmlist,t1.resulttype.def.size,tt_normal,temp1);
  318. temptovalue:=true;
  319. cg.a_load_loc_ref(exprasmlist,opsize,t1.location,temp1);
  320. location_freetemp(exprasmlist,t1.location);
  321. end
  322. else
  323. temptovalue:=false;
  324. { produce start assignment }
  325. secondpass(left);
  326. secondpass(right);
  327. case left.location.loc of
  328. LOC_REFERENCE,
  329. LOC_CREFERENCE :
  330. cg.a_load_loc_ref(exprasmlist,left.location.size,right.location,left.location.reference);
  331. LOC_REGISTER,
  332. LOC_CREGISTER :
  333. cg.a_load_loc_reg(exprasmlist,left.location.size,right.location,left.location.register);
  334. else
  335. internalerror(200501311);
  336. end;
  337. if lnf_backward in loopflags then
  338. if count_var_is_signed then
  339. hcond:=OC_LT
  340. else
  341. hcond:=OC_B
  342. else
  343. if count_var_is_signed then
  344. hcond:=OC_GT
  345. else
  346. hcond:=OC_A;
  347. {$ifdef OLDREGVARS}
  348. load_all_regvars(exprasmlist);
  349. {$endif OLDREGVARS}
  350. if temptovalue then
  351. begin
  352. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,
  353. temp1,left.location,aktbreaklabel);
  354. end
  355. else
  356. begin
  357. if lnf_testatbegin in loopflags then
  358. begin
  359. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  360. tordconstnode(t1).value,
  361. left.location,aktbreaklabel);
  362. end;
  363. end;
  364. {If the loopvar doesn't mind on exit, we avoid this ugly
  365. dec instruction and do the loopvar inc/dec after the loop
  366. body.}
  367. if not do_loopvar_at_end then
  368. begin
  369. if lnf_backward in loopflags then
  370. hop:=OP_ADD
  371. else
  372. hop:=OP_SUB;
  373. cg.a_op_const_loc(exprasmlist,hop,1,left.location);
  374. end;
  375. if assigned(entrylabel) then
  376. cg.a_jmp_always(exprasmlist,tcglabelnode(entrylabel).getasmlabel);
  377. { align loop target }
  378. if not(cs_littlesize in aktglobalswitches) then
  379. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  380. cg.a_label(exprasmlist,l3);
  381. {If the loopvar doesn't mind on exit, we avoid the loopvar inc/dec
  382. after the loop body instead of here.}
  383. if not do_loopvar_at_end then
  384. begin
  385. { according to count direction DEC or INC... }
  386. if lnf_backward in loopflags then
  387. hop:=OP_SUB
  388. else
  389. hop:=OP_ADD;
  390. cg.a_op_const_loc(exprasmlist,hop,1,left.location);
  391. end;
  392. if assigned(t2) then
  393. begin
  394. secondpass(t2);
  395. {$ifdef OLDREGVARS}
  396. load_all_regvars(exprasmlist);
  397. {$endif OLDREGVARS}
  398. end;
  399. {If the loopvar doesn't mind on exit, we do the loopvar inc/dec
  400. after the loop body instead of here.}
  401. if do_loopvar_at_end then
  402. begin
  403. { according to count direction DEC or INC... }
  404. if lnf_backward in loopflags then
  405. hop:=OP_SUB
  406. else
  407. hop:=OP_ADD;
  408. cg.a_op_const_loc(exprasmlist,hop,1,left.location);
  409. end;
  410. cg.a_label(exprasmlist,aktcontinuelabel);
  411. if do_loopvar_at_end then
  412. if lnf_backward in loopflags then
  413. if count_var_is_signed then
  414. hcond:=OC_GTE
  415. else
  416. hcond:=OC_AE
  417. else
  418. if count_var_is_signed then
  419. hcond:=OC_LTE
  420. else
  421. hcond:=OC_BE
  422. else
  423. if lnf_backward in loopflags then
  424. if count_var_is_signed then
  425. hcond:=OC_GT
  426. else
  427. hcond:=OC_A
  428. else
  429. if count_var_is_signed then
  430. hcond:=OC_LT
  431. else
  432. hcond:=OC_B;
  433. {$ifdef OLDREGVARS}
  434. load_all_regvars(exprasmlist);
  435. {$endif OLDREGVARS}
  436. { produce comparison and the corresponding }
  437. { jump }
  438. if temptovalue then
  439. begin
  440. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,temp1,
  441. left.location,l3);
  442. tg.ungetiftemp(exprasmlist,temp1);
  443. end
  444. else
  445. begin
  446. cmp_const:=Tordconstnode(t1).value;
  447. if do_loopvar_at_end then
  448. begin
  449. {Watch out for wrap around 255 -> 0.}
  450. {Ugly: This code is way to long... Use tables?}
  451. case opsize of
  452. OS_8:
  453. begin
  454. if lnf_backward in loopflags then
  455. begin
  456. if byte(cmp_const)=low(byte) then
  457. begin
  458. hcond:=OC_NE;
  459. cmp_const:=high(byte);
  460. end
  461. end
  462. else
  463. begin
  464. if byte(cmp_const)=high(byte) then
  465. begin
  466. hcond:=OC_NE;
  467. cmp_const:=low(byte);
  468. end
  469. end
  470. end;
  471. OS_16:
  472. begin
  473. if lnf_backward in loopflags then
  474. begin
  475. if word(cmp_const)=high(word) then
  476. begin
  477. hcond:=OC_NE;
  478. cmp_const:=low(word);
  479. end
  480. end
  481. else
  482. begin
  483. if word(cmp_const)=low(word) then
  484. begin
  485. hcond:=OC_NE;
  486. cmp_const:=high(word);
  487. end
  488. end
  489. end;
  490. OS_32:
  491. begin
  492. if lnf_backward in loopflags then
  493. begin
  494. if cardinal(cmp_const)=high(cardinal) then
  495. begin
  496. hcond:=OC_NE;
  497. cmp_const:=low(cardinal);
  498. end
  499. end
  500. else
  501. begin
  502. if cardinal(cmp_const)=low(cardinal) then
  503. begin
  504. hcond:=OC_NE;
  505. cmp_const:=high(cardinal);
  506. end
  507. end
  508. end;
  509. OS_64:
  510. begin
  511. if lnf_backward in loopflags then
  512. begin
  513. if qword(cmp_const)=high(qword) then
  514. begin
  515. hcond:=OC_NE;
  516. cmp_const:=low(qword);
  517. end
  518. end
  519. else
  520. begin
  521. if qword(cmp_const)=low(qword) then
  522. begin
  523. hcond:=OC_NE;
  524. cmp_const:=high(qword);
  525. end
  526. end
  527. end;
  528. OS_S8:
  529. begin
  530. if lnf_backward in loopflags then
  531. begin
  532. if shortint(cmp_const)=low(shortint) then
  533. begin
  534. hcond:=OC_NE;
  535. cmp_const:=high(shortint);
  536. end
  537. end
  538. else
  539. begin
  540. if shortint(cmp_const)=high(shortint) then
  541. begin
  542. hcond:=OC_NE;
  543. cmp_const:=low(shortint);
  544. end
  545. end
  546. end;
  547. OS_S16:
  548. begin
  549. if lnf_backward in loopflags then
  550. begin
  551. if integer(cmp_const)=high(smallint) then
  552. begin
  553. hcond:=OC_NE;
  554. cmp_const:=low(smallint);
  555. end
  556. end
  557. else
  558. begin
  559. if integer(cmp_const)=low(smallint) then
  560. begin
  561. hcond:=OC_NE;
  562. cmp_const:=high(smallint);
  563. end
  564. end
  565. end;
  566. OS_S32:
  567. begin
  568. if lnf_backward in loopflags then
  569. begin
  570. if longint(cmp_const)=high(longint) then
  571. begin
  572. hcond:=OC_NE;
  573. cmp_const:=low(longint);
  574. end
  575. end
  576. else
  577. begin
  578. if longint(cmp_const)=low(longint) then
  579. begin
  580. hcond:=OC_NE;
  581. cmp_const:=high(longint);
  582. end
  583. end
  584. end;
  585. OS_S64:
  586. begin
  587. if lnf_backward in loopflags then
  588. begin
  589. if int64(cmp_const)=high(int64) then
  590. begin
  591. hcond:=OC_NE;
  592. cmp_const:=low(int64);
  593. end
  594. end
  595. else
  596. begin
  597. if int64(cmp_const)=low(int64) then
  598. begin
  599. hcond:=OC_NE;
  600. cmp_const:=high(int64);
  601. end
  602. end
  603. end;
  604. else
  605. internalerror(200201021);
  606. end;
  607. end;
  608. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  609. cmp_const,left.location,l3);
  610. end;
  611. { this is the break label: }
  612. cg.a_label(exprasmlist,aktbreaklabel);
  613. aktcontinuelabel:=oldclabel;
  614. aktbreaklabel:=oldblabel;
  615. { a break/continue in a while/repeat block can't be seen outside }
  616. flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue]);
  617. end;
  618. {*****************************************************************************
  619. SecondExitN
  620. *****************************************************************************}
  621. procedure tcgexitnode.pass_2;
  622. begin
  623. location_reset(location,LOC_VOID,OS_NO);
  624. include(flowcontrol,fc_exit);
  625. if assigned(left) then
  626. secondpass(left);
  627. cg.a_jmp_always(exprasmlist,current_procinfo.aktexitlabel);
  628. end;
  629. {*****************************************************************************
  630. SecondBreakN
  631. *****************************************************************************}
  632. procedure tcgbreaknode.pass_2;
  633. begin
  634. location_reset(location,LOC_VOID,OS_NO);
  635. include(flowcontrol,fc_break);
  636. if aktbreaklabel<>nil then
  637. begin
  638. {$ifdef OLDREGVARS}
  639. load_all_regvars(exprasmlist);
  640. {$endif OLDREGVARS}
  641. cg.a_jmp_always(exprasmlist,aktbreaklabel)
  642. end
  643. else
  644. CGMessage(cg_e_break_not_allowed);
  645. end;
  646. {*****************************************************************************
  647. SecondContinueN
  648. *****************************************************************************}
  649. procedure tcgcontinuenode.pass_2;
  650. begin
  651. location_reset(location,LOC_VOID,OS_NO);
  652. include(flowcontrol,fc_continue);
  653. if aktcontinuelabel<>nil then
  654. begin
  655. {$ifdef OLDREGVARS}
  656. load_all_regvars(exprasmlist);
  657. {$endif OLDREGVARS}
  658. cg.a_jmp_always(exprasmlist,aktcontinuelabel)
  659. end
  660. else
  661. CGMessage(cg_e_continue_not_allowed);
  662. end;
  663. {*****************************************************************************
  664. SecondGoto
  665. *****************************************************************************}
  666. procedure tcggotonode.pass_2;
  667. begin
  668. location_reset(location,LOC_VOID,OS_NO);
  669. {$ifdef OLDREGVARS}
  670. load_all_regvars(exprasmlist);
  671. {$endif OLDREGVARS}
  672. cg.a_jmp_always(exprasmlist,tcglabelnode(labelnode).getasmlabel)
  673. end;
  674. {*****************************************************************************
  675. SecondLabel
  676. *****************************************************************************}
  677. function tcglabelnode.getasmlabel : tasmlabel;
  678. begin
  679. if not(assigned(asmlabel)) then
  680. objectlibrary.getjumplabel(asmlabel);
  681. result:=asmlabel
  682. end;
  683. procedure tcglabelnode.pass_2;
  684. begin
  685. location_reset(location,LOC_VOID,OS_NO);
  686. {$ifdef OLDREGVARS}
  687. load_all_regvars(exprasmlist);
  688. {$endif OLDREGVARS}
  689. cg.a_label(exprasmlist,getasmlabel);
  690. secondpass(left);
  691. end;
  692. {*****************************************************************************
  693. SecondRaise
  694. *****************************************************************************}
  695. procedure tcgraisenode.pass_2;
  696. var
  697. a : tasmlabel;
  698. href2: treference;
  699. paraloc1,paraloc2,paraloc3 : tcgpara;
  700. begin
  701. paraloc1.init;
  702. paraloc2.init;
  703. paraloc3.init;
  704. paramanager.getintparaloc(pocall_default,1,paraloc1);
  705. paramanager.getintparaloc(pocall_default,2,paraloc2);
  706. paramanager.getintparaloc(pocall_default,3,paraloc3);
  707. location_reset(location,LOC_VOID,OS_NO);
  708. if assigned(left) then
  709. begin
  710. { multiple parameters? }
  711. if assigned(right) then
  712. begin
  713. if assigned(frametree) then
  714. secondpass(frametree);
  715. secondpass(right);
  716. end;
  717. secondpass(left);
  718. if codegenerror then
  719. exit;
  720. { Push parameters }
  721. if assigned(right) then
  722. begin
  723. paramanager.allocparaloc(exprasmlist,paraloc3);
  724. if assigned(frametree) then
  725. cg.a_param_loc(exprasmlist,frametree.location,paraloc3)
  726. else
  727. cg.a_param_const(exprasmlist,OS_INT,0,paraloc3);
  728. { push address }
  729. paramanager.allocparaloc(exprasmlist,paraloc2);
  730. cg.a_param_loc(exprasmlist,right.location,paraloc2);
  731. end
  732. else
  733. begin
  734. { get current address }
  735. objectlibrary.getaddrlabel(a);
  736. cg.a_label(exprasmlist,a);
  737. reference_reset_symbol(href2,a,0);
  738. { push current frame }
  739. paramanager.allocparaloc(exprasmlist,paraloc3);
  740. cg.a_param_reg(exprasmlist,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3);
  741. { push current address }
  742. paramanager.allocparaloc(exprasmlist,paraloc2);
  743. if target_info.system <> system_powerpc_macos then
  744. cg.a_paramaddr_ref(exprasmlist,href2,paraloc2)
  745. else
  746. cg.a_param_const(exprasmlist,OS_INT,0,paraloc2);
  747. end;
  748. paramanager.allocparaloc(exprasmlist,paraloc1);
  749. cg.a_param_loc(exprasmlist,left.location,paraloc1);
  750. paramanager.freeparaloc(exprasmlist,paraloc1);
  751. paramanager.freeparaloc(exprasmlist,paraloc2);
  752. paramanager.freeparaloc(exprasmlist,paraloc3);
  753. cg.allocallcpuregisters(exprasmlist);
  754. cg.a_call_name(exprasmlist,'FPC_RAISEEXCEPTION');
  755. cg.deallocallcpuregisters(exprasmlist);
  756. end
  757. else
  758. begin
  759. cg.allocallcpuregisters(exprasmlist);
  760. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  761. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  762. cg.deallocallcpuregisters(exprasmlist);
  763. end;
  764. paraloc1.done;
  765. paraloc2.done;
  766. paraloc3.done;
  767. end;
  768. {*****************************************************************************
  769. SecondTryExcept
  770. *****************************************************************************}
  771. var
  772. endexceptlabel : tasmlabel;
  773. { does the necessary things to clean up the object stack }
  774. { in the except block }
  775. procedure cleanupobjectstack;
  776. var
  777. paraloc1 : tcgpara;
  778. begin
  779. cg.allocallcpuregisters(exprasmlist);
  780. cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK');
  781. cg.deallocallcpuregisters(exprasmlist);
  782. paraloc1.init;
  783. paramanager.getintparaloc(pocall_default,1,paraloc1);
  784. paramanager.allocparaloc(exprasmlist,paraloc1);
  785. cg.a_param_reg(exprasmlist,OS_ADDR,NR_FUNCTION_RESULT_REG,paraloc1);
  786. paramanager.freeparaloc(exprasmlist,paraloc1);
  787. cg.allocallcpuregisters(exprasmlist);
  788. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  789. cg.deallocallcpuregisters(exprasmlist);
  790. paraloc1.done;
  791. end;
  792. procedure tcgtryexceptnode.pass_2;
  793. var
  794. exceptlabel,doexceptlabel,oldendexceptlabel,
  795. lastonlabel,
  796. exitexceptlabel,
  797. continueexceptlabel,
  798. breakexceptlabel,
  799. exittrylabel,
  800. continuetrylabel,
  801. breaktrylabel,
  802. doobjectdestroy,
  803. doobjectdestroyandreraise,
  804. oldaktexitlabel,
  805. oldaktcontinuelabel,
  806. oldaktbreaklabel : tasmlabel;
  807. oldflowcontrol,tryflowcontrol,
  808. exceptflowcontrol : tflowcontrol;
  809. destroytemps,
  810. excepttemps : texceptiontemps;
  811. paraloc1 : tcgpara;
  812. label
  813. errorexit;
  814. begin
  815. location_reset(location,LOC_VOID,OS_NO);
  816. oldflowcontrol:=flowcontrol;
  817. flowcontrol:=[];
  818. { this can be called recursivly }
  819. oldaktbreaklabel:=nil;
  820. oldaktcontinuelabel:=nil;
  821. oldendexceptlabel:=endexceptlabel;
  822. { save the old labels for control flow statements }
  823. oldaktexitlabel:=current_procinfo.aktexitlabel;
  824. if assigned(aktbreaklabel) then
  825. begin
  826. oldaktcontinuelabel:=aktcontinuelabel;
  827. oldaktbreaklabel:=aktbreaklabel;
  828. end;
  829. { get new labels for the control flow statements }
  830. objectlibrary.getjumplabel(exittrylabel);
  831. objectlibrary.getjumplabel(exitexceptlabel);
  832. if assigned(aktbreaklabel) then
  833. begin
  834. objectlibrary.getjumplabel(breaktrylabel);
  835. objectlibrary.getjumplabel(continuetrylabel);
  836. objectlibrary.getjumplabel(breakexceptlabel);
  837. objectlibrary.getjumplabel(continueexceptlabel);
  838. end;
  839. objectlibrary.getjumplabel(exceptlabel);
  840. objectlibrary.getjumplabel(doexceptlabel);
  841. objectlibrary.getjumplabel(endexceptlabel);
  842. objectlibrary.getjumplabel(lastonlabel);
  843. get_exception_temps(exprasmlist,excepttemps);
  844. new_exception(exprasmlist,excepttemps,exceptlabel);
  845. { try block }
  846. { set control flow labels for the try block }
  847. current_procinfo.aktexitlabel:=exittrylabel;
  848. if assigned(oldaktbreaklabel) then
  849. begin
  850. aktcontinuelabel:=continuetrylabel;
  851. aktbreaklabel:=breaktrylabel;
  852. end;
  853. flowcontrol:=[];
  854. secondpass(left);
  855. tryflowcontrol:=flowcontrol;
  856. if codegenerror then
  857. goto errorexit;
  858. cg.a_label(exprasmlist,exceptlabel);
  859. free_exception(exprasmlist, excepttemps, 0, endexceptlabel, false);
  860. cg.a_label(exprasmlist,doexceptlabel);
  861. { set control flow labels for the except block }
  862. { and the on statements }
  863. current_procinfo.aktexitlabel:=exitexceptlabel;
  864. if assigned(oldaktbreaklabel) then
  865. begin
  866. aktcontinuelabel:=continueexceptlabel;
  867. aktbreaklabel:=breakexceptlabel;
  868. end;
  869. flowcontrol:=[];
  870. { on statements }
  871. if assigned(right) then
  872. secondpass(right);
  873. cg.a_label(exprasmlist,lastonlabel);
  874. { default handling except handling }
  875. if assigned(t1) then
  876. begin
  877. { FPC_CATCHES must be called with
  878. 'default handler' flag (=-1)
  879. }
  880. paraloc1.init;
  881. paramanager.getintparaloc(pocall_default,1,paraloc1);
  882. paramanager.allocparaloc(exprasmlist,paraloc1);
  883. cg.a_param_const(exprasmlist,OS_ADDR,-1,paraloc1);
  884. paramanager.freeparaloc(exprasmlist,paraloc1);
  885. cg.allocallcpuregisters(exprasmlist);
  886. cg.a_call_name(exprasmlist,'FPC_CATCHES');
  887. cg.deallocallcpuregisters(exprasmlist);
  888. paraloc1.done;
  889. { the destruction of the exception object must be also }
  890. { guarded by an exception frame }
  891. objectlibrary.getjumplabel(doobjectdestroy);
  892. objectlibrary.getjumplabel(doobjectdestroyandreraise);
  893. get_exception_temps(exprasmlist,destroytemps);
  894. new_exception(exprasmlist,destroytemps,doobjectdestroyandreraise);
  895. { here we don't have to reset flowcontrol }
  896. { the default and on flowcontrols are handled equal }
  897. secondpass(t1);
  898. exceptflowcontrol:=flowcontrol;
  899. cg.a_label(exprasmlist,doobjectdestroyandreraise);
  900. free_exception(exprasmlist,destroytemps,0,doobjectdestroy,false);
  901. cg.allocallcpuregisters(exprasmlist);
  902. cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
  903. cg.deallocallcpuregisters(exprasmlist);
  904. paraloc1.init;
  905. paramanager.getintparaloc(pocall_default,1,paraloc1);
  906. paramanager.allocparaloc(exprasmlist,paraloc1);
  907. cg.a_param_reg(exprasmlist, OS_ADDR, NR_FUNCTION_RESULT_REG, paraloc1);
  908. paramanager.freeparaloc(exprasmlist,paraloc1);
  909. cg.allocallcpuregisters(exprasmlist);
  910. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  911. cg.deallocallcpuregisters(exprasmlist);
  912. paraloc1.done;
  913. { we don't need to restore esi here because reraise never }
  914. { returns }
  915. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  916. cg.a_label(exprasmlist,doobjectdestroy);
  917. cleanupobjectstack;
  918. unget_exception_temps(exprasmlist,destroytemps);
  919. cg.a_jmp_always(exprasmlist,endexceptlabel);
  920. end
  921. else
  922. begin
  923. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  924. exceptflowcontrol:=flowcontrol;
  925. end;
  926. if fc_exit in exceptflowcontrol then
  927. begin
  928. { do some magic for exit in the try block }
  929. cg.a_label(exprasmlist,exitexceptlabel);
  930. { we must also destroy the address frame which guards }
  931. { exception object }
  932. cg.allocallcpuregisters(exprasmlist);
  933. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  934. cg.deallocallcpuregisters(exprasmlist);
  935. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  936. cleanupobjectstack;
  937. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  938. end;
  939. if fc_break in exceptflowcontrol then
  940. begin
  941. cg.a_label(exprasmlist,breakexceptlabel);
  942. { we must also destroy the address frame which guards }
  943. { exception object }
  944. cg.allocallcpuregisters(exprasmlist);
  945. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  946. cg.deallocallcpuregisters(exprasmlist);
  947. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  948. cleanupobjectstack;
  949. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  950. end;
  951. if fc_continue in exceptflowcontrol then
  952. begin
  953. cg.a_label(exprasmlist,continueexceptlabel);
  954. { we must also destroy the address frame which guards }
  955. { exception object }
  956. cg.allocallcpuregisters(exprasmlist);
  957. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  958. cg.deallocallcpuregisters(exprasmlist);
  959. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  960. cleanupobjectstack;
  961. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  962. end;
  963. if fc_exit in tryflowcontrol then
  964. begin
  965. { do some magic for exit in the try block }
  966. cg.a_label(exprasmlist,exittrylabel);
  967. cg.allocallcpuregisters(exprasmlist);
  968. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  969. cg.deallocallcpuregisters(exprasmlist);
  970. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  971. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  972. end;
  973. if fc_break in tryflowcontrol then
  974. begin
  975. cg.a_label(exprasmlist,breaktrylabel);
  976. cg.allocallcpuregisters(exprasmlist);
  977. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  978. cg.deallocallcpuregisters(exprasmlist);
  979. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  980. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  981. end;
  982. if fc_continue in tryflowcontrol then
  983. begin
  984. cg.a_label(exprasmlist,continuetrylabel);
  985. cg.allocallcpuregisters(exprasmlist);
  986. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  987. cg.deallocallcpuregisters(exprasmlist);
  988. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  989. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  990. end;
  991. unget_exception_temps(exprasmlist,excepttemps);
  992. cg.a_label(exprasmlist,endexceptlabel);
  993. errorexit:
  994. { restore all saved labels }
  995. endexceptlabel:=oldendexceptlabel;
  996. { restore the control flow labels }
  997. current_procinfo.aktexitlabel:=oldaktexitlabel;
  998. if assigned(oldaktbreaklabel) then
  999. begin
  1000. aktcontinuelabel:=oldaktcontinuelabel;
  1001. aktbreaklabel:=oldaktbreaklabel;
  1002. end;
  1003. { return all used control flow statements }
  1004. flowcontrol:=oldflowcontrol+exceptflowcontrol+
  1005. tryflowcontrol;
  1006. end;
  1007. procedure tcgonnode.pass_2;
  1008. var
  1009. nextonlabel,
  1010. exitonlabel,
  1011. continueonlabel,
  1012. breakonlabel,
  1013. oldaktexitlabel,
  1014. oldaktcontinuelabel,
  1015. doobjectdestroyandreraise,
  1016. doobjectdestroy,
  1017. oldaktbreaklabel : tasmlabel;
  1018. oldflowcontrol : tflowcontrol;
  1019. excepttemps : texceptiontemps;
  1020. exceptref,
  1021. href2: treference;
  1022. paraloc1 : tcgpara;
  1023. begin
  1024. paraloc1.init;
  1025. location_reset(location,LOC_VOID,OS_NO);
  1026. oldflowcontrol:=flowcontrol;
  1027. flowcontrol:=[];
  1028. objectlibrary.getjumplabel(nextonlabel);
  1029. { send the vmt parameter }
  1030. reference_reset_symbol(href2,objectlibrary.newasmsymbol(excepttype.vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
  1031. paramanager.getintparaloc(pocall_default,1,paraloc1);
  1032. paramanager.allocparaloc(exprasmlist,paraloc1);
  1033. cg.a_paramaddr_ref(exprasmlist,href2,paraloc1);
  1034. paramanager.freeparaloc(exprasmlist,paraloc1);
  1035. cg.allocallcpuregisters(exprasmlist);
  1036. cg.a_call_name(exprasmlist,'FPC_CATCHES');
  1037. cg.deallocallcpuregisters(exprasmlist);
  1038. { is it this catch? No. go to next onlabel }
  1039. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,NR_FUNCTION_RESULT_REG,nextonlabel);
  1040. { what a hack ! }
  1041. if assigned(exceptsymtable) then
  1042. begin
  1043. tlocalvarsym(exceptsymtable.symindex.first).localloc.loc:=LOC_REFERENCE;
  1044. tlocalvarsym(exceptsymtable.symindex.first).localloc.size:=OS_ADDR;
  1045. tg.GetLocal(exprasmlist,sizeof(aint),voidpointertype.def,
  1046. tlocalvarsym(exceptsymtable.symindex.first).localloc.reference);
  1047. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,tlocalvarsym(exceptsymtable.symindex.first).localloc.reference);
  1048. end
  1049. else
  1050. begin
  1051. tg.GetTemp(exprasmlist,sizeof(aint),tt_normal,exceptref);
  1052. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,exceptref);
  1053. end;
  1054. { in the case that another exception is risen
  1055. we've to destroy the old one }
  1056. objectlibrary.getjumplabel(doobjectdestroyandreraise);
  1057. { call setjmp, and jump to finally label on non-zero result }
  1058. get_exception_temps(exprasmlist,excepttemps);
  1059. new_exception(exprasmlist,excepttemps,doobjectdestroyandreraise);
  1060. oldaktbreaklabel:=nil;
  1061. oldaktcontinuelabel:=nil;
  1062. if assigned(right) then
  1063. begin
  1064. oldaktexitlabel:=current_procinfo.aktexitlabel;
  1065. objectlibrary.getjumplabel(exitonlabel);
  1066. current_procinfo.aktexitlabel:=exitonlabel;
  1067. if assigned(aktbreaklabel) then
  1068. begin
  1069. oldaktcontinuelabel:=aktcontinuelabel;
  1070. oldaktbreaklabel:=aktbreaklabel;
  1071. objectlibrary.getjumplabel(breakonlabel);
  1072. objectlibrary.getjumplabel(continueonlabel);
  1073. aktcontinuelabel:=continueonlabel;
  1074. aktbreaklabel:=breakonlabel;
  1075. end;
  1076. secondpass(right);
  1077. end;
  1078. objectlibrary.getjumplabel(doobjectdestroy);
  1079. cg.a_label(exprasmlist,doobjectdestroyandreraise);
  1080. free_exception(exprasmlist,excepttemps,0,doobjectdestroy,false);
  1081. cg.allocallcpuregisters(exprasmlist);
  1082. cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
  1083. cg.deallocallcpuregisters(exprasmlist);
  1084. paramanager.getintparaloc(pocall_default,1,paraloc1);
  1085. paramanager.allocparaloc(exprasmlist,paraloc1);
  1086. cg.a_param_reg(exprasmlist, OS_ADDR, NR_FUNCTION_RESULT_REG, paraloc1);
  1087. paramanager.freeparaloc(exprasmlist,paraloc1);
  1088. cg.allocallcpuregisters(exprasmlist);
  1089. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  1090. cg.deallocallcpuregisters(exprasmlist);
  1091. { we don't need to store/restore registers here because reraise never
  1092. returns }
  1093. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  1094. cg.a_label(exprasmlist,doobjectdestroy);
  1095. cleanupobjectstack;
  1096. { clear some stuff }
  1097. if assigned(exceptsymtable) then
  1098. begin
  1099. tg.UngetLocal(exprasmlist,tlocalvarsym(exceptsymtable.symindex.first).localloc.reference);
  1100. tlocalvarsym(exceptsymtable.symindex.first).localloc.loc:=LOC_INVALID;
  1101. end
  1102. else
  1103. tg.Ungettemp(exprasmlist,exceptref);
  1104. cg.a_jmp_always(exprasmlist,endexceptlabel);
  1105. if assigned(right) then
  1106. begin
  1107. { special handling for control flow instructions }
  1108. if fc_exit in flowcontrol then
  1109. begin
  1110. { the address and object pop does secondtryexcept }
  1111. cg.a_label(exprasmlist,exitonlabel);
  1112. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  1113. end;
  1114. if fc_break in flowcontrol then
  1115. begin
  1116. { the address and object pop does secondtryexcept }
  1117. cg.a_label(exprasmlist,breakonlabel);
  1118. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  1119. end;
  1120. if fc_continue in flowcontrol then
  1121. begin
  1122. { the address and object pop does secondtryexcept }
  1123. cg.a_label(exprasmlist,continueonlabel);
  1124. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  1125. end;
  1126. current_procinfo.aktexitlabel:=oldaktexitlabel;
  1127. if assigned(oldaktbreaklabel) then
  1128. begin
  1129. aktcontinuelabel:=oldaktcontinuelabel;
  1130. aktbreaklabel:=oldaktbreaklabel;
  1131. end;
  1132. end;
  1133. unget_exception_temps(exprasmlist,excepttemps);
  1134. cg.a_label(exprasmlist,nextonlabel);
  1135. flowcontrol:=oldflowcontrol+flowcontrol;
  1136. paraloc1.done;
  1137. { next on node }
  1138. if assigned(left) then
  1139. secondpass(left);
  1140. end;
  1141. {*****************************************************************************
  1142. SecondTryFinally
  1143. *****************************************************************************}
  1144. procedure tcgtryfinallynode.pass_2;
  1145. var
  1146. reraiselabel,
  1147. finallylabel,
  1148. endfinallylabel,
  1149. exitfinallylabel,
  1150. continuefinallylabel,
  1151. breakfinallylabel,
  1152. oldaktexitlabel,
  1153. oldaktcontinuelabel,
  1154. oldaktbreaklabel : tasmlabel;
  1155. oldflowcontrol,tryflowcontrol : tflowcontrol;
  1156. decconst : longint;
  1157. excepttemps : texceptiontemps;
  1158. begin
  1159. location_reset(location,LOC_VOID,OS_NO);
  1160. { check if child nodes do a break/continue/exit }
  1161. oldflowcontrol:=flowcontrol;
  1162. flowcontrol:=[];
  1163. objectlibrary.getjumplabel(finallylabel);
  1164. objectlibrary.getjumplabel(endfinallylabel);
  1165. objectlibrary.getjumplabel(reraiselabel);
  1166. { the finally block must catch break, continue and exit }
  1167. { statements }
  1168. oldaktexitlabel:=current_procinfo.aktexitlabel;
  1169. if implicitframe then
  1170. exitfinallylabel:=finallylabel
  1171. else
  1172. objectlibrary.getjumplabel(exitfinallylabel);
  1173. current_procinfo.aktexitlabel:=exitfinallylabel;
  1174. if assigned(aktbreaklabel) then
  1175. begin
  1176. oldaktcontinuelabel:=aktcontinuelabel;
  1177. oldaktbreaklabel:=aktbreaklabel;
  1178. if implicitframe then
  1179. begin
  1180. breakfinallylabel:=finallylabel;
  1181. continuefinallylabel:=finallylabel;
  1182. end
  1183. else
  1184. begin
  1185. objectlibrary.getjumplabel(breakfinallylabel);
  1186. objectlibrary.getjumplabel(continuefinallylabel);
  1187. end;
  1188. aktcontinuelabel:=continuefinallylabel;
  1189. aktbreaklabel:=breakfinallylabel;
  1190. end;
  1191. { call setjmp, and jump to finally label on non-zero result }
  1192. get_exception_temps(exprasmlist,excepttemps);
  1193. new_exception(exprasmlist,excepttemps,finallylabel);
  1194. { try code }
  1195. if assigned(left) then
  1196. begin
  1197. secondpass(left);
  1198. tryflowcontrol:=flowcontrol;
  1199. if codegenerror then
  1200. exit;
  1201. end;
  1202. cg.a_label(exprasmlist,finallylabel);
  1203. { just free the frame information }
  1204. free_exception(exprasmlist,excepttemps,1,finallylabel,true);
  1205. { finally code }
  1206. flowcontrol:=[];
  1207. secondpass(right);
  1208. if flowcontrol<>[] then
  1209. CGMessage(cg_e_control_flow_outside_finally);
  1210. if codegenerror then
  1211. exit;
  1212. { the value should now be in the exception handler }
  1213. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  1214. if implicitframe then
  1215. begin
  1216. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,endfinallylabel);
  1217. { finally code only needed to be executed on exception }
  1218. flowcontrol:=[];
  1219. secondpass(t1);
  1220. if flowcontrol<>[] then
  1221. CGMessage(cg_e_control_flow_outside_finally);
  1222. if codegenerror then
  1223. exit;
  1224. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  1225. end
  1226. else
  1227. begin
  1228. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,endfinallylabel);
  1229. cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,1,NR_FUNCTION_RESULT_REG);
  1230. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,reraiselabel);
  1231. if fc_exit in tryflowcontrol then
  1232. begin
  1233. cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,1,NR_FUNCTION_RESULT_REG);
  1234. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldaktexitlabel);
  1235. decconst:=1;
  1236. end
  1237. else
  1238. decconst:=2;
  1239. if fc_break in tryflowcontrol then
  1240. begin
  1241. cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,decconst,NR_FUNCTION_RESULT_REG);
  1242. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldaktbreaklabel);
  1243. decconst:=1;
  1244. end
  1245. else
  1246. inc(decconst);
  1247. if fc_continue in tryflowcontrol then
  1248. begin
  1249. cg.a_op_const_reg(exprasmlist,OP_SUB,OS_INT,decconst,NR_FUNCTION_RESULT_REG);
  1250. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldaktcontinuelabel);
  1251. end;
  1252. cg.a_label(exprasmlist,reraiselabel);
  1253. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  1254. { do some magic for exit,break,continue in the try block }
  1255. if fc_exit in tryflowcontrol then
  1256. begin
  1257. cg.a_label(exprasmlist,exitfinallylabel);
  1258. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  1259. cg.g_exception_reason_save_const(exprasmlist,excepttemps.reasonbuf,2);
  1260. cg.a_jmp_always(exprasmlist,finallylabel);
  1261. end;
  1262. if fc_break in tryflowcontrol then
  1263. begin
  1264. cg.a_label(exprasmlist,breakfinallylabel);
  1265. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  1266. cg.g_exception_reason_save_const(exprasmlist,excepttemps.reasonbuf,3);
  1267. cg.a_jmp_always(exprasmlist,finallylabel);
  1268. end;
  1269. if fc_continue in tryflowcontrol then
  1270. begin
  1271. cg.a_label(exprasmlist,continuefinallylabel);
  1272. cg.g_exception_reason_load(exprasmlist,excepttemps.reasonbuf);
  1273. cg.g_exception_reason_save_const(exprasmlist,excepttemps.reasonbuf,4);
  1274. cg.a_jmp_always(exprasmlist,finallylabel);
  1275. end;
  1276. end;
  1277. unget_exception_temps(exprasmlist,excepttemps);
  1278. cg.a_label(exprasmlist,endfinallylabel);
  1279. current_procinfo.aktexitlabel:=oldaktexitlabel;
  1280. if assigned(aktbreaklabel) then
  1281. begin
  1282. aktcontinuelabel:=oldaktcontinuelabel;
  1283. aktbreaklabel:=oldaktbreaklabel;
  1284. end;
  1285. flowcontrol:=oldflowcontrol+tryflowcontrol;
  1286. end;
  1287. begin
  1288. cwhilerepeatnode:=tcgwhilerepeatnode;
  1289. cifnode:=tcgifnode;
  1290. cfornode:=tcgfornode;
  1291. cexitnode:=tcgexitnode;
  1292. cbreaknode:=tcgbreaknode;
  1293. ccontinuenode:=tcgcontinuenode;
  1294. cgotonode:=tcggotonode;
  1295. clabelnode:=tcglabelnode;
  1296. craisenode:=tcgraisenode;
  1297. ctryexceptnode:=tcgtryexceptnode;
  1298. ctryfinallynode:=tcgtryfinallynode;
  1299. connode:=tcgonnode;
  1300. end.