n386flw.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for nodes that influence the flow
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit n386flw;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,nflw;
  23. type
  24. ti386raisenode = class(traisenode)
  25. procedure pass_2;override;
  26. end;
  27. ti386tryexceptnode = class(ttryexceptnode)
  28. procedure pass_2;override;
  29. end;
  30. ti386tryfinallynode = class(ttryfinallynode)
  31. procedure pass_2;override;
  32. end;
  33. ti386onnode = class(tonnode)
  34. procedure pass_2;override;
  35. end;
  36. ti386failnode = class(tfailnode)
  37. procedure pass_2;override;
  38. end;
  39. implementation
  40. uses
  41. verbose,systems,
  42. symsym,aasm,
  43. cgbase,temp_gen,pass_2,
  44. cpubase,cpuasm,
  45. nld,ncon,
  46. tainst,cga,tgcpu;
  47. {*****************************************************************************
  48. SecondRaise
  49. *****************************************************************************}
  50. procedure ti386raisenode.pass_2;
  51. var
  52. a : tasmlabel;
  53. begin
  54. if assigned(left) then
  55. begin
  56. { multiple parameters? }
  57. if assigned(right) then
  58. begin
  59. { push frame }
  60. if assigned(frametree) then
  61. begin
  62. secondpass(frametree);
  63. if codegenerror then
  64. exit;
  65. emit_push_loc(frametree.location);
  66. end
  67. else
  68. emit_const(A_PUSH,S_L,0);
  69. { push address }
  70. secondpass(right);
  71. if codegenerror then
  72. exit;
  73. emit_push_loc(right.location);
  74. end
  75. else
  76. begin
  77. getaddrlabel(a);
  78. emitlab(a);
  79. emit_reg(A_PUSH,S_L,R_EBP);
  80. emit_sym(A_PUSH,S_L,a);
  81. end;
  82. { push object }
  83. secondpass(left);
  84. if codegenerror then
  85. exit;
  86. emit_push_loc(left.location);
  87. emitcall('FPC_RAISEEXCEPTION');
  88. end
  89. else
  90. begin
  91. emitcall('FPC_POPADDRSTACK');
  92. emitcall('FPC_RERAISE');
  93. end;
  94. end;
  95. {*****************************************************************************
  96. SecondTryExcept
  97. *****************************************************************************}
  98. var
  99. endexceptlabel : tasmlabel;
  100. { does the necessary things to clean up the object stack }
  101. { in the except block }
  102. procedure cleanupobjectstack;
  103. begin
  104. emitcall('FPC_POPOBJECTSTACK');
  105. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  106. emit_reg(A_PUSH,S_L,R_EAX);
  107. emitcall('FPC_DESTROYEXCEPTION');
  108. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  109. maybe_loadself;
  110. end;
  111. { pops one element from the exception address stack }
  112. { and removes the flag }
  113. procedure cleanupaddrstack;
  114. begin
  115. emitcall('FPC_POPADDRSTACK');
  116. { allocate eax }
  117. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  118. emit_reg(A_POP,S_L,R_EAX);
  119. { deallocate eax }
  120. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  121. end;
  122. procedure ti386tryexceptnode.pass_2;
  123. var
  124. exceptlabel,doexceptlabel,oldendexceptlabel,
  125. lastonlabel,
  126. exitexceptlabel,
  127. continueexceptlabel,
  128. breakexceptlabel,
  129. exittrylabel,
  130. continuetrylabel,
  131. breaktrylabel,
  132. doobjectdestroy,
  133. doobjectdestroyandreraise,
  134. oldaktexitlabel,
  135. oldaktexit2label,
  136. oldaktcontinuelabel,
  137. oldaktbreaklabel : tasmlabel;
  138. oldflowcontrol,tryflowcontrol,
  139. exceptflowcontrol : tflowcontrol;
  140. tempbuf,tempaddr : treference;
  141. label
  142. errorexit;
  143. begin
  144. oldflowcontrol:=flowcontrol;
  145. flowcontrol:=[];
  146. { this can be called recursivly }
  147. oldendexceptlabel:=endexceptlabel;
  148. { we modify EAX }
  149. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  150. { save the old labels for control flow statements }
  151. oldaktexitlabel:=aktexitlabel;
  152. oldaktexit2label:=aktexit2label;
  153. if assigned(aktbreaklabel) then
  154. begin
  155. oldaktcontinuelabel:=aktcontinuelabel;
  156. oldaktbreaklabel:=aktbreaklabel;
  157. end;
  158. { get new labels for the control flow statements }
  159. getlabel(exittrylabel);
  160. getlabel(exitexceptlabel);
  161. if assigned(aktbreaklabel) then
  162. begin
  163. getlabel(breaktrylabel);
  164. getlabel(continuetrylabel);
  165. getlabel(breakexceptlabel);
  166. getlabel(continueexceptlabel);
  167. end;
  168. getlabel(exceptlabel);
  169. getlabel(doexceptlabel);
  170. getlabel(endexceptlabel);
  171. getlabel(lastonlabel);
  172. gettempofsizereferencepersistant(24,tempbuf);
  173. gettempofsizereferencepersistant(12,tempaddr);
  174. emitpushreferenceaddr(tempaddr);
  175. emitpushreferenceaddr(tempbuf);
  176. push_int (1); { push type of exceptionframe }
  177. emitcall('FPC_PUSHEXCEPTADDR');
  178. { allocate eax }
  179. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  180. emit_reg(A_PUSH,S_L,R_EAX);
  181. emitcall('FPC_SETJMP');
  182. emit_reg(A_PUSH,S_L,R_EAX);
  183. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  184. { deallocate eax }
  185. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  186. emitjmp(C_NE,exceptlabel);
  187. { try block }
  188. { set control flow labels for the try block }
  189. aktexitlabel:=exittrylabel;
  190. aktexit2label:=exittrylabel;
  191. if assigned(oldaktbreaklabel) then
  192. begin
  193. aktcontinuelabel:=continuetrylabel;
  194. aktbreaklabel:=breaktrylabel;
  195. end;
  196. flowcontrol:=[];
  197. secondpass(left);
  198. tryflowcontrol:=flowcontrol;
  199. if codegenerror then
  200. goto errorexit;
  201. emitlab(exceptlabel);
  202. emitcall('FPC_POPADDRSTACK');
  203. ungetpersistanttempreference(tempaddr);
  204. ungetpersistanttempreference(tempbuf);
  205. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  206. emit_reg(A_POP,S_L,R_EAX);
  207. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  208. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  209. emitjmp(C_E,endexceptlabel);
  210. emitlab(doexceptlabel);
  211. { set control flow labels for the except block }
  212. { and the on statements }
  213. aktexitlabel:=exitexceptlabel;
  214. aktexit2label:=exitexceptlabel;
  215. if assigned(oldaktbreaklabel) then
  216. begin
  217. aktcontinuelabel:=continueexceptlabel;
  218. aktbreaklabel:=breakexceptlabel;
  219. end;
  220. flowcontrol:=[];
  221. { on statements }
  222. if assigned(right) then
  223. secondpass(right);
  224. emitlab(lastonlabel);
  225. { default handling except handling }
  226. if assigned(t1) then
  227. begin
  228. { FPC_CATCHES must be called with
  229. 'default handler' flag (=-1)
  230. }
  231. push_int (-1);
  232. emitcall('FPC_CATCHES');
  233. maybe_loadself;
  234. { the destruction of the exception object must be also }
  235. { guarded by an exception frame }
  236. getlabel(doobjectdestroy);
  237. getlabel(doobjectdestroyandreraise);
  238. gettempofsizereferencepersistant(12,tempaddr);
  239. gettempofsizereferencepersistant(24,tempbuf);
  240. emitpushreferenceaddr(tempaddr);
  241. emitpushreferenceaddr(tempbuf);
  242. exprasmList.concat(Taicpu.Op_const(A_PUSH,S_L,1));
  243. emitcall('FPC_PUSHEXCEPTADDR');
  244. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  245. exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
  246. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  247. emitcall('FPC_SETJMP');
  248. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  249. exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
  250. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  251. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  252. emitjmp(C_NE,doobjectdestroyandreraise);
  253. { here we don't have to reset flowcontrol }
  254. { the default and on flowcontrols are handled equal }
  255. secondpass(t1);
  256. exceptflowcontrol:=flowcontrol;
  257. emitlab(doobjectdestroyandreraise);
  258. emitcall('FPC_POPADDRSTACK');
  259. ungetpersistanttempreference(tempaddr);
  260. ungetpersistanttempreference(tempbuf);
  261. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  262. exprasmList.concat(Taicpu.op_reg(A_POP,S_L,R_EAX));
  263. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  264. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  265. emitjmp(C_E,doobjectdestroy);
  266. emitcall('FPC_POPSECONDOBJECTSTACK');
  267. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  268. emit_reg(A_PUSH,S_L,R_EAX);
  269. emitcall('FPC_DESTROYEXCEPTION');
  270. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  271. { we don't need to restore esi here because reraise never }
  272. { returns }
  273. emitcall('FPC_RERAISE');
  274. emitlab(doobjectdestroy);
  275. cleanupobjectstack;
  276. emitjmp(C_None,endexceptlabel);
  277. end
  278. else
  279. begin
  280. emitcall('FPC_RERAISE');
  281. exceptflowcontrol:=flowcontrol;
  282. end;
  283. if fc_exit in exceptflowcontrol then
  284. begin
  285. { do some magic for exit in the try block }
  286. emitlab(exitexceptlabel);
  287. { we must also destroy the address frame which guards }
  288. { exception object }
  289. cleanupaddrstack;
  290. cleanupobjectstack;
  291. emitjmp(C_None,oldaktexitlabel);
  292. end;
  293. if fc_break in exceptflowcontrol then
  294. begin
  295. emitlab(breakexceptlabel);
  296. { we must also destroy the address frame which guards }
  297. { exception object }
  298. cleanupaddrstack;
  299. cleanupobjectstack;
  300. emitjmp(C_None,oldaktbreaklabel);
  301. end;
  302. if fc_continue in exceptflowcontrol then
  303. begin
  304. emitlab(continueexceptlabel);
  305. { we must also destroy the address frame which guards }
  306. { exception object }
  307. cleanupaddrstack;
  308. cleanupobjectstack;
  309. emitjmp(C_None,oldaktcontinuelabel);
  310. end;
  311. if fc_exit in tryflowcontrol then
  312. begin
  313. { do some magic for exit in the try block }
  314. emitlab(exittrylabel);
  315. cleanupaddrstack;
  316. emitjmp(C_None,oldaktexitlabel);
  317. end;
  318. if fc_break in tryflowcontrol then
  319. begin
  320. emitlab(breaktrylabel);
  321. cleanupaddrstack;
  322. emitjmp(C_None,oldaktbreaklabel);
  323. end;
  324. if fc_continue in tryflowcontrol then
  325. begin
  326. emitlab(continuetrylabel);
  327. cleanupaddrstack;
  328. emitjmp(C_None,oldaktcontinuelabel);
  329. end;
  330. emitlab(endexceptlabel);
  331. errorexit:
  332. { restore all saved labels }
  333. endexceptlabel:=oldendexceptlabel;
  334. { restore the control flow labels }
  335. aktexitlabel:=oldaktexitlabel;
  336. aktexit2label:=oldaktexit2label;
  337. if assigned(oldaktbreaklabel) then
  338. begin
  339. aktcontinuelabel:=oldaktcontinuelabel;
  340. aktbreaklabel:=oldaktbreaklabel;
  341. end;
  342. { return all used control flow statements }
  343. flowcontrol:=oldflowcontrol+exceptflowcontrol+
  344. tryflowcontrol;
  345. end;
  346. procedure ti386onnode.pass_2;
  347. var
  348. nextonlabel,
  349. exitonlabel,
  350. continueonlabel,
  351. breakonlabel,
  352. oldaktexitlabel,
  353. oldaktexit2label,
  354. oldaktcontinuelabel,
  355. doobjectdestroyandreraise,
  356. doobjectdestroy,
  357. oldaktbreaklabel : tasmlabel;
  358. ref : treference;
  359. oldflowcontrol : tflowcontrol;
  360. tempbuf,tempaddr : treference;
  361. begin
  362. oldflowcontrol:=flowcontrol;
  363. flowcontrol:=[];
  364. getlabel(nextonlabel);
  365. { push the vmt }
  366. emit_sym(A_PUSH,S_L,
  367. newasmsymbol(excepttype.vmt_mangledname));
  368. emitcall('FPC_CATCHES');
  369. { allocate eax }
  370. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  371. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  372. emitjmp(C_E,nextonlabel);
  373. ref.symbol:=nil;
  374. gettempofsizereference(4,ref);
  375. { what a hack ! }
  376. if assigned(exceptsymtable) then
  377. tvarsym(exceptsymtable.symindex.first).address:=ref.offset;
  378. emit_reg_ref(A_MOV,S_L,
  379. R_EAX,newreference(ref));
  380. { deallocate eax }
  381. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  382. { in the case that another exception is risen }
  383. { we've to destroy the old one }
  384. getlabel(doobjectdestroyandreraise);
  385. gettempofsizereferencepersistant(12,tempaddr);
  386. gettempofsizereferencepersistant(24,tempbuf);
  387. emitpushreferenceaddr(tempaddr);
  388. emitpushreferenceaddr(tempbuf);
  389. exprasmList.concat(Taicpu.Op_const(A_PUSH,S_L,1));
  390. emitcall('FPC_PUSHEXCEPTADDR');
  391. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  392. exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
  393. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  394. emitcall('FPC_SETJMP');
  395. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  396. exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
  397. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  398. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  399. emitjmp(C_NE,doobjectdestroyandreraise);
  400. if assigned(right) then
  401. begin
  402. oldaktexitlabel:=aktexitlabel;
  403. oldaktexit2label:=aktexit2label;
  404. getlabel(exitonlabel);
  405. aktexitlabel:=exitonlabel;
  406. aktexit2label:=exitonlabel;
  407. if assigned(aktbreaklabel) then
  408. begin
  409. oldaktcontinuelabel:=aktcontinuelabel;
  410. oldaktbreaklabel:=aktbreaklabel;
  411. getlabel(breakonlabel);
  412. getlabel(continueonlabel);
  413. aktcontinuelabel:=continueonlabel;
  414. aktbreaklabel:=breakonlabel;
  415. end;
  416. { esi is destroyed by FPC_CATCHES }
  417. maybe_loadself;
  418. secondpass(right);
  419. end;
  420. getlabel(doobjectdestroy);
  421. emitlab(doobjectdestroyandreraise);
  422. emitcall('FPC_POPADDRSTACK');
  423. ungetpersistanttempreference(tempaddr);
  424. ungetpersistanttempreference(tempbuf);
  425. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  426. exprasmList.concat(Taicpu.op_reg(A_POP,S_L,R_EAX));
  427. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  428. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  429. emitjmp(C_E,doobjectdestroy);
  430. emitcall('FPC_POPSECONDOBJECTSTACK');
  431. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  432. emit_reg(A_PUSH,S_L,R_EAX);
  433. emitcall('FPC_DESTROYEXCEPTION');
  434. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  435. { we don't need to restore esi here because reraise never }
  436. { returns }
  437. emitcall('FPC_RERAISE');
  438. emitlab(doobjectdestroy);
  439. cleanupobjectstack;
  440. { clear some stuff }
  441. ungetiftemp(ref);
  442. emitjmp(C_None,endexceptlabel);
  443. if assigned(right) then
  444. begin
  445. { special handling for control flow instructions }
  446. if fc_exit in flowcontrol then
  447. begin
  448. { the address and object pop does secondtryexcept }
  449. emitlab(exitonlabel);
  450. emitjmp(C_None,oldaktexitlabel);
  451. end;
  452. if fc_break in flowcontrol then
  453. begin
  454. { the address and object pop does secondtryexcept }
  455. emitlab(breakonlabel);
  456. emitjmp(C_None,oldaktbreaklabel);
  457. end;
  458. if fc_continue in flowcontrol then
  459. begin
  460. { the address and object pop does secondtryexcept }
  461. emitlab(continueonlabel);
  462. emitjmp(C_None,oldaktcontinuelabel);
  463. end;
  464. aktexitlabel:=oldaktexitlabel;
  465. aktexit2label:=oldaktexit2label;
  466. if assigned(oldaktbreaklabel) then
  467. begin
  468. aktcontinuelabel:=oldaktcontinuelabel;
  469. aktbreaklabel:=oldaktbreaklabel;
  470. end;
  471. end;
  472. emitlab(nextonlabel);
  473. flowcontrol:=oldflowcontrol+flowcontrol;
  474. { next on node }
  475. if assigned(left) then
  476. begin
  477. cleartempgen;
  478. secondpass(left);
  479. end;
  480. end;
  481. {*****************************************************************************
  482. SecondTryFinally
  483. *****************************************************************************}
  484. procedure ti386tryfinallynode.pass_2;
  485. var
  486. reraiselabel,
  487. finallylabel,
  488. endfinallylabel,
  489. exitfinallylabel,
  490. continuefinallylabel,
  491. breakfinallylabel,
  492. oldaktexitlabel,
  493. oldaktexit2label,
  494. oldaktcontinuelabel,
  495. oldaktbreaklabel : tasmlabel;
  496. oldflowcontrol,tryflowcontrol : tflowcontrol;
  497. decconst : longint;
  498. tempbuf,tempaddr : treference;
  499. begin
  500. { check if child nodes do a break/continue/exit }
  501. oldflowcontrol:=flowcontrol;
  502. flowcontrol:=[];
  503. { we modify EAX }
  504. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  505. getlabel(finallylabel);
  506. getlabel(endfinallylabel);
  507. getlabel(reraiselabel);
  508. { the finally block must catch break, continue and exit }
  509. { statements }
  510. oldaktexitlabel:=aktexitlabel;
  511. oldaktexit2label:=aktexit2label;
  512. getlabel(exitfinallylabel);
  513. aktexitlabel:=exitfinallylabel;
  514. aktexit2label:=exitfinallylabel;
  515. if assigned(aktbreaklabel) then
  516. begin
  517. oldaktcontinuelabel:=aktcontinuelabel;
  518. oldaktbreaklabel:=aktbreaklabel;
  519. getlabel(breakfinallylabel);
  520. getlabel(continuefinallylabel);
  521. aktcontinuelabel:=continuefinallylabel;
  522. aktbreaklabel:=breakfinallylabel;
  523. end;
  524. gettempofsizereferencepersistant(12,tempaddr);
  525. gettempofsizereferencepersistant(24,tempbuf);
  526. emitpushreferenceaddr(tempaddr);
  527. emitpushreferenceaddr(tempbuf);
  528. push_int(1); { Type of stack-frame must be pushed}
  529. emitcall('FPC_PUSHEXCEPTADDR');
  530. { allocate eax }
  531. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  532. emit_reg(A_PUSH,S_L,R_EAX);
  533. emitcall('FPC_SETJMP');
  534. emit_reg(A_PUSH,S_L,R_EAX);
  535. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  536. { deallocate eax }
  537. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  538. emitjmp(C_NE,finallylabel);
  539. { try code }
  540. if assigned(left) then
  541. begin
  542. secondpass(left);
  543. tryflowcontrol:=flowcontrol;
  544. if codegenerror then
  545. exit;
  546. end;
  547. emitlab(finallylabel);
  548. emitcall('FPC_POPADDRSTACK');
  549. ungetpersistanttempreference(tempaddr);
  550. ungetpersistanttempreference(tempbuf);
  551. { finally code }
  552. flowcontrol:=[];
  553. secondpass(right);
  554. if flowcontrol<>[] then
  555. CGMessage(cg_e_control_flow_outside_finally);
  556. if codegenerror then
  557. exit;
  558. { allocate eax }
  559. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  560. emit_reg(A_POP,S_L,R_EAX);
  561. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  562. emitjmp(C_E,endfinallylabel);
  563. emit_reg(A_DEC,S_L,R_EAX);
  564. emitjmp(C_Z,reraiselabel);
  565. if fc_exit in tryflowcontrol then
  566. begin
  567. emit_reg(A_DEC,S_L,R_EAX);
  568. emitjmp(C_Z,oldaktexitlabel);
  569. decconst:=1;
  570. end
  571. else
  572. decconst:=2;
  573. if fc_break in tryflowcontrol then
  574. begin
  575. emit_const_reg(A_SUB,S_L,decconst,R_EAX);
  576. emitjmp(C_Z,oldaktbreaklabel);
  577. decconst:=1;
  578. end
  579. else
  580. inc(decconst);
  581. if fc_continue in tryflowcontrol then
  582. begin
  583. emit_const_reg(A_SUB,S_L,decconst,R_EAX);
  584. emitjmp(C_Z,oldaktcontinuelabel);
  585. end;
  586. { deallocate eax }
  587. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  588. emitlab(reraiselabel);
  589. emitcall('FPC_RERAISE');
  590. { do some magic for exit,break,continue in the try block }
  591. if fc_exit in tryflowcontrol then
  592. begin
  593. emitlab(exitfinallylabel);
  594. { allocate eax }
  595. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  596. emit_reg(A_POP,S_L,R_EAX);
  597. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  598. emit_const(A_PUSH,S_L,2);
  599. emitjmp(C_NONE,finallylabel);
  600. end;
  601. if fc_break in tryflowcontrol then
  602. begin
  603. emitlab(breakfinallylabel);
  604. { allocate eax }
  605. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  606. emit_reg(A_POP,S_L,R_EAX);
  607. { deallocate eax }
  608. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  609. emit_const(A_PUSH,S_L,3);
  610. emitjmp(C_NONE,finallylabel);
  611. end;
  612. if fc_continue in tryflowcontrol then
  613. begin
  614. emitlab(continuefinallylabel);
  615. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  616. emit_reg(A_POP,S_L,R_EAX);
  617. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  618. emit_const(A_PUSH,S_L,4);
  619. emitjmp(C_NONE,finallylabel);
  620. end;
  621. emitlab(endfinallylabel);
  622. aktexitlabel:=oldaktexitlabel;
  623. aktexit2label:=oldaktexit2label;
  624. if assigned(aktbreaklabel) then
  625. begin
  626. aktcontinuelabel:=oldaktcontinuelabel;
  627. aktbreaklabel:=oldaktbreaklabel;
  628. end;
  629. flowcontrol:=oldflowcontrol+tryflowcontrol;
  630. end;
  631. {*****************************************************************************
  632. SecondFail
  633. *****************************************************************************}
  634. procedure ti386failnode.pass_2;
  635. begin
  636. emitjmp(C_None,faillabel);
  637. end;
  638. begin
  639. craisenode:=ti386raisenode;
  640. ctryexceptnode:=ti386tryexceptnode;
  641. ctryfinallynode:=ti386tryfinallynode;
  642. connode:=ti386onnode;
  643. cfailnode:=ti386failnode;
  644. end.
  645. {
  646. $Log$
  647. Revision 1.19 2001-12-29 15:29:58 jonas
  648. * powerpc/cgcpu.pas compiles :)
  649. * several powerpc-related fixes
  650. * cpuasm unit is now based on common tainst unit
  651. + nppcmat unit for powerpc (almost complete)
  652. Revision 1.17 2001/09/29 21:34:04 jonas
  653. - removed unused code (replaced by processor independent code)
  654. Revision 1.16 2001/09/28 20:39:33 jonas
  655. * changed all flow control structures (except for exception handling
  656. related things) to processor independent code (in new ncgflw unit)
  657. + generic cgobj unit which contains lots of code generator helpers with
  658. global "cg" class instance variable
  659. + cgcpu unit for i386 (implements processor specific routines of the above
  660. unit)
  661. * updated cgbase and cpubase for the new code generator units
  662. * include ncgflw unit in cpunode unit
  663. Revision 1.15 2001/08/26 13:36:58 florian
  664. * some cg reorganisation
  665. * some PPC updates
  666. Revision 1.14 2001/08/06 21:40:50 peter
  667. * funcret moved from tprocinfo to tprocdef
  668. Revision 1.13 2001/07/01 20:16:20 peter
  669. * alignmentinfo record added
  670. * -Oa argument supports more alignment settings that can be specified
  671. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  672. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  673. required alignment and the maximum usefull alignment. The final
  674. alignment will be choosen per variable size dependent on these
  675. settings
  676. Revision 1.12 2001/04/15 09:48:31 peter
  677. * fixed crash in labelnode
  678. * easier detection of goto and label in try blocks
  679. Revision 1.11 2001/04/14 14:07:11 peter
  680. * moved more code from pass_1 to det_resulttype
  681. Revision 1.10 2001/04/13 01:22:19 peter
  682. * symtable change to classes
  683. * range check generation and errors fixed, make cycle DEBUG=1 works
  684. * memory leaks fixed
  685. Revision 1.9 2001/04/02 21:20:37 peter
  686. * resulttype rewrite
  687. Revision 1.8 2001/01/27 21:29:35 florian
  688. * behavior -Oa optimized
  689. Revision 1.7 2001/01/06 23:35:05 jonas
  690. * fixed webbug 1323
  691. Revision 1.6 2001/01/05 17:36:58 florian
  692. * the info about exception frames is stored now on the stack
  693. instead on the heap
  694. Revision 1.5 2000/12/25 00:07:32 peter
  695. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  696. tlinkedlist objects)
  697. Revision 1.4 2000/12/05 11:44:33 jonas
  698. + new integer regvar handling, should be much more efficient
  699. Revision 1.3 2000/11/29 00:30:47 florian
  700. * unused units removed from uses clause
  701. * some changes for widestrings
  702. Revision 1.2 2000/10/31 22:02:56 peter
  703. * symtable splitted, no real code changes
  704. Revision 1.1 2000/10/15 09:33:31 peter
  705. * moved n386*.pas to i386/ cpu_target dir
  706. Revision 1.1 2000/10/14 10:14:48 peter
  707. * moehrendorf oct 2000 rewrite
  708. }