ncgflw.pas 60 KB

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