ncgflw.pas 63 KB

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