n386flw.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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 fpcdefs.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. implementation
  37. uses
  38. verbose,systems,
  39. symsym,aasmbase,aasmtai,aasmcpu,
  40. cgbase,pass_2,
  41. cpuinfo,cpubase,paramgr,
  42. nld,ncon,
  43. cga,cgobj,tgobj,rgobj;
  44. {*****************************************************************************
  45. SecondRaise
  46. *****************************************************************************}
  47. procedure ti386raisenode.pass_2;
  48. var
  49. a : tasmlabel;
  50. begin
  51. if assigned(left) then
  52. begin
  53. { multiple parameters? }
  54. if assigned(right) then
  55. begin
  56. { push frame }
  57. if assigned(frametree) then
  58. begin
  59. secondpass(frametree);
  60. if codegenerror then
  61. exit;
  62. cg.a_param_loc(exprasmlist,frametree.location,paramanager.getintparaloc(2));
  63. end
  64. else
  65. cg.a_param_const(exprasmlist,OS_INT,0,paramanager.getintparaloc(2));
  66. { push address }
  67. secondpass(right);
  68. if codegenerror then
  69. exit;
  70. cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(1));
  71. end
  72. else
  73. begin
  74. objectlibrary.getaddrlabel(a);
  75. cg.a_label(exprasmlist,a);
  76. cg.a_param_reg(exprasmlist,OS_INT,R_EBP,paramanager.getintparaloc(2));
  77. emit_sym(A_PUSH,S_L,a);
  78. end;
  79. { push object }
  80. secondpass(left);
  81. if codegenerror then
  82. exit;
  83. cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(1));
  84. cg.a_call_name(exprasmlist,'FPC_RAISEEXCEPTION');
  85. end
  86. else
  87. begin
  88. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  89. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  90. end;
  91. end;
  92. {*****************************************************************************
  93. SecondTryExcept
  94. *****************************************************************************}
  95. var
  96. endexceptlabel : tasmlabel;
  97. { does the necessary things to clean up the object stack }
  98. { in the except block }
  99. procedure cleanupobjectstack;
  100. begin
  101. cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK');
  102. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  103. emit_reg(A_PUSH,S_L,R_EAX);
  104. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  105. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  106. cg.g_maybe_loadself(exprasmlist);
  107. end;
  108. { pops one element from the exception address stack }
  109. { and removes the flag }
  110. procedure cleanupaddrstack;
  111. begin
  112. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  113. { allocate eax }
  114. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  115. emit_reg(A_POP,S_L,R_EAX);
  116. { deallocate eax }
  117. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  118. end;
  119. procedure ti386tryexceptnode.pass_2;
  120. var
  121. exceptlabel,doexceptlabel,oldendexceptlabel,
  122. lastonlabel,
  123. exitexceptlabel,
  124. continueexceptlabel,
  125. breakexceptlabel,
  126. exittrylabel,
  127. continuetrylabel,
  128. breaktrylabel,
  129. doobjectdestroy,
  130. doobjectdestroyandreraise,
  131. oldaktexitlabel,
  132. oldaktexit2label,
  133. oldaktcontinuelabel,
  134. oldaktbreaklabel : tasmlabel;
  135. oldflowcontrol,tryflowcontrol,
  136. exceptflowcontrol : tflowcontrol;
  137. tempbuf,tempaddr : treference;
  138. label
  139. errorexit;
  140. begin
  141. oldflowcontrol:=flowcontrol;
  142. flowcontrol:=[];
  143. { this can be called recursivly }
  144. oldendexceptlabel:=endexceptlabel;
  145. { we modify EAX }
  146. include(rg.usedinproc,R_EAX);
  147. { save the old labels for control flow statements }
  148. oldaktexitlabel:=aktexitlabel;
  149. oldaktexit2label:=aktexit2label;
  150. if assigned(aktbreaklabel) then
  151. begin
  152. oldaktcontinuelabel:=aktcontinuelabel;
  153. oldaktbreaklabel:=aktbreaklabel;
  154. end;
  155. { get new labels for the control flow statements }
  156. objectlibrary.getlabel(exittrylabel);
  157. objectlibrary.getlabel(exitexceptlabel);
  158. if assigned(aktbreaklabel) then
  159. begin
  160. objectlibrary.getlabel(breaktrylabel);
  161. objectlibrary.getlabel(continuetrylabel);
  162. objectlibrary.getlabel(breakexceptlabel);
  163. objectlibrary.getlabel(continueexceptlabel);
  164. end;
  165. objectlibrary.getlabel(exceptlabel);
  166. objectlibrary.getlabel(doexceptlabel);
  167. objectlibrary.getlabel(endexceptlabel);
  168. objectlibrary.getlabel(lastonlabel);
  169. tg.GetTemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
  170. tg.GetTemp(exprasmlist,12,tt_persistant,tempaddr);
  171. cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
  172. cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
  173. { push type of exceptionframe }
  174. cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
  175. cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
  176. { allocate eax }
  177. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  178. emit_reg(A_PUSH,S_L,R_EAX);
  179. cg.a_call_name(exprasmlist,'FPC_SETJMP');
  180. emit_reg(A_PUSH,S_L,R_EAX);
  181. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  182. { deallocate eax }
  183. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  184. emitjmp(C_NE,exceptlabel);
  185. { try block }
  186. { set control flow labels for the try block }
  187. aktexitlabel:=exittrylabel;
  188. aktexit2label:=exittrylabel;
  189. if assigned(oldaktbreaklabel) then
  190. begin
  191. aktcontinuelabel:=continuetrylabel;
  192. aktbreaklabel:=breaktrylabel;
  193. end;
  194. flowcontrol:=[];
  195. secondpass(left);
  196. tryflowcontrol:=flowcontrol;
  197. if codegenerror then
  198. goto errorexit;
  199. cg.a_label(exprasmlist,exceptlabel);
  200. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  201. tg.UnGetTemp(exprasmlist,tempaddr);
  202. tg.UnGetTemp(exprasmlist,tempbuf);
  203. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  204. emit_reg(A_POP,S_L,R_EAX);
  205. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  206. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  207. emitjmp(C_E,endexceptlabel);
  208. cg.a_label(exprasmlist,doexceptlabel);
  209. { set control flow labels for the except block }
  210. { and the on statements }
  211. aktexitlabel:=exitexceptlabel;
  212. aktexit2label:=exitexceptlabel;
  213. if assigned(oldaktbreaklabel) then
  214. begin
  215. aktcontinuelabel:=continueexceptlabel;
  216. aktbreaklabel:=breakexceptlabel;
  217. end;
  218. flowcontrol:=[];
  219. { on statements }
  220. if assigned(right) then
  221. secondpass(right);
  222. cg.a_label(exprasmlist,lastonlabel);
  223. { default handling except handling }
  224. if assigned(t1) then
  225. begin
  226. { FPC_CATCHES must be called with
  227. 'default handler' flag (=-1)
  228. }
  229. cg.a_param_const(exprasmlist,OS_INT,aword(-1),paramanager.getintparaloc(1));
  230. cg.a_call_name(exprasmlist,'FPC_CATCHES');
  231. cg.g_maybe_loadself(exprasmlist);
  232. { the destruction of the exception object must be also }
  233. { guarded by an exception frame }
  234. objectlibrary.getlabel(doobjectdestroy);
  235. objectlibrary.getlabel(doobjectdestroyandreraise);
  236. tg.GetTemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
  237. tg.GetTemp(exprasmlist,12,tt_persistant,tempaddr);
  238. cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
  239. cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
  240. { push type of exceptionframe }
  241. cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
  242. cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
  243. { allocate eax }
  244. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  245. emit_reg(A_PUSH,S_L,R_EAX);
  246. cg.a_call_name(exprasmlist,'FPC_SETJMP');
  247. emit_reg(A_PUSH,S_L,R_EAX);
  248. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  249. { deallocate eax }
  250. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  251. emitjmp(C_NE,exceptlabel);
  252. { here we don't have to reset flowcontrol }
  253. { the default and on flowcontrols are handled equal }
  254. secondpass(t1);
  255. exceptflowcontrol:=flowcontrol;
  256. cg.a_label(exprasmlist,doobjectdestroyandreraise);
  257. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  258. tg.Ungettemp(exprasmlist,tempaddr);
  259. tg.Ungettemp(exprasmlist,tempbuf);
  260. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  261. exprasmList.concat(Taicpu.op_reg(A_POP,S_L,R_EAX));
  262. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  263. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  264. emitjmp(C_E,doobjectdestroy);
  265. cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
  266. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  267. emit_reg(A_PUSH,S_L,R_EAX);
  268. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  269. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  270. { we don't need to restore esi here because reraise never }
  271. { returns }
  272. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  273. cg.a_label(exprasmlist,doobjectdestroy);
  274. cleanupobjectstack;
  275. cg.a_jmp_always(exprasmlist,endexceptlabel);
  276. end
  277. else
  278. begin
  279. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  280. exceptflowcontrol:=flowcontrol;
  281. end;
  282. if fc_exit in exceptflowcontrol then
  283. begin
  284. { do some magic for exit in the try block }
  285. cg.a_label(exprasmlist,exitexceptlabel);
  286. { we must also destroy the address frame which guards }
  287. { exception object }
  288. cleanupaddrstack;
  289. cleanupobjectstack;
  290. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  291. end;
  292. if fc_break in exceptflowcontrol then
  293. begin
  294. cg.a_label(exprasmlist,breakexceptlabel);
  295. { we must also destroy the address frame which guards }
  296. { exception object }
  297. cleanupaddrstack;
  298. cleanupobjectstack;
  299. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  300. end;
  301. if fc_continue in exceptflowcontrol then
  302. begin
  303. cg.a_label(exprasmlist,continueexceptlabel);
  304. { we must also destroy the address frame which guards }
  305. { exception object }
  306. cleanupaddrstack;
  307. cleanupobjectstack;
  308. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  309. end;
  310. if fc_exit in tryflowcontrol then
  311. begin
  312. { do some magic for exit in the try block }
  313. cg.a_label(exprasmlist,exittrylabel);
  314. cleanupaddrstack;
  315. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  316. end;
  317. if fc_break in tryflowcontrol then
  318. begin
  319. cg.a_label(exprasmlist,breaktrylabel);
  320. cleanupaddrstack;
  321. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  322. end;
  323. if fc_continue in tryflowcontrol then
  324. begin
  325. cg.a_label(exprasmlist,continuetrylabel);
  326. cleanupaddrstack;
  327. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  328. end;
  329. cg.a_label(exprasmlist,endexceptlabel);
  330. errorexit:
  331. { restore all saved labels }
  332. endexceptlabel:=oldendexceptlabel;
  333. { restore the control flow labels }
  334. aktexitlabel:=oldaktexitlabel;
  335. aktexit2label:=oldaktexit2label;
  336. if assigned(oldaktbreaklabel) then
  337. begin
  338. aktcontinuelabel:=oldaktcontinuelabel;
  339. aktbreaklabel:=oldaktbreaklabel;
  340. end;
  341. { return all used control flow statements }
  342. flowcontrol:=oldflowcontrol+exceptflowcontrol+
  343. tryflowcontrol;
  344. end;
  345. procedure ti386onnode.pass_2;
  346. var
  347. nextonlabel,
  348. exitonlabel,
  349. continueonlabel,
  350. breakonlabel,
  351. oldaktexitlabel,
  352. oldaktexit2label,
  353. oldaktcontinuelabel,
  354. doobjectdestroyandreraise,
  355. doobjectdestroy,
  356. oldaktbreaklabel : tasmlabel;
  357. ref : treference;
  358. oldflowcontrol : tflowcontrol;
  359. tempbuf,tempaddr : treference;
  360. begin
  361. oldflowcontrol:=flowcontrol;
  362. flowcontrol:=[];
  363. objectlibrary.getlabel(nextonlabel);
  364. { push the vmt }
  365. emit_sym(A_PUSH,S_L,
  366. objectlibrary.newasmsymbol(excepttype.vmt_mangledname));
  367. cg.a_call_name(exprasmlist,'FPC_CATCHES');
  368. { allocate eax }
  369. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  370. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  371. emitjmp(C_E,nextonlabel);
  372. ref.symbol:=nil;
  373. tg.GetTemp(exprasmlist,4,tt_normal,ref);
  374. { what a hack ! }
  375. if assigned(exceptsymtable) then
  376. tvarsym(exceptsymtable.symindex.first).address:=ref.offset;
  377. emit_reg_ref(A_MOV,S_L,R_EAX,ref);
  378. { deallocate eax }
  379. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  380. { in the case that another exception is risen }
  381. { we've to destroy the old one }
  382. objectlibrary.getlabel(doobjectdestroyandreraise);
  383. tg.GetTemp(exprasmlist,12,tt_persistant,tempaddr);
  384. tg.GetTemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
  385. cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
  386. cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
  387. cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
  388. cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
  389. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  390. exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
  391. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  392. cg.a_call_name(exprasmlist,'FPC_SETJMP');
  393. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  394. exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
  395. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  396. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  397. emitjmp(C_NE,doobjectdestroyandreraise);
  398. if assigned(right) then
  399. begin
  400. oldaktexitlabel:=aktexitlabel;
  401. oldaktexit2label:=aktexit2label;
  402. objectlibrary.getlabel(exitonlabel);
  403. aktexitlabel:=exitonlabel;
  404. aktexit2label:=exitonlabel;
  405. if assigned(aktbreaklabel) then
  406. begin
  407. oldaktcontinuelabel:=aktcontinuelabel;
  408. oldaktbreaklabel:=aktbreaklabel;
  409. objectlibrary.getlabel(breakonlabel);
  410. objectlibrary.getlabel(continueonlabel);
  411. aktcontinuelabel:=continueonlabel;
  412. aktbreaklabel:=breakonlabel;
  413. end;
  414. { esi is destroyed by FPC_CATCHES }
  415. cg.g_maybe_loadself(exprasmlist);
  416. secondpass(right);
  417. end;
  418. objectlibrary.getlabel(doobjectdestroy);
  419. cg.a_label(exprasmlist,doobjectdestroyandreraise);
  420. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  421. tg.Ungettemp(exprasmlist,tempaddr);
  422. tg.Ungettemp(exprasmlist,tempbuf);
  423. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  424. exprasmList.concat(Taicpu.op_reg(A_POP,S_L,R_EAX));
  425. exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
  426. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  427. emitjmp(C_E,doobjectdestroy);
  428. cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
  429. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  430. emit_reg(A_PUSH,S_L,R_EAX);
  431. cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
  432. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  433. { we don't need to restore esi here because reraise never }
  434. { returns }
  435. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  436. cg.a_label(exprasmlist,doobjectdestroy);
  437. cleanupobjectstack;
  438. { clear some stuff }
  439. tg.ungetiftemp(exprasmlist,ref);
  440. cg.a_jmp_always(exprasmlist,endexceptlabel);
  441. if assigned(right) then
  442. begin
  443. { special handling for control flow instructions }
  444. if fc_exit in flowcontrol then
  445. begin
  446. { the address and object pop does secondtryexcept }
  447. cg.a_label(exprasmlist,exitonlabel);
  448. cg.a_jmp_always(exprasmlist,oldaktexitlabel);
  449. end;
  450. if fc_break in flowcontrol then
  451. begin
  452. { the address and object pop does secondtryexcept }
  453. cg.a_label(exprasmlist,breakonlabel);
  454. cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
  455. end;
  456. if fc_continue in flowcontrol then
  457. begin
  458. { the address and object pop does secondtryexcept }
  459. cg.a_label(exprasmlist,continueonlabel);
  460. cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
  461. end;
  462. aktexitlabel:=oldaktexitlabel;
  463. aktexit2label:=oldaktexit2label;
  464. if assigned(oldaktbreaklabel) then
  465. begin
  466. aktcontinuelabel:=oldaktcontinuelabel;
  467. aktbreaklabel:=oldaktbreaklabel;
  468. end;
  469. end;
  470. cg.a_label(exprasmlist,nextonlabel);
  471. flowcontrol:=oldflowcontrol+flowcontrol;
  472. { next on node }
  473. if assigned(left) then
  474. begin
  475. rg.cleartempgen;
  476. secondpass(left);
  477. end;
  478. end;
  479. {*****************************************************************************
  480. SecondTryFinally
  481. *****************************************************************************}
  482. procedure ti386tryfinallynode.pass_2;
  483. var
  484. reraiselabel,
  485. finallylabel,
  486. endfinallylabel,
  487. exitfinallylabel,
  488. continuefinallylabel,
  489. breakfinallylabel,
  490. oldaktexitlabel,
  491. oldaktexit2label,
  492. oldaktcontinuelabel,
  493. oldaktbreaklabel : tasmlabel;
  494. oldflowcontrol,tryflowcontrol : tflowcontrol;
  495. decconst : longint;
  496. tempbuf,tempaddr : treference;
  497. begin
  498. { check if child nodes do a break/continue/exit }
  499. oldflowcontrol:=flowcontrol;
  500. flowcontrol:=[];
  501. { we modify EAX }
  502. include(rg.usedinproc,R_EAX);
  503. objectlibrary.getlabel(finallylabel);
  504. objectlibrary.getlabel(endfinallylabel);
  505. objectlibrary.getlabel(reraiselabel);
  506. { the finally block must catch break, continue and exit }
  507. { statements }
  508. oldaktexitlabel:=aktexitlabel;
  509. oldaktexit2label:=aktexit2label;
  510. objectlibrary.getlabel(exitfinallylabel);
  511. aktexitlabel:=exitfinallylabel;
  512. aktexit2label:=exitfinallylabel;
  513. if assigned(aktbreaklabel) then
  514. begin
  515. oldaktcontinuelabel:=aktcontinuelabel;
  516. oldaktbreaklabel:=aktbreaklabel;
  517. objectlibrary.getlabel(breakfinallylabel);
  518. objectlibrary.getlabel(continuefinallylabel);
  519. aktcontinuelabel:=continuefinallylabel;
  520. aktbreaklabel:=breakfinallylabel;
  521. end;
  522. tg.Gettemp(exprasmlist,12,tt_persistant,tempaddr);
  523. tg.Gettemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
  524. cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
  525. cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
  526. { Type of stack-frame must be pushed}
  527. cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
  528. cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
  529. { allocate eax }
  530. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  531. emit_reg(A_PUSH,S_L,R_EAX);
  532. cg.a_call_name(exprasmlist,'FPC_SETJMP');
  533. emit_reg(A_PUSH,S_L,R_EAX);
  534. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  535. { deallocate eax }
  536. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  537. emitjmp(C_NE,finallylabel);
  538. { try code }
  539. if assigned(left) then
  540. begin
  541. secondpass(left);
  542. tryflowcontrol:=flowcontrol;
  543. if codegenerror then
  544. exit;
  545. end;
  546. cg.a_label(exprasmlist,finallylabel);
  547. cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
  548. tg.Ungettemp(exprasmlist,tempaddr);
  549. tg.Ungettemp(exprasmlist,tempbuf);
  550. { finally code }
  551. flowcontrol:=[];
  552. secondpass(right);
  553. if flowcontrol<>[] then
  554. CGMessage(cg_e_control_flow_outside_finally);
  555. if codegenerror then
  556. exit;
  557. { allocate eax }
  558. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  559. emit_reg(A_POP,S_L,R_EAX);
  560. emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
  561. emitjmp(C_E,endfinallylabel);
  562. emit_reg(A_DEC,S_L,R_EAX);
  563. emitjmp(C_Z,reraiselabel);
  564. if fc_exit in tryflowcontrol then
  565. begin
  566. emit_reg(A_DEC,S_L,R_EAX);
  567. emitjmp(C_Z,oldaktexitlabel);
  568. decconst:=1;
  569. end
  570. else
  571. decconst:=2;
  572. if fc_break in tryflowcontrol then
  573. begin
  574. emit_const_reg(A_SUB,S_L,decconst,R_EAX);
  575. emitjmp(C_Z,oldaktbreaklabel);
  576. decconst:=1;
  577. end
  578. else
  579. inc(decconst);
  580. if fc_continue in tryflowcontrol then
  581. begin
  582. emit_const_reg(A_SUB,S_L,decconst,R_EAX);
  583. emitjmp(C_Z,oldaktcontinuelabel);
  584. end;
  585. { deallocate eax }
  586. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  587. cg.a_label(exprasmlist,reraiselabel);
  588. cg.a_call_name(exprasmlist,'FPC_RERAISE');
  589. { do some magic for exit,break,continue in the try block }
  590. if fc_exit in tryflowcontrol then
  591. begin
  592. cg.a_label(exprasmlist,exitfinallylabel);
  593. { allocate eax }
  594. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  595. emit_reg(A_POP,S_L,R_EAX);
  596. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  597. emit_const(A_PUSH,S_L,2);
  598. cg.a_jmp_always(exprasmlist,finallylabel);
  599. end;
  600. if fc_break in tryflowcontrol then
  601. begin
  602. cg.a_label(exprasmlist,breakfinallylabel);
  603. { allocate eax }
  604. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  605. emit_reg(A_POP,S_L,R_EAX);
  606. { deallocate eax }
  607. exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
  608. emit_const(A_PUSH,S_L,3);
  609. cg.a_jmp_always(exprasmlist,finallylabel);
  610. end;
  611. if fc_continue in tryflowcontrol then
  612. begin
  613. cg.a_label(exprasmlist,continuefinallylabel);
  614. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  615. emit_reg(A_POP,S_L,R_EAX);
  616. exprasmList.concat(tai_regalloc.Alloc(R_EAX));
  617. emit_const(A_PUSH,S_L,4);
  618. cg.a_jmp_always(exprasmlist,finallylabel);
  619. end;
  620. cg.a_label(exprasmlist,endfinallylabel);
  621. aktexitlabel:=oldaktexitlabel;
  622. aktexit2label:=oldaktexit2label;
  623. if assigned(aktbreaklabel) then
  624. begin
  625. aktcontinuelabel:=oldaktcontinuelabel;
  626. aktbreaklabel:=oldaktbreaklabel;
  627. end;
  628. flowcontrol:=oldflowcontrol+tryflowcontrol;
  629. end;
  630. begin
  631. craisenode:=ti386raisenode;
  632. ctryexceptnode:=ti386tryexceptnode;
  633. ctryfinallynode:=ti386tryfinallynode;
  634. connode:=ti386onnode;
  635. end.
  636. {
  637. $Log$
  638. Revision 1.34 2002-08-23 16:14:49 peter
  639. * tempgen cleanup
  640. * tt_noreuse temp type added that will be used in genentrycode
  641. Revision 1.33 2002/08/15 15:15:55 carl
  642. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  643. * more generic nodes for maths
  644. * several fixes for better m68k support
  645. Revision 1.32 2002/08/11 14:32:30 peter
  646. * renamed current_library to objectlibrary
  647. Revision 1.31 2002/08/11 13:24:17 peter
  648. * saving of asmsymbols in ppu supported
  649. * asmsymbollist global is removed and moved into a new class
  650. tasmlibrarydata that will hold the info of a .a file which
  651. corresponds with a single module. Added librarydata to tmodule
  652. to keep the library info stored for the module. In the future the
  653. objectfiles will also be stored to the tasmlibrarydata class
  654. * all getlabel/newasmsymbol and friends are moved to the new class
  655. Revision 1.30 2002/07/11 14:41:33 florian
  656. * start of the new generic parameter handling
  657. Revision 1.29 2002/07/07 09:52:34 florian
  658. * powerpc target fixed, very simple units can be compiled
  659. * some basic stuff for better callparanode handling, far from being finished
  660. Revision 1.28 2002/07/01 18:46:33 peter
  661. * internal linker
  662. * reorganized aasm layer
  663. Revision 1.27 2002/05/20 13:30:41 carl
  664. * bugfix of hdisponen (base must be set, not index)
  665. * more portability fixes
  666. Revision 1.26 2002/05/18 13:34:25 peter
  667. * readded missing revisions
  668. Revision 1.25 2002/05/16 19:46:51 carl
  669. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  670. + try to fix temp allocation (still in ifdef)
  671. + generic constructor calls
  672. + start of tassembler / tmodulebase class cleanup
  673. Revision 1.23 2002/05/12 16:53:17 peter
  674. * moved entry and exitcode to ncgutil and cgobj
  675. * foreach gets extra argument for passing local data to the
  676. iterator function
  677. * -CR checks also class typecasts at runtime by changing them
  678. into as
  679. * fixed compiler to cycle with the -CR option
  680. * fixed stabs with elf writer, finally the global variables can
  681. be watched
  682. * removed a lot of routines from cga unit and replaced them by
  683. calls to cgobj
  684. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  685. u32bit then the other is typecasted also to u32bit without giving
  686. a rangecheck warning/error.
  687. * fixed pascal calling method with reversing also the high tree in
  688. the parast, detected by tcalcst3 test
  689. Revision 1.22 2002/04/04 19:06:11 peter
  690. * removed unused units
  691. * use tlocation.size in cg.a_*loc*() routines
  692. Revision 1.21 2002/04/02 17:11:36 peter
  693. * tlocation,treference update
  694. * LOC_CONSTANT added for better constant handling
  695. * secondadd splitted in multiple routines
  696. * location_force_reg added for loading a location to a register
  697. of a specified size
  698. * secondassignment parses now first the right and then the left node
  699. (this is compatible with Kylix). This saves a lot of push/pop especially
  700. with string operations
  701. * adapted some routines to use the new cg methods
  702. Revision 1.20 2002/03/31 20:26:38 jonas
  703. + a_loadfpu_* and a_loadmm_* methods in tcg
  704. * register allocation is now handled by a class and is mostly processor
  705. independent (+rgobj.pas and i386/rgcpu.pas)
  706. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  707. * some small improvements and fixes to the optimizer
  708. * some register allocation fixes
  709. * some fpuvaroffset fixes in the unary minus node
  710. * push/popusedregisters is now called rg.save/restoreusedregisters and
  711. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  712. also better optimizable)
  713. * fixed and optimized register saving/restoring for new/dispose nodes
  714. * LOC_FPU locations now also require their "register" field to be set to
  715. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  716. - list field removed of the tnode class because it's not used currently
  717. and can cause hard-to-find bugs
  718. }