ncgflw.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for nodes that influence the flow which are
  4. the same for all (most?) processors
  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 ncgflw;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. symtype,symdef,
  24. aasmbase,aasmdata,
  25. node,nflw,
  26. pass_2,cgbase,cgutils,ncgutil,cgexcept;
  27. type
  28. tcgwhilerepeatnode = class(twhilerepeatnode)
  29. usedregvars: tusedregvars;
  30. procedure pass_generate_code;override;
  31. procedure sync_regvars(checkusedregvars: boolean);
  32. end;
  33. tcgifnode = class(tifnode)
  34. procedure pass_generate_code;override;
  35. end;
  36. tcgfornode = class(tfornode)
  37. procedure pass_generate_code;override;
  38. end;
  39. tcgexitnode = class(texitnode)
  40. procedure pass_generate_code;override;
  41. end;
  42. tcgbreaknode = class(tbreaknode)
  43. procedure pass_generate_code;override;
  44. end;
  45. tcgcontinuenode = class(tcontinuenode)
  46. procedure pass_generate_code;override;
  47. end;
  48. tcggotonode = class(tgotonode)
  49. procedure pass_generate_code;override;
  50. end;
  51. tcglabelnode = class(tlabelnode)
  52. protected
  53. asmlabel : tasmlabel;
  54. public
  55. function getasmlabel : tasmlabel; virtual;
  56. procedure pass_generate_code;override;
  57. end;
  58. tcgraisenode = class(traisenode)
  59. function pass_1: tnode;override;
  60. {$ifndef jvm}
  61. procedure pass_generate_code;override;
  62. {$endif jvm}
  63. end;
  64. tcgtryexceptnode = class(ttryexceptnode)
  65. protected
  66. type
  67. tframetype = (ft_try,ft_except);
  68. procedure emit_jump_out_of_try_except_frame(list: TasmList; frametype: tframetype; const exceptiontate: tcgexceptionstatehandler.texceptionstate; var excepttemps: tcgexceptionstatehandler.texceptiontemps; framelabel, outerlabel: tasmlabel); virtual;
  69. public
  70. procedure pass_generate_code;override;
  71. end;
  72. tcgtryfinallynode = class(ttryfinallynode)
  73. protected
  74. procedure emit_jump_out_of_try_finally_frame(list: TasmList; const reason: byte; const finallycodelabel: tasmlabel; var excepttemps: tcgexceptionstatehandler.texceptiontemps; framelabel: tasmlabel);
  75. function get_jump_out_of_try_finally_frame_label(const finallyexceptionstate: tcgexceptionstatehandler.texceptionstate): tasmlabel;
  76. public
  77. procedure handle_safecall_exception;
  78. procedure pass_generate_code;override;
  79. end;
  80. tcgonnode = class(tonnode)
  81. procedure pass_generate_code;override;
  82. end;
  83. implementation
  84. uses
  85. cutils,
  86. verbose,globals,systems,
  87. symconst,symsym,symtable,aasmtai,aasmcpu,defutil,
  88. procinfo,parabase,
  89. fmodule,
  90. cpubase,
  91. tgobj,paramgr,
  92. cgobj,hlcgobj,nutils
  93. {$ifndef jvm}
  94. ,psabiehpi
  95. {$endif jvm}
  96. ;
  97. {*****************************************************************************
  98. Second_While_RepeatN
  99. *****************************************************************************}
  100. procedure tcgwhilerepeatnode.sync_regvars(checkusedregvars: boolean);
  101. begin
  102. if (cs_opt_regvar in current_settings.optimizerswitches) and
  103. not(pi_has_label in current_procinfo.flags) then
  104. begin
  105. if checkusedregvars then
  106. begin
  107. usedregvars.intregvars.init;
  108. usedregvars.addrregvars.init;
  109. usedregvars.fpuregvars.init;
  110. usedregvars.mmregvars.init;
  111. { we have to synchronise both the regvars used in the loop }
  112. { and the ones in the while/until condition }
  113. get_used_regvars(self,usedregvars);
  114. gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
  115. end
  116. else
  117. begin
  118. gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
  119. usedregvars.intregvars.done;
  120. usedregvars.addrregvars.done;
  121. usedregvars.fpuregvars.done;
  122. usedregvars.mmregvars.done;
  123. end;
  124. end;
  125. end;
  126. procedure tcgwhilerepeatnode.pass_generate_code;
  127. var
  128. lcont,lbreak,lloop,
  129. oldclabel,oldblabel : tasmlabel;
  130. truelabel,falselabel : tasmlabel;
  131. oldflowcontrol : tflowcontrol;
  132. begin
  133. location_reset(location,LOC_VOID,OS_NO);
  134. current_asmdata.getjumplabel(lloop);
  135. current_asmdata.getjumplabel(lcont);
  136. current_asmdata.getjumplabel(lbreak);
  137. { arrange continue and breaklabels: }
  138. oldflowcontrol:=flowcontrol;
  139. oldclabel:=current_procinfo.CurrContinueLabel;
  140. oldblabel:=current_procinfo.CurrBreakLabel;
  141. include(flowcontrol,fc_inflowcontrol);
  142. exclude(flowcontrol,fc_unwind_loop);
  143. sync_regvars(true);
  144. {$ifdef OLDREGVARS}
  145. load_all_regvars(current_asmdata.CurrAsmList);
  146. {$endif OLDREGVARS}
  147. { handling code at the end as it is much more efficient, and makes
  148. while equal to repeat loop, only the end true/false is swapped (PFV) }
  149. if lnf_testatbegin in loopflags then
  150. hlcg.a_jmp_always(current_asmdata.CurrAsmList,lcont);
  151. if not(cs_opt_size in current_settings.optimizerswitches) then
  152. { align loop target, as an unconditional jump is done before,
  153. use jump align which assume that the instructions inserted as alignment are never executed }
  154. current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.jumpalign,current_settings.alignment.jumpalignskipmax));
  155. hlcg.a_label(current_asmdata.CurrAsmList,lloop);
  156. current_procinfo.CurrContinueLabel:=lcont;
  157. current_procinfo.CurrBreakLabel:=lbreak;
  158. if assigned(right) then
  159. secondpass(right);
  160. {$ifdef OLDREGVARS}
  161. load_all_regvars(current_asmdata.CurrAsmList);
  162. {$endif OLDREGVARS}
  163. hlcg.a_label(current_asmdata.CurrAsmList,lcont);
  164. if lnf_checknegate in loopflags then
  165. begin
  166. truelabel:=lbreak;
  167. falselabel:=lloop;
  168. end
  169. else
  170. begin
  171. truelabel:=lloop;
  172. falselabel:=lbreak;
  173. end;
  174. secondpass(left);
  175. hlcg.maketojumpboollabels(current_asmdata.CurrAsmList,left,truelabel,falselabel);
  176. hlcg.a_label(current_asmdata.CurrAsmList,lbreak);
  177. sync_regvars(false);
  178. current_procinfo.CurrContinueLabel:=oldclabel;
  179. current_procinfo.CurrBreakLabel:=oldblabel;
  180. { a break/continue in a while/repeat block can't be seen outside }
  181. flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
  182. end;
  183. {*****************************************************************************
  184. tcgIFNODE
  185. *****************************************************************************}
  186. procedure tcgifnode.pass_generate_code;
  187. var
  188. hl : tasmlabel;
  189. oldflowcontrol: tflowcontrol;
  190. (*
  191. org_regvar_loaded_other,
  192. then_regvar_loaded_other,
  193. else_regvar_loaded_other : regvarother_booleanarray;
  194. org_regvar_loaded_int,
  195. then_regvar_loaded_int,
  196. else_regvar_loaded_int : Tsuperregisterset;
  197. org_list,
  198. then_list,
  199. else_list : TAsmList;
  200. *)
  201. begin
  202. location_reset(location,LOC_VOID,OS_NO);
  203. hl:=nil;
  204. oldflowcontrol := flowcontrol;
  205. include(flowcontrol,fc_inflowcontrol);
  206. secondpass(left);
  207. (*
  208. { save regvars loaded in the beginning so that we can restore them }
  209. { when processing the else-block }
  210. if cs_opt_regvar in current_settings.optimizerswitches then
  211. begin
  212. org_list := current_asmdata.CurrAsmList;
  213. current_asmdata.CurrAsmList := TAsmList.create;
  214. end;
  215. *)
  216. hlcg.maketojumpbool(current_asmdata.CurrAsmList,left);
  217. (*
  218. if cs_opt_regvar in current_settings.optimizerswitches then
  219. begin
  220. org_regvar_loaded_int := rg.regvar_loaded_int;
  221. org_regvar_loaded_other := rg.regvar_loaded_other;
  222. end;
  223. *)
  224. if assigned(right) then
  225. begin
  226. hlcg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
  227. secondpass(right);
  228. end;
  229. { save current asmlist (previous instructions + then-block) and }
  230. { loaded regvar state and create new clean ones }
  231. {
  232. if cs_opt_regvar in current_settings.optimizerswitches then
  233. begin
  234. then_regvar_loaded_int := rg.regvar_loaded_int;
  235. then_regvar_loaded_other := rg.regvar_loaded_other;
  236. rg.regvar_loaded_int := org_regvar_loaded_int;
  237. rg.regvar_loaded_other := org_regvar_loaded_other;
  238. then_list := current_asmdata.CurrAsmList;
  239. current_asmdata.CurrAsmList := TAsmList.create;
  240. end;
  241. }
  242. if assigned(t1) then
  243. begin
  244. if assigned(right) then
  245. begin
  246. current_asmdata.getjumplabel(hl);
  247. { do go back to if line !! }
  248. (*
  249. if not(cs_opt_regvar in current_settings.optimizerswitches) then
  250. *)
  251. current_filepos:=current_asmdata.CurrAsmList.getlasttaifilepos^
  252. (*
  253. else
  254. current_filepos:=then_list.getlasttaifilepos^
  255. *)
  256. ;
  257. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hl);
  258. if not(cs_opt_size in current_settings.optimizerswitches) then
  259. current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.jumpalign,current_settings.alignment.jumpalignskipmax));
  260. end;
  261. hlcg.a_label(current_asmdata.CurrAsmList,left.location.falselabel);
  262. secondpass(t1);
  263. (*
  264. { save current asmlist (previous instructions + else-block) }
  265. { and loaded regvar state and create a new clean list }
  266. if cs_opt_regvar in current_settings.optimizerswitches then
  267. begin
  268. { else_regvar_loaded_int := rg.regvar_loaded_int;
  269. else_regvar_loaded_other := rg.regvar_loaded_other;}
  270. else_list := current_asmdata.CurrAsmList;
  271. current_asmdata.CurrAsmList := TAsmList.create;
  272. end;
  273. *)
  274. if assigned(right) then
  275. hlcg.a_label(current_asmdata.CurrAsmList,hl);
  276. end
  277. else
  278. begin
  279. (*
  280. if cs_opt_regvar in current_settings.optimizerswitches then
  281. begin
  282. { else_regvar_loaded_int := rg.regvar_loaded_int;
  283. else_regvar_loaded_other := rg.regvar_loaded_other;}
  284. else_list := current_asmdata.CurrAsmList;
  285. current_asmdata.CurrAsmList := TAsmList.create;
  286. end;
  287. *)
  288. if not(cs_opt_size in current_settings.optimizerswitches) then
  289. current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.coalescealign,current_settings.alignment.coalescealignskipmax));
  290. hlcg.a_label(current_asmdata.CurrAsmList,left.location.falselabel);
  291. end;
  292. if not(assigned(right)) then
  293. begin
  294. if not(cs_opt_size in current_settings.optimizerswitches) then
  295. current_asmdata.CurrAsmList.concat(cai_align.create_max(current_settings.alignment.coalescealign,current_settings.alignment.coalescealignskipmax));
  296. hlcg.a_label(current_asmdata.CurrAsmList,left.location.truelabel);
  297. end;
  298. (*
  299. if cs_opt_regvar in current_settings.optimizerswitches then
  300. begin
  301. { add loads of regvars at the end of the then- and else-blocks }
  302. { so that at the end of both blocks the same regvars are loaded }
  303. { no else block? }
  304. if not assigned(t1) then
  305. begin
  306. sync_regvars_int(org_list,then_list,org_regvar_loaded_int,then_regvar_loaded_int);
  307. sync_regvars_other(org_list,then_list,org_regvar_loaded_other,then_regvar_loaded_other);
  308. end
  309. { no then block? }
  310. else if not assigned(right) then
  311. begin
  312. sync_regvars_int(org_list,else_list,org_regvar_loaded_int,else_regvar_loaded_int);
  313. sync_regvars_other(org_list,else_list,org_regvar_loaded_other,else_regvar_loaded_other);
  314. end
  315. { both else and then blocks }
  316. else
  317. begin
  318. sync_regvars_int(then_list,else_list,then_regvar_loaded_int,else_regvar_loaded_int);
  319. sync_regvars_other(then_list,else_list,then_regvar_loaded_other,else_regvar_loaded_other);
  320. end;
  321. { add all lists together }
  322. org_list.concatlist(then_list);
  323. then_list.free;
  324. org_list.concatlist(else_list);
  325. else_list.free;
  326. org_list.concatlist(current_asmdata.CurrAsmList);
  327. current_asmdata.CurrAsmList.free;
  328. current_asmdata.CurrAsmList := org_list;
  329. end;
  330. *)
  331. flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
  332. end;
  333. {*****************************************************************************
  334. SecondFor
  335. *****************************************************************************}
  336. procedure tcgfornode.pass_generate_code;
  337. begin
  338. { for nodes are converted in pass_1 in a while loop }
  339. internalerror(2015082501);
  340. end;
  341. {*****************************************************************************
  342. SecondExitN
  343. *****************************************************************************}
  344. procedure tcgexitnode.pass_generate_code;
  345. begin
  346. location_reset(location,LOC_VOID,OS_NO);
  347. include(flowcontrol,fc_exit);
  348. if assigned(left) then
  349. secondpass(left);
  350. if (fc_unwind_exit in flowcontrol) then
  351. hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel)
  352. else
  353. hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
  354. end;
  355. {*****************************************************************************
  356. SecondBreakN
  357. *****************************************************************************}
  358. procedure tcgbreaknode.pass_generate_code;
  359. begin
  360. location_reset(location,LOC_VOID,OS_NO);
  361. include(flowcontrol,fc_break);
  362. if current_procinfo.CurrBreakLabel<>nil then
  363. begin
  364. {$ifdef OLDREGVARS}
  365. load_all_regvars(current_asmdata.CurrAsmList);
  366. {$endif OLDREGVARS}
  367. if (fc_unwind_loop in flowcontrol) then
  368. hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel)
  369. else
  370. hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel)
  371. end
  372. else
  373. CGMessage(cg_e_break_not_allowed);
  374. end;
  375. {*****************************************************************************
  376. SecondContinueN
  377. *****************************************************************************}
  378. procedure tcgcontinuenode.pass_generate_code;
  379. begin
  380. location_reset(location,LOC_VOID,OS_NO);
  381. include(flowcontrol,fc_continue);
  382. if current_procinfo.CurrContinueLabel<>nil then
  383. begin
  384. {$ifdef OLDREGVARS}
  385. load_all_regvars(current_asmdata.CurrAsmList);
  386. {$endif OLDREGVARS}
  387. if (fc_unwind_loop in flowcontrol) then
  388. hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel)
  389. else
  390. hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel)
  391. end
  392. else
  393. CGMessage(cg_e_continue_not_allowed);
  394. end;
  395. {*****************************************************************************
  396. SecondGoto
  397. *****************************************************************************}
  398. procedure tcggotonode.pass_generate_code;
  399. begin
  400. location_reset(location,LOC_VOID,OS_NO);
  401. include(flowcontrol,fc_gotolabel);
  402. {$ifdef OLDREGVARS}
  403. load_all_regvars(current_asmdata.CurrAsmList);
  404. {$endif OLDREGVARS}
  405. hlcg.a_jmp_always(current_asmdata.CurrAsmList,tcglabelnode(labelnode).getasmlabel)
  406. end;
  407. {*****************************************************************************
  408. SecondLabel
  409. *****************************************************************************}
  410. function tcglabelnode.getasmlabel : tasmlabel;
  411. begin
  412. if not(assigned(asmlabel)) then
  413. { labsym is not set in inlined procedures, but since assembler }
  414. { routines can't be inlined, that shouldn't matter }
  415. if assigned(labsym) and
  416. labsym.nonlocal then
  417. current_asmdata.getglobaljumplabel(asmlabel)
  418. else
  419. current_asmdata.getjumplabel(asmlabel);
  420. result:=asmlabel
  421. end;
  422. procedure tcglabelnode.pass_generate_code;
  423. begin
  424. location_reset(location,LOC_VOID,OS_NO);
  425. include(flowcontrol,fc_gotolabel);
  426. {$ifdef OLDREGVARS}
  427. load_all_regvars(current_asmdata.CurrAsmList);
  428. {$endif OLDREGVARS}
  429. hlcg.a_label(current_asmdata.CurrAsmList,getasmlabel);
  430. { Write also extra label if this label was referenced from
  431. assembler block }
  432. if assigned(labsym) and
  433. assigned(labsym.asmblocklabel) then
  434. hlcg.a_label(current_asmdata.CurrAsmList,labsym.asmblocklabel);
  435. secondpass(left);
  436. end;
  437. {*****************************************************************************
  438. SecondTryExcept
  439. *****************************************************************************}
  440. var
  441. endexceptlabel : tasmlabel;
  442. { jump out of an try/except block }
  443. procedure tcgtryexceptnode.emit_jump_out_of_try_except_frame(list: TasmList; frametype: tframetype; const exceptiontate: tcgexceptionstatehandler.texceptionstate; var excepttemps: tcgexceptionstatehandler.texceptiontemps; framelabel, outerlabel: tasmlabel);
  444. begin
  445. hlcg.a_label(list,framelabel);
  446. { we must also destroy the address frame which guards
  447. the exception object }
  448. cexceptionstatehandler.popaddrstack(list);
  449. hlcg.g_exception_reason_discard(list,osuinttype,excepttemps.reasonbuf);
  450. if frametype=ft_except then
  451. begin
  452. cexceptionstatehandler.cleanupobjectstack(list);
  453. cexceptionstatehandler.end_catch(list);
  454. end;
  455. hlcg.a_jmp_always(list,outerlabel);
  456. end;
  457. procedure tcgtryexceptnode.pass_generate_code;
  458. var
  459. oldendexceptlabel,
  460. lastonlabel,
  461. exitexceptlabel,
  462. continueexceptlabel,
  463. breakexceptlabel,
  464. exittrylabel,
  465. continuetrylabel,
  466. breaktrylabel,
  467. oldCurrExitLabel,
  468. oldContinueLabel,
  469. oldBreakLabel : tasmlabel;
  470. destroytemps,
  471. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  472. trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  473. afteronflowcontrol: tflowcontrol;
  474. label
  475. errorexit;
  476. begin
  477. location_reset(location,LOC_VOID,OS_NO);
  478. continuetrylabel:=nil;
  479. breaktrylabel:=nil;
  480. continueexceptlabel:=nil;
  481. breakexceptlabel:=nil;
  482. doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
  483. { this can be called recursivly }
  484. oldBreakLabel:=nil;
  485. oldContinueLabel:=nil;
  486. oldendexceptlabel:=endexceptlabel;
  487. { save the old labels for control flow statements }
  488. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  489. if assigned(current_procinfo.CurrBreakLabel) then
  490. begin
  491. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  492. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  493. end;
  494. { get new labels for the control flow statements }
  495. current_asmdata.getjumplabel(exittrylabel);
  496. current_asmdata.getjumplabel(exitexceptlabel);
  497. if assigned(current_procinfo.CurrBreakLabel) then
  498. begin
  499. current_asmdata.getjumplabel(breaktrylabel);
  500. current_asmdata.getjumplabel(continuetrylabel);
  501. current_asmdata.getjumplabel(breakexceptlabel);
  502. current_asmdata.getjumplabel(continueexceptlabel);
  503. end;
  504. current_asmdata.getjumplabel(endexceptlabel);
  505. current_asmdata.getjumplabel(lastonlabel);
  506. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  507. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate);
  508. { try block }
  509. { set control flow labels for the try block }
  510. current_procinfo.CurrExitLabel:=exittrylabel;
  511. if assigned(oldBreakLabel) then
  512. begin
  513. current_procinfo.CurrContinueLabel:=continuetrylabel;
  514. current_procinfo.CurrBreakLabel:=breaktrylabel;
  515. end;
  516. secondpass(left);
  517. if codegenerror then
  518. goto errorexit;
  519. { don't generate line info for internal cleanup }
  520. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  521. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,endexceptlabel);
  522. cexceptionstatehandler.emit_except_label(current_asmdata.CurrAsmList,tek_except,trystate,excepttemps);
  523. cexceptionstatehandler.free_exception(current_asmdata.CurrAsmList, excepttemps, trystate, 0, endexceptlabel, false);
  524. { end cleanup }
  525. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  526. { set control flow labels for the except block }
  527. { and the on statements }
  528. current_procinfo.CurrExitLabel:=exitexceptlabel;
  529. if assigned(oldBreakLabel) then
  530. begin
  531. current_procinfo.CurrContinueLabel:=continueexceptlabel;
  532. current_procinfo.CurrBreakLabel:=breakexceptlabel;
  533. end;
  534. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  535. { on statements }
  536. if assigned(right) then
  537. secondpass(right);
  538. afteronflowcontrol:=flowcontrol;
  539. { don't generate line info for internal cleanup }
  540. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  541. hlcg.a_label(current_asmdata.CurrAsmList,lastonlabel);
  542. { default handling except handling }
  543. if assigned(t1) then
  544. begin
  545. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  546. it doesn't change any state and its return value is ignored (Sergei)
  547. }
  548. { the destruction of the exception object must be also }
  549. { guarded by an exception frame, but it can be omitted }
  550. { if there's no user code in 'except' block }
  551. cexceptionstatehandler.catch_all_start(current_asmdata.CurrAsmList);
  552. if not (has_no_code(t1)) then
  553. begin
  554. { if there is an outer frame that catches exceptions, remember this for the "except"
  555. part of this try/except }
  556. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  557. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,destroytemps);
  558. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  559. cexceptionstatehandler.catch_all_add(current_asmdata.CurrAsmList);
  560. { the flowcontrol from the default except-block must be merged
  561. with the flowcontrol flags potentially set by the
  562. on-statements handled above (secondpass(right)), as they are
  563. at the same program level }
  564. flowcontrol:=
  565. flowcontrol+
  566. afteronflowcontrol;
  567. { except block needs line info }
  568. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  569. secondpass(t1);
  570. cexceptionstatehandler.handle_nested_exception(current_asmdata.CurrAsmList,destroytemps,doobjectdestroyandreraisestate);
  571. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,destroytemps);
  572. cexceptionstatehandler.catch_all_end(current_asmdata.CurrAsmList);
  573. hlcg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
  574. end
  575. else
  576. begin
  577. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  578. cexceptionstatehandler.cleanupobjectstack(current_asmdata.CurrAsmList);
  579. cexceptionstatehandler.catch_all_end(current_asmdata.CurrAsmList);
  580. hlcg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
  581. end;
  582. end
  583. else
  584. begin
  585. cexceptionstatehandler.handle_reraise(current_asmdata.CurrAsmList,excepttemps,trystate,tek_except);
  586. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  587. end;
  588. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  589. emit_jump_out_of_try_except_frame(current_asmdata.CurrAsmList,ft_except,doobjectdestroyandreraisestate,excepttemps,exitexceptlabel,oldCurrExitLabel);
  590. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  591. emit_jump_out_of_try_except_frame(current_asmdata.CurrAsmList,ft_except,doobjectdestroyandreraisestate,excepttemps,breakexceptlabel,oldBreakLabel);
  592. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  593. emit_jump_out_of_try_except_frame(current_asmdata.CurrAsmList,ft_except,doobjectdestroyandreraisestate,excepttemps,continueexceptlabel,oldContinueLabel);
  594. if fc_exit in trystate.newflowcontrol then
  595. emit_jump_out_of_try_except_frame(current_asmdata.CurrAsmList,ft_try,trystate,excepttemps,exittrylabel,oldCurrExitLabel);
  596. if fc_break in trystate.newflowcontrol then
  597. emit_jump_out_of_try_except_frame(current_asmdata.CurrAsmList,ft_try,trystate,excepttemps,breaktrylabel,oldBreakLabel);
  598. if fc_continue in trystate.newflowcontrol then
  599. emit_jump_out_of_try_except_frame(current_asmdata.CurrAsmList,ft_try,trystate,excepttemps,continuetrylabel,oldContinueLabel);
  600. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  601. hlcg.a_label(current_asmdata.CurrAsmList,endexceptlabel);
  602. { end cleanup }
  603. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  604. errorexit:
  605. { restore all saved labels }
  606. endexceptlabel:=oldendexceptlabel;
  607. { restore the control flow labels }
  608. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  609. if assigned(oldBreakLabel) then
  610. begin
  611. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  612. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  613. end;
  614. { return all used control flow statements }
  615. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  616. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  617. end;
  618. procedure tcgonnode.pass_generate_code;
  619. var
  620. nextonlabel,
  621. exitonlabel,
  622. continueonlabel,
  623. breakonlabel,
  624. oldCurrExitLabel,
  625. oldContinueLabel,
  626. oldBreakLabel : tasmlabel;
  627. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  628. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  629. exceptvarsym : tlocalvarsym;
  630. exceptlocdef: tdef;
  631. exceptlocreg: tregister;
  632. begin
  633. location_reset(location,LOC_VOID,OS_NO);
  634. oldCurrExitLabel:=nil;
  635. continueonlabel:=nil;
  636. breakonlabel:=nil;
  637. exitonlabel:=nil;
  638. current_asmdata.getjumplabel(nextonlabel);
  639. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nextonlabel,exceptlocdef,exceptlocreg);
  640. { Retrieve exception variable }
  641. if assigned(excepTSymtable) then
  642. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  643. else
  644. internalerror(2011020401);
  645. if assigned(exceptvarsym) then
  646. begin
  647. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  648. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  649. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  650. end;
  651. { in the case that another exception is risen
  652. we've to destroy the old one, so create a new
  653. exception frame for the catch-handler }
  654. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  655. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  656. oldBreakLabel:=nil;
  657. oldContinueLabel:=nil;
  658. if assigned(right) then
  659. begin
  660. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  661. current_asmdata.getjumplabel(exitonlabel);
  662. current_procinfo.CurrExitLabel:=exitonlabel;
  663. if assigned(current_procinfo.CurrBreakLabel) then
  664. begin
  665. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  666. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  667. current_asmdata.getjumplabel(breakonlabel);
  668. current_asmdata.getjumplabel(continueonlabel);
  669. current_procinfo.CurrContinueLabel:=continueonlabel;
  670. current_procinfo.CurrBreakLabel:=breakonlabel;
  671. end;
  672. secondpass(right);
  673. end;
  674. cexceptionstatehandler.handle_nested_exception(current_asmdata.CurrAsmList,excepttemps,doobjectdestroyandreraisestate);
  675. { clear some stuff }
  676. if assigned(exceptvarsym) then
  677. begin
  678. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  679. exceptvarsym.localloc.loc:=LOC_INVALID;
  680. end;
  681. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  682. hlcg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
  683. if assigned(right) then
  684. begin
  685. { special handling for control flow instructions }
  686. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  687. begin
  688. { the address and object pop does secondtryexcept }
  689. hlcg.a_label(current_asmdata.CurrAsmList,exitonlabel);
  690. hlcg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
  691. end;
  692. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  693. begin
  694. { the address and object pop does secondtryexcept }
  695. hlcg.a_label(current_asmdata.CurrAsmList,breakonlabel);
  696. hlcg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel);
  697. end;
  698. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  699. begin
  700. { the address and object pop does secondtryexcept }
  701. hlcg.a_label(current_asmdata.CurrAsmList,continueonlabel);
  702. hlcg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel);
  703. end;
  704. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  705. if assigned(oldBreakLabel) then
  706. begin
  707. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  708. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  709. end;
  710. end;
  711. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  712. hlcg.a_label(current_asmdata.CurrAsmList,nextonlabel);
  713. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  714. { propagate exit/break/continue }
  715. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  716. { next on node }
  717. if assigned(left) then
  718. secondpass(left);
  719. end;
  720. {*****************************************************************************
  721. SecondTryFinally
  722. *****************************************************************************}
  723. { jump out of a finally block }
  724. procedure tcgtryfinallynode.emit_jump_out_of_try_finally_frame(list: TasmList; const reason: byte; const finallycodelabel: tasmlabel; var excepttemps: tcgexceptionstatehandler.texceptiontemps; framelabel: tasmlabel);
  725. begin
  726. hlcg.a_label(list,framelabel);
  727. hlcg.g_exception_reason_discard(list,osuinttype,excepttemps.reasonbuf);
  728. hlcg.g_exception_reason_save_const(list,osuinttype,reason,excepttemps.reasonbuf);
  729. hlcg.a_jmp_always(list,finallycodelabel);
  730. end;
  731. function tcgtryfinallynode.get_jump_out_of_try_finally_frame_label(const finallyexceptionstate: tcgexceptionstatehandler.texceptionstate): tasmlabel;
  732. begin
  733. current_asmdata.getjumplabel(result);
  734. end;
  735. procedure tcgtryfinallynode.handle_safecall_exception;
  736. var
  737. cgpara, resultpara: tcgpara;
  738. selfsym: tparavarsym;
  739. pd: tprocdef;
  740. safecallresult: tlocalvarsym;
  741. begin
  742. { call fpc_safecallhandler, passing self for methods of classes,
  743. nil otherwise. }
  744. pd:=search_system_proc('fpc_safecallhandler');
  745. cgpara.init;
  746. paramanager.getintparaloc(current_asmdata.CurrAsmList,pd,1,cgpara);
  747. if is_class(current_procinfo.procdef.struct) then
  748. begin
  749. selfsym:=tparavarsym(current_procinfo.procdef.parast.Find('self'));
  750. if (selfsym=nil) or (selfsym.typ<>paravarsym) then
  751. InternalError(2011123101);
  752. hlcg.a_load_loc_cgpara(current_asmdata.CurrAsmList,selfsym.vardef,selfsym.localloc,cgpara);
  753. end
  754. else
  755. hlcg.a_load_const_cgpara(current_asmdata.CurrAsmList,voidpointertype,0,cgpara);
  756. paramanager.freecgpara(current_asmdata.CurrAsmList,cgpara);
  757. resultpara:=hlcg.g_call_system_proc(current_asmdata.CurrAsmList,pd,[@cgpara],nil);
  758. cgpara.done;
  759. safecallresult:=tlocalvarsym(current_procinfo.procdef.localst.Find('safecallresult'));
  760. hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,resultpara.def,resultpara,safecallresult.localloc,false);
  761. resultpara.resetiftemp;
  762. end;
  763. procedure tcgtryfinallynode.pass_generate_code;
  764. var
  765. endfinallylabel,
  766. exitfinallylabel,
  767. continuefinallylabel,
  768. breakfinallylabel,
  769. oldCurrExitLabel,
  770. oldContinueLabel,
  771. oldBreakLabel,
  772. finallyNoExceptionLabel: tasmlabel;
  773. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  774. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  775. reasonreg : tregister;
  776. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  777. tmplist: TAsmList;
  778. procedure handle_breakcontinueexit(const finallycode: tasmlabel; doreraise: boolean);
  779. begin
  780. { no exception happened, but maybe break/continue/exit }
  781. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,osuinttype,OC_EQ,0,reasonreg,endfinallylabel);
  782. if fc_exit in finallyexceptionstate.newflowcontrol then
  783. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,osuinttype,OC_EQ,2,reasonreg,oldCurrExitLabel);
  784. if fc_break in finallyexceptionstate.newflowcontrol then
  785. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,osuinttype,OC_EQ,3,reasonreg,oldBreakLabel);
  786. if fc_continue in finallyexceptionstate.newflowcontrol then
  787. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,osuinttype,OC_EQ,4,reasonreg,oldContinueLabel);
  788. if doreraise then
  789. cexceptionstatehandler.handle_reraise(current_asmdata.CurrAsmList,excepttemps,finallyexceptionstate,tek_normalfinally)
  790. else
  791. hlcg.g_unreachable(current_asmdata.CurrAsmList);
  792. { redirect break/continue/exit to the label above, with the reasonbuf set appropriately }
  793. if fc_exit in finallyexceptionstate.newflowcontrol then
  794. emit_jump_out_of_try_finally_frame(current_asmdata.CurrAsmList,2,finallycode,excepttemps,exitfinallylabel);
  795. if fc_break in finallyexceptionstate.newflowcontrol then
  796. emit_jump_out_of_try_finally_frame(current_asmdata.CurrAsmList,3,finallycode,excepttemps,breakfinallylabel);
  797. if fc_continue in finallyexceptionstate.newflowcontrol then
  798. emit_jump_out_of_try_finally_frame(current_asmdata.CurrAsmList,4,finallycode,excepttemps,continuefinallylabel);
  799. end;
  800. begin
  801. location_reset(location,LOC_VOID,OS_NO);
  802. oldBreakLabel:=nil;
  803. oldContinueLabel:=nil;
  804. continuefinallylabel:=nil;
  805. breakfinallylabel:=nil;
  806. if not implicitframe then
  807. exceptframekind:=tek_normalfinally
  808. else
  809. exceptframekind:=tek_implicitfinally;
  810. current_asmdata.getjumplabel(endfinallylabel);
  811. { call setjmp, and jump to finally label on non-zero result }
  812. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  813. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  814. { the finally block must catch break, continue and exit }
  815. { statements }
  816. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  817. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  818. current_procinfo.CurrExitLabel:=exitfinallylabel;
  819. if assigned(current_procinfo.CurrBreakLabel) then
  820. begin
  821. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  822. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  823. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  824. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  825. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  826. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  827. end;
  828. { try code }
  829. if assigned(left) then
  830. begin
  831. secondpass(left);
  832. if codegenerror then
  833. exit;
  834. end;
  835. { don't generate line info for internal cleanup }
  836. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  837. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,finallyexceptionstate.finallycodelabel);
  838. if assigned(third) then
  839. begin
  840. tmplist:=TAsmList.create;
  841. { emit the except label already (to a temporary list) to ensure that any calls in the
  842. finally block refer to the outer exception frame rather than to the exception frame
  843. that emits this same finally code in case an exception does happen }
  844. cexceptionstatehandler.emit_except_label(tmplist,exceptframekind,finallyexceptionstate,excepttemps);
  845. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  846. current_asmdata.getjumplabel(finallyNoExceptionLabel);
  847. hlcg.a_label(current_asmdata.CurrAsmList,finallyNoExceptionLabel);
  848. if not implicitframe then
  849. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  850. secondpass(third);
  851. if codegenerror then
  852. exit;
  853. if not implicitframe then
  854. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  855. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,osuinttype);
  856. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,osuinttype,osuinttype,excepttemps.reasonbuf,reasonreg);
  857. handle_breakcontinueexit(finallyNoExceptionLabel,false);
  858. current_asmdata.CurrAsmList.concatList(tmplist);
  859. tmplist.free;
  860. end
  861. else
  862. cexceptionstatehandler.emit_except_label(current_asmdata.CurrAsmList,exceptframekind,finallyexceptionstate,excepttemps);
  863. { just free the frame information }
  864. cexceptionstatehandler.free_exception(current_asmdata.CurrAsmList,excepttemps,finallyexceptionstate,1,finallyexceptionstate.exceptionlabel,true);
  865. { end cleanup }
  866. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  867. { finally code (don't unconditionally set fc_inflowcontrol, since the
  868. finally code is unconditionally executed; we do have to filter out
  869. flags regarding break/contrinue/etc. because we have to give an
  870. error in case one of those is used in the finally-code }
  871. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  872. secondpass(right);
  873. { goto is allowed if it stays inside the finally block,
  874. this is checked using the exception block number }
  875. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  876. CGMessage(cg_e_control_flow_outside_finally);
  877. if codegenerror then
  878. exit;
  879. { don't generate line info for internal cleanup }
  880. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  881. { same level as before try, but this part is only executed if an exception occcurred
  882. -> always fc_in_flowcontrol }
  883. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_catching_exceptions];
  884. include(flowcontrol,fc_inflowcontrol);
  885. if not assigned(third) then
  886. begin
  887. { the value should now be in the exception handler }
  888. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,osuinttype);
  889. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,osuinttype,osuinttype,excepttemps.reasonbuf,reasonreg);
  890. if implicitframe then
  891. begin
  892. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,osuinttype,OC_EQ,0,reasonreg,endfinallylabel);
  893. { finally code only needed to be executed on exception (-> in
  894. if-branch -> fc_inflowcontrol) }
  895. if current_procinfo.procdef.generate_safecall_wrapper then
  896. begin
  897. handle_safecall_exception;
  898. { we have to jump immediatly as we have to return the value of FPC_SAFECALL }
  899. hlcg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
  900. end
  901. else
  902. cexceptionstatehandler.handle_reraise(current_asmdata.CurrAsmList,excepttemps,finallyexceptionstate,exceptframekind);
  903. { we have to load 0 into the execepttemp, else the program thinks an exception happended }
  904. emit_jump_out_of_try_finally_frame(current_asmdata.CurrAsmList,0,finallyexceptionstate.exceptionlabel,excepttemps,exitfinallylabel);
  905. end
  906. else
  907. begin
  908. handle_breakcontinueexit(finallyexceptionstate.exceptionlabel,true);
  909. end;
  910. end
  911. else
  912. begin
  913. if implicitframe then
  914. begin
  915. if current_procinfo.procdef.generate_safecall_wrapper then
  916. handle_safecall_exception
  917. else
  918. cexceptionstatehandler.handle_reraise(current_asmdata.CurrAsmList,excepttemps,finallyexceptionstate,exceptframekind);
  919. end
  920. else
  921. begin
  922. cexceptionstatehandler.handle_reraise(current_asmdata.CurrAsmList,excepttemps,finallyexceptionstate,exceptframekind);
  923. end;
  924. end;
  925. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  926. hlcg.a_label(current_asmdata.CurrAsmList,endfinallylabel);
  927. { end cleanup }
  928. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  929. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  930. if assigned(current_procinfo.CurrBreakLabel) then
  931. begin
  932. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  933. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  934. end;
  935. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  936. end;
  937. function tcgraisenode.pass_1: tnode;
  938. begin
  939. if not(tf_use_psabieh in target_info.flags) or assigned(left) then
  940. result:=inherited
  941. else
  942. begin
  943. expectloc:=LOC_VOID;
  944. result:=nil;
  945. end;
  946. end;
  947. {$ifndef jvm}
  948. { has to be factored out as well }
  949. procedure tcgraisenode.pass_generate_code;
  950. var
  951. CurrentLandingPad, CurrentAction, ReRaiseLandingPad: TPSABIEHAction;
  952. psabiehprocinfo: tpsabiehprocinfo;
  953. begin
  954. if not(tf_use_psabieh in target_info.flags) then
  955. Internalerror(2019021701);
  956. location_reset(location,LOC_VOID,OS_NO);
  957. CurrentLandingPad:=nil;
  958. CurrentAction:=nil;
  959. ReRaiseLandingPad:=nil;
  960. psabiehprocinfo:=current_procinfo as tpsabiehprocinfo;
  961. { a reraise must raise the exception to the parent exception frame }
  962. if fc_catching_exceptions in flowcontrol then
  963. begin
  964. psabiehprocinfo.CreateNewPSABIEHCallsite(current_asmdata.CurrAsmList);
  965. CurrentLandingPad:=psabiehprocinfo.CurrentLandingPad;
  966. if psabiehprocinfo.PopLandingPad(CurrentLandingPad) then
  967. exclude(flowcontrol,fc_catching_exceptions);
  968. CurrentAction:=psabiehprocinfo.CurrentAction;
  969. psabiehprocinfo.FinalizeAndPopAction(CurrentAction);
  970. if not(fc_catching_exceptions in flowcontrol) then
  971. begin
  972. ReRaiseLandingPad:=psabiehprocinfo.NoAction;
  973. psabiehprocinfo.PushAction(ReRaiseLandingPad);
  974. psabiehprocinfo.PushLandingPad(ReRaiseLandingPad);
  975. end;
  976. end;
  977. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  978. if assigned(CurrentLandingPad) then
  979. begin
  980. psabiehprocinfo.CreateNewPSABIEHCallsite(current_asmdata.CurrAsmList);
  981. if not(fc_catching_exceptions in flowcontrol) then
  982. begin
  983. psabiehprocinfo.PopLandingPad(psabiehprocinfo.CurrentLandingPad);
  984. psabiehprocinfo.PopAction(ReRaiseLandingPad);
  985. end;
  986. psabiehprocinfo.PushAction(CurrentAction);
  987. psabiehprocinfo.PushLandingPad(CurrentLandingPad);
  988. include(flowcontrol,fc_catching_exceptions);
  989. end;
  990. end;
  991. {$endif jvm}
  992. begin
  993. cwhilerepeatnode:=tcgwhilerepeatnode;
  994. cifnode:=tcgifnode;
  995. cfornode:=tcgfornode;
  996. cexitnode:=tcgexitnode;
  997. cbreaknode:=tcgbreaknode;
  998. ccontinuenode:=tcgcontinuenode;
  999. cgotonode:=tcggotonode;
  1000. clabelnode:=tcglabelnode;
  1001. craisenode:=tcgraisenode;
  1002. ctryexceptnode:=tcgtryexceptnode;
  1003. ctryfinallynode:=tcgtryfinallynode;
  1004. connode:=tcgonnode;
  1005. cexceptionstatehandler:=tcgexceptionstatehandler;
  1006. end.