ncgflw.pas 64 KB

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