ncgflw.pas 59 KB

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