n386flw.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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. 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.18 2001-09-30 16:16:28 jonas
  648. - removed unused units form uses-clause and unused local vars
  649. Revision 1.17 2001/09/29 21:34:04 jonas
  650. - removed unused code (replaced by processor independent code)
  651. Revision 1.16 2001/09/28 20:39:33 jonas
  652. * changed all flow control structures (except for exception handling
  653. related things) to processor independent code (in new ncgflw unit)
  654. + generic cgobj unit which contains lots of code generator helpers with
  655. global "cg" class instance variable
  656. + cgcpu unit for i386 (implements processor specific routines of the above
  657. unit)
  658. * updated cgbase and cpubase for the new code generator units
  659. * include ncgflw unit in cpunode unit
  660. Revision 1.15 2001/08/26 13:36:58 florian
  661. * some cg reorganisation
  662. * some PPC updates
  663. Revision 1.14 2001/08/06 21:40:50 peter
  664. * funcret moved from tprocinfo to tprocdef
  665. Revision 1.13 2001/07/01 20:16:20 peter
  666. * alignmentinfo record added
  667. * -Oa argument supports more alignment settings that can be specified
  668. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  669. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  670. required alignment and the maximum usefull alignment. The final
  671. alignment will be choosen per variable size dependent on these
  672. settings
  673. Revision 1.12 2001/04/15 09:48:31 peter
  674. * fixed crash in labelnode
  675. * easier detection of goto and label in try blocks
  676. Revision 1.11 2001/04/14 14:07:11 peter
  677. * moved more code from pass_1 to det_resulttype
  678. Revision 1.10 2001/04/13 01:22:19 peter
  679. * symtable change to classes
  680. * range check generation and errors fixed, make cycle DEBUG=1 works
  681. * memory leaks fixed
  682. Revision 1.9 2001/04/02 21:20:37 peter
  683. * resulttype rewrite
  684. Revision 1.8 2001/01/27 21:29:35 florian
  685. * behavior -Oa optimized
  686. Revision 1.7 2001/01/06 23:35:05 jonas
  687. * fixed webbug 1323
  688. Revision 1.6 2001/01/05 17:36:58 florian
  689. * the info about exception frames is stored now on the stack
  690. instead on the heap
  691. Revision 1.5 2000/12/25 00:07:32 peter
  692. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  693. tlinkedlist objects)
  694. Revision 1.4 2000/12/05 11:44:33 jonas
  695. + new integer regvar handling, should be much more efficient
  696. Revision 1.3 2000/11/29 00:30:47 florian
  697. * unused units removed from uses clause
  698. * some changes for widestrings
  699. Revision 1.2 2000/10/31 22:02:56 peter
  700. * symtable splitted, no real code changes
  701. Revision 1.1 2000/10/15 09:33:31 peter
  702. * moved n386*.pas to i386/ cpu_target dir
  703. Revision 1.1 2000/10/14 10:14:48 peter
  704. * moehrendorf oct 2000 rewrite
  705. }