nwasmflw.pas 103 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342
  1. {
  2. Copyright (c) 2019 by Dmitry Boyarintsev
  3. Generate assembler for nodes that influence the flow for the JVM
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nwasmflw;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. aasmbase,node,nflw,ncgflw, cutils;
  22. type
  23. { twasmifnode }
  24. { Wasm doesn't have any jump(+offset) operations
  25. It only provide structured blockes to handle jumps
  26. (It's possible to jump-out-of-block at any time)
  27. "If" is also implemented as a block, identical to high-level language. }
  28. twasmifnode = class(tcgifnode)
  29. public
  30. procedure pass_generate_code;override;
  31. end;
  32. { twasmwhilerepeatnode }
  33. twasmwhilerepeatnode = class(tcgwhilerepeatnode)
  34. public
  35. procedure pass_generate_code_condition;
  36. procedure pass_generate_code;override;
  37. end;
  38. { twasmraisenode }
  39. twasmraisenode = class(tcgraisenode)
  40. private
  41. function pass_1_no_exceptions : tnode;
  42. function pass_1_native_exnref_exceptions : tnode;
  43. function pass_1_native_legacy_exceptions : tnode;
  44. function pass_1_bf_exceptions : tnode;
  45. public
  46. function pass_1 : tnode;override;
  47. end;
  48. { twasmtryexceptnode }
  49. twasmtryexceptnode = class(tcgtryexceptnode)
  50. private
  51. procedure pass_generate_code_no_exceptions;
  52. procedure pass_generate_code_native_exnref_exceptions;
  53. procedure pass_generate_code_native_legacy_exceptions;
  54. procedure pass_generate_code_bf_exceptions;
  55. public
  56. procedure pass_generate_code;override;
  57. end;
  58. { twasmtryfinallynode }
  59. twasmtryfinallynode = class(tcgtryfinallynode)
  60. private
  61. procedure pass_generate_code_no_exceptions;
  62. procedure pass_generate_code_native_exnref_exceptions;
  63. procedure pass_generate_code_native_legacy_exceptions;
  64. procedure pass_generate_code_bf_exceptions;
  65. public
  66. procedure pass_generate_code;override;
  67. end;
  68. { twasmonnode }
  69. twasmonnode = class(tcgonnode)
  70. private
  71. procedure pass_generate_code_no_exceptions;
  72. procedure pass_generate_code_native_exnref_exceptions;
  73. procedure pass_generate_code_native_legacy_exceptions;
  74. procedure pass_generate_code_bf_exceptions;
  75. public
  76. procedure pass_generate_code;override;
  77. end;
  78. implementation
  79. uses
  80. verbose,globals,systems,globtype,constexp,
  81. symconst,symdef,symsym,symtype,aasmtai,aasmdata,aasmcpu,defutil,defcmp,
  82. procinfo,cgbase,cgexcept,pass_1,pass_2,parabase,compinnr,
  83. cpubase,cpuinfo,cpupi,
  84. nbas,nld,ncon,ncnv,ncal,ninl,nmem,nadd,nutils,
  85. tgobj,paramgr,
  86. cgutils,hlcgobj,hlcgcpu;
  87. {*****************************************************************************
  88. twasmwhilerepeatnode
  89. *****************************************************************************}
  90. procedure twasmwhilerepeatnode.pass_generate_code_condition;
  91. begin
  92. secondpass(left);
  93. thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  94. // reversing the condition
  95. if not (lnf_checknegate in loopflags) then
  96. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_i32_eqz));
  97. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,1) );
  98. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  99. end;
  100. procedure twasmwhilerepeatnode.pass_generate_code;
  101. var
  102. lcont,lbreak,lloop,
  103. oldclabel,oldblabel : tasmlabel;
  104. truelabel,falselabel : tasmlabel;
  105. oldflowcontrol : tflowcontrol;
  106. begin
  107. location_reset(location,LOC_VOID,OS_NO);
  108. current_asmdata.getjumplabel(lloop);
  109. current_asmdata.getjumplabel(lcont);
  110. current_asmdata.getjumplabel(lbreak);
  111. oldflowcontrol:=flowcontrol;
  112. oldclabel:=current_procinfo.CurrContinueLabel;
  113. oldblabel:=current_procinfo.CurrBreakLabel;
  114. include(flowcontrol,fc_inflowcontrol);
  115. exclude(flowcontrol,fc_unwind_loop);
  116. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  117. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_loop));
  118. if lnf_testatbegin in loopflags then
  119. begin
  120. hlcg.a_label(current_asmdata.CurrAsmList,lcont);
  121. pass_generate_code_condition;
  122. end;
  123. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  124. current_procinfo.CurrContinueLabel:=lcont;
  125. current_procinfo.CurrBreakLabel:=lbreak;
  126. secondpass(right);
  127. if (lnf_testatbegin in loopflags) then
  128. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1) ); // jump back to the external loop
  129. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  130. if not (lnf_testatbegin in loopflags) then
  131. begin
  132. hlcg.a_label(current_asmdata.CurrAsmList,lcont);
  133. pass_generate_code_condition;
  134. end;
  135. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,0) ); // jump back to loop
  136. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_loop));
  137. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  138. hlcg.a_label(current_asmdata.CurrAsmList,lbreak);
  139. current_procinfo.CurrContinueLabel:=oldclabel;
  140. current_procinfo.CurrBreakLabel:=oldblabel;
  141. { a break/continue in a while/repeat block can't be seen outside }
  142. flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
  143. end;
  144. {*****************************************************************************
  145. twasmifnode
  146. *****************************************************************************}
  147. procedure twasmifnode.pass_generate_code;
  148. var
  149. oldflowcontrol: tflowcontrol;
  150. begin
  151. // left - condition
  152. // right - then
  153. // t1 - else (optional)
  154. location_reset(location,LOC_VOID,OS_NO);
  155. oldflowcontrol := flowcontrol;
  156. include(flowcontrol,fc_inflowcontrol);
  157. //todo: MOVE all current_asm_data actions to Wasm HL CodeGen
  158. secondpass(left); // condition exprssions
  159. thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  160. if is_64bit(left.resultdef) then
  161. begin
  162. thlcgwasm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,left.resultdef,0,R_INTREGISTER);
  163. current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i64_ne));
  164. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  165. end;
  166. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  167. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  168. if Assigned(right) then
  169. secondpass(right); // then branchs
  170. if Assigned(t1) then // else branch
  171. begin
  172. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_else));
  173. secondpass(t1);
  174. end;
  175. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  176. flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
  177. end;
  178. {*****************************************************************************
  179. twasmraisenode
  180. *****************************************************************************}
  181. function twasmraisenode.pass_1_no_exceptions : tnode;
  182. var
  183. statements : tstatementnode;
  184. //current_addr : tlabelnode;
  185. raisenode : tcallnode;
  186. begin
  187. result:=internalstatements(statements);
  188. if assigned(left) then
  189. begin
  190. { first para must be a class }
  191. firstpass(left);
  192. { insert needed typeconvs for addr,frame }
  193. if assigned(right) then
  194. begin
  195. { addr }
  196. firstpass(right);
  197. { frame }
  198. if assigned(third) then
  199. firstpass(third)
  200. else
  201. third:=cpointerconstnode.Create(0,voidpointertype);
  202. end
  203. else
  204. begin
  205. third:=cinlinenode.create(in_get_frame,false,nil);
  206. //current_addr:=clabelnode.create(cnothingnode.create,clabelsym.create('$raiseaddr'));
  207. //addstatement(statements,current_addr);
  208. //right:=caddrnode.create(cloadnode.create(current_addr.labsym,current_addr.labsym.owner));
  209. right:=cnilnode.create;
  210. { raise address off by one so we are for sure inside the action area for the raise }
  211. if tf_use_psabieh in target_info.flags then
  212. right:=caddnode.create_internal(addn,right,cordconstnode.create(1,sizesinttype,false));
  213. end;
  214. raisenode:=ccallnode.createintern('fpc_raiseexception',
  215. ccallparanode.create(third,
  216. ccallparanode.create(right,
  217. ccallparanode.create(left,nil)))
  218. );
  219. include(raisenode.callnodeflags,cnf_call_never_returns);
  220. addstatement(statements,raisenode);
  221. end
  222. else
  223. begin
  224. addstatement(statements,ccallnode.createintern('fpc_popaddrstack',nil));
  225. raisenode:=ccallnode.createintern('fpc_reraise',nil);
  226. include(raisenode.callnodeflags,cnf_call_never_returns);
  227. addstatement(statements,raisenode);
  228. end;
  229. left:=nil;
  230. right:=nil;
  231. third:=nil;
  232. end;
  233. function twasmraisenode.pass_1_native_exnref_exceptions: tnode;
  234. var
  235. statements : tstatementnode;
  236. //current_addr : tlabelnode;
  237. raisenode : tcallnode;
  238. begin
  239. result:=internalstatements(statements);
  240. if assigned(left) then
  241. begin
  242. { first para must be a class }
  243. firstpass(left);
  244. { insert needed typeconvs for addr,frame }
  245. if assigned(right) then
  246. begin
  247. { addr }
  248. firstpass(right);
  249. { frame }
  250. if assigned(third) then
  251. firstpass(third)
  252. else
  253. third:=cpointerconstnode.Create(0,voidpointertype);
  254. end
  255. else
  256. begin
  257. third:=cinlinenode.create(in_get_frame,false,nil);
  258. //current_addr:=clabelnode.create(cnothingnode.create,clabelsym.create('$raiseaddr'));
  259. //addstatement(statements,current_addr);
  260. //right:=caddrnode.create(cloadnode.create(current_addr.labsym,current_addr.labsym.owner));
  261. right:=cnilnode.create;
  262. { raise address off by one so we are for sure inside the action area for the raise }
  263. if tf_use_psabieh in target_info.flags then
  264. right:=caddnode.create_internal(addn,right,cordconstnode.create(1,sizesinttype,false));
  265. end;
  266. raisenode:=ccallnode.createintern('fpc_raiseexception',
  267. ccallparanode.create(third,
  268. ccallparanode.create(right,
  269. ccallparanode.create(left,nil)))
  270. );
  271. include(raisenode.callnodeflags,cnf_call_never_returns);
  272. addstatement(statements,raisenode);
  273. end
  274. else
  275. begin
  276. //addstatement(statements,ccallnode.createintern('fpc_popaddrstack',nil));
  277. raisenode:=ccallnode.createintern('fpc_reraise2',nil);
  278. include(raisenode.callnodeflags,cnf_call_never_returns);
  279. addstatement(statements,raisenode);
  280. end;
  281. left:=nil;
  282. right:=nil;
  283. third:=nil;
  284. end;
  285. function twasmraisenode.pass_1_native_legacy_exceptions : tnode;
  286. var
  287. statements : tstatementnode;
  288. //current_addr : tlabelnode;
  289. raisenode : tcallnode;
  290. begin
  291. result:=internalstatements(statements);
  292. if assigned(left) then
  293. begin
  294. { first para must be a class }
  295. firstpass(left);
  296. { insert needed typeconvs for addr,frame }
  297. if assigned(right) then
  298. begin
  299. { addr }
  300. firstpass(right);
  301. { frame }
  302. if assigned(third) then
  303. firstpass(third)
  304. else
  305. third:=cpointerconstnode.Create(0,voidpointertype);
  306. end
  307. else
  308. begin
  309. third:=cinlinenode.create(in_get_frame,false,nil);
  310. //current_addr:=clabelnode.create(cnothingnode.create,clabelsym.create('$raiseaddr'));
  311. //addstatement(statements,current_addr);
  312. //right:=caddrnode.create(cloadnode.create(current_addr.labsym,current_addr.labsym.owner));
  313. right:=cnilnode.create;
  314. { raise address off by one so we are for sure inside the action area for the raise }
  315. if tf_use_psabieh in target_info.flags then
  316. right:=caddnode.create_internal(addn,right,cordconstnode.create(1,sizesinttype,false));
  317. end;
  318. raisenode:=ccallnode.createintern('fpc_raiseexception',
  319. ccallparanode.create(third,
  320. ccallparanode.create(right,
  321. ccallparanode.create(left,nil)))
  322. );
  323. include(raisenode.callnodeflags,cnf_call_never_returns);
  324. addstatement(statements,raisenode);
  325. end
  326. else
  327. begin
  328. //addstatement(statements,ccallnode.createintern('fpc_popaddrstack',nil));
  329. raisenode:=ccallnode.createintern('fpc_reraise2',nil);
  330. include(raisenode.callnodeflags,cnf_call_never_returns);
  331. addstatement(statements,raisenode);
  332. end;
  333. left:=nil;
  334. right:=nil;
  335. third:=nil;
  336. end;
  337. function twasmraisenode.pass_1_bf_exceptions : tnode;
  338. var
  339. statements : tstatementnode;
  340. //current_addr : tlabelnode;
  341. raisenode : tcallnode;
  342. begin
  343. result:=internalstatements(statements);
  344. if assigned(left) then
  345. begin
  346. { first para must be a class }
  347. firstpass(left);
  348. { insert needed typeconvs for addr,frame }
  349. if assigned(right) then
  350. begin
  351. { addr }
  352. firstpass(right);
  353. { frame }
  354. if assigned(third) then
  355. firstpass(third)
  356. else
  357. third:=cpointerconstnode.Create(0,voidpointertype);
  358. end
  359. else
  360. begin
  361. third:=cinlinenode.create(in_get_frame,false,nil);
  362. //current_addr:=clabelnode.create(cnothingnode.create,clabelsym.create('$raiseaddr'));
  363. //addstatement(statements,current_addr);
  364. //right:=caddrnode.create(cloadnode.create(current_addr.labsym,current_addr.labsym.owner));
  365. right:=cnilnode.create;
  366. { raise address off by one so we are for sure inside the action area for the raise }
  367. if tf_use_psabieh in target_info.flags then
  368. right:=caddnode.create_internal(addn,right,cordconstnode.create(1,sizesinttype,false));
  369. end;
  370. raisenode:=ccallnode.createintern('fpc_raiseexception',
  371. ccallparanode.create(third,
  372. ccallparanode.create(right,
  373. ccallparanode.create(left,nil)))
  374. );
  375. include(raisenode.callnodeflags,cnf_call_never_returns);
  376. addstatement(statements,raisenode);
  377. end
  378. else
  379. begin
  380. //addstatement(statements,ccallnode.createintern('fpc_popaddrstack',nil));
  381. raisenode:=ccallnode.createintern('fpc_reraise2',nil);
  382. include(raisenode.callnodeflags,cnf_call_never_returns);
  383. addstatement(statements,raisenode);
  384. end;
  385. left:=nil;
  386. right:=nil;
  387. third:=nil;
  388. end;
  389. function twasmraisenode.pass_1 : tnode;
  390. begin
  391. if ts_wasm_no_exceptions in current_settings.targetswitches then
  392. result:=pass_1_no_exceptions
  393. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  394. result:=pass_1_native_exnref_exceptions
  395. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  396. result:=pass_1_native_legacy_exceptions
  397. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  398. result:=pass_1_bf_exceptions
  399. else
  400. result:=inherited;
  401. end;
  402. {*****************************************************************************
  403. twasmtryexceptnode
  404. *****************************************************************************}
  405. procedure twasmtryexceptnode.pass_generate_code_no_exceptions;
  406. begin
  407. location_reset(location,LOC_VOID,OS_NO);
  408. secondpass(left);
  409. end;
  410. procedure twasmtryexceptnode.pass_generate_code_native_exnref_exceptions;
  411. var
  412. trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  413. destroytemps,
  414. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  415. afteronflowcontrol: tflowcontrol;
  416. oldCurrExitLabel,
  417. oldContinueLabel,
  418. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  419. NewCurrExitLabel: tasmlabel;
  420. in_loop: Boolean;
  421. label
  422. errorexit;
  423. begin
  424. oldCurrExitLabel:=nil;
  425. oldContinueLabel:=nil;
  426. oldBreakLabel:=nil;
  427. NewContinueLabel:=nil;
  428. NewBreakLabel:=nil;
  429. location_reset(location,LOC_VOID,OS_NO);
  430. doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
  431. { Exception temps? We don't need no stinking exception temps! :) }
  432. fillchar(excepttemps,sizeof(excepttemps),0);
  433. reference_reset(excepttemps.envbuf,0,[]);
  434. reference_reset(excepttemps.jmpbuf,0,[]);
  435. reference_reset(excepttemps.reasonbuf,0,[]);
  436. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  437. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate);
  438. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  439. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  440. current_asmdata.CurrAsmList.concat(taicpu.op_catch(a_try_table,[taicpu.op_sym_const(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG),0)]));
  441. { try block }
  442. secondpass(left);
  443. if codegenerror then
  444. goto errorexit;
  445. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil);
  446. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try_table));
  447. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1));
  448. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  449. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  450. { on statements }
  451. if assigned(right) then
  452. secondpass(right);
  453. afteronflowcontrol:=flowcontrol;
  454. { default handling except handling }
  455. if assigned(t1) then
  456. begin
  457. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  458. it doesn't change any state and its return value is ignored (Sergei)
  459. }
  460. { the destruction of the exception object must be also }
  461. { guarded by an exception frame, but it can be omitted }
  462. { if there's no user code in 'except' block }
  463. if not (has_no_code(t1)) then
  464. begin
  465. { if there is an outer frame that catches exceptions, remember this for the "except"
  466. part of this try/except }
  467. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  468. { Exception temps? We don't need no stinking exception temps! :) }
  469. fillchar(excepttemps,sizeof(destroytemps),0);
  470. reference_reset(destroytemps.envbuf,0,[]);
  471. reference_reset(destroytemps.jmpbuf,0,[]);
  472. reference_reset(destroytemps.reasonbuf,0,[]);
  473. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  474. { the flowcontrol from the default except-block must be merged
  475. with the flowcontrol flags potentially set by the
  476. on-statements handled above (secondpass(right)), as they are
  477. at the same program level }
  478. flowcontrol:=
  479. flowcontrol+
  480. afteronflowcontrol;
  481. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  482. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  483. current_asmdata.CurrAsmList.concat(taicpu.op_catch(a_try_table,[taicpu.op_sym_const(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG),0)]));
  484. { the 'exit' block }
  485. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  486. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  487. current_asmdata.getjumplabel(NewCurrExitLabel);
  488. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  489. { the 'break' block }
  490. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  491. if in_loop then
  492. begin
  493. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  494. current_asmdata.getjumplabel(NewBreakLabel);
  495. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  496. end;
  497. { the 'continue' block }
  498. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  499. if in_loop then
  500. begin
  501. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  502. current_asmdata.getjumplabel(NewContinueLabel);
  503. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  504. end;
  505. secondpass(t1);
  506. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,destroytemps,doobjectdestroyandreraisestate,nil);
  507. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  508. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,6));
  509. { exit the 'continue' block }
  510. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  511. if in_loop then
  512. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  513. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  514. begin
  515. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  516. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  517. end;
  518. { exit the 'break' block }
  519. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  520. if in_loop then
  521. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  522. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  523. begin
  524. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  525. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  526. end;
  527. { exit the 'exit' block }
  528. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  529. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  530. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  531. begin
  532. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  533. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  534. end;
  535. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  536. if in_loop then
  537. begin
  538. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  539. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  540. end;
  541. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try_table));
  542. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1));
  543. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  544. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  545. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  546. end
  547. else
  548. begin
  549. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  550. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  551. end;
  552. end
  553. else
  554. begin
  555. current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_throw,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  556. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  557. end;
  558. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  559. errorexit:
  560. { return all used control flow statements }
  561. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  562. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  563. end;
  564. procedure twasmtryexceptnode.pass_generate_code_native_legacy_exceptions;
  565. var
  566. trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  567. destroytemps,
  568. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  569. afteronflowcontrol: tflowcontrol;
  570. oldCurrExitLabel,
  571. oldContinueLabel,
  572. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  573. NewCurrExitLabel: tasmlabel;
  574. in_loop: Boolean;
  575. label
  576. errorexit;
  577. begin
  578. oldCurrExitLabel:=nil;
  579. oldContinueLabel:=nil;
  580. oldBreakLabel:=nil;
  581. NewContinueLabel:=nil;
  582. NewBreakLabel:=nil;
  583. location_reset(location,LOC_VOID,OS_NO);
  584. doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
  585. { Exception temps? We don't need no stinking exception temps! :) }
  586. fillchar(excepttemps,sizeof(excepttemps),0);
  587. reference_reset(excepttemps.envbuf,0,[]);
  588. reference_reset(excepttemps.jmpbuf,0,[]);
  589. reference_reset(excepttemps.reasonbuf,0,[]);
  590. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  591. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate);
  592. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  593. { try block }
  594. secondpass(left);
  595. if codegenerror then
  596. goto errorexit;
  597. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil);
  598. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  599. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  600. { on statements }
  601. if assigned(right) then
  602. secondpass(right);
  603. afteronflowcontrol:=flowcontrol;
  604. { default handling except handling }
  605. if assigned(t1) then
  606. begin
  607. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  608. it doesn't change any state and its return value is ignored (Sergei)
  609. }
  610. { the destruction of the exception object must be also }
  611. { guarded by an exception frame, but it can be omitted }
  612. { if there's no user code in 'except' block }
  613. if not (has_no_code(t1)) then
  614. begin
  615. { if there is an outer frame that catches exceptions, remember this for the "except"
  616. part of this try/except }
  617. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  618. { Exception temps? We don't need no stinking exception temps! :) }
  619. fillchar(excepttemps,sizeof(destroytemps),0);
  620. reference_reset(destroytemps.envbuf,0,[]);
  621. reference_reset(destroytemps.jmpbuf,0,[]);
  622. reference_reset(destroytemps.reasonbuf,0,[]);
  623. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  624. { the flowcontrol from the default except-block must be merged
  625. with the flowcontrol flags potentially set by the
  626. on-statements handled above (secondpass(right)), as they are
  627. at the same program level }
  628. flowcontrol:=
  629. flowcontrol+
  630. afteronflowcontrol;
  631. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  632. { the 'exit' block }
  633. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  634. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  635. current_asmdata.getjumplabel(NewCurrExitLabel);
  636. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  637. { the 'break' block }
  638. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  639. if in_loop then
  640. begin
  641. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  642. current_asmdata.getjumplabel(NewBreakLabel);
  643. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  644. end;
  645. { the 'continue' block }
  646. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  647. if in_loop then
  648. begin
  649. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  650. current_asmdata.getjumplabel(NewContinueLabel);
  651. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  652. end;
  653. secondpass(t1);
  654. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,destroytemps,doobjectdestroyandreraisestate,nil);
  655. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  656. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4));
  657. { exit the 'continue' block }
  658. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  659. if in_loop then
  660. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  661. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  662. begin
  663. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  664. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  665. end;
  666. { exit the 'break' block }
  667. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  668. if in_loop then
  669. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  670. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  671. begin
  672. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  673. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  674. end;
  675. { exit the 'exit' block }
  676. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  677. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  678. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  679. begin
  680. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  681. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  682. end;
  683. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  684. if in_loop then
  685. begin
  686. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  687. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  688. end;
  689. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  690. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  691. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  692. end
  693. else
  694. begin
  695. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  696. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  697. end;
  698. end
  699. else
  700. begin
  701. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_legacy_rethrow,0));
  702. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  703. end;
  704. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  705. errorexit:
  706. { return all used control flow statements }
  707. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  708. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  709. end;
  710. procedure twasmtryexceptnode.pass_generate_code_bf_exceptions;
  711. var
  712. trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  713. destroytemps,
  714. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  715. afteronflowcontrol: tflowcontrol;
  716. oldCurrRaiseLabel,
  717. oldCurrExitLabel,
  718. oldContinueLabel,
  719. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  720. NewCurrExitLabel, NewCurrRaiseLabel: tasmlabel;
  721. in_loop: Boolean;
  722. label
  723. errorexit;
  724. begin
  725. oldCurrRaiseLabel:=nil;
  726. oldCurrExitLabel:=nil;
  727. oldContinueLabel:=nil;
  728. oldBreakLabel:=nil;
  729. NewContinueLabel:=nil;
  730. NewBreakLabel:=nil;
  731. NewCurrRaiseLabel:=nil;
  732. location_reset(location,LOC_VOID,OS_NO);
  733. doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
  734. { Exception temps? We don't need no stinking exception temps! :) }
  735. fillchar(excepttemps,sizeof(excepttemps),0);
  736. reference_reset(excepttemps.envbuf,0,[]);
  737. reference_reset(excepttemps.jmpbuf,0,[]);
  738. reference_reset(excepttemps.reasonbuf,0,[]);
  739. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  740. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate);
  741. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  742. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  743. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  744. current_asmdata.getjumplabel(NewCurrRaiseLabel);
  745. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
  746. { try block }
  747. secondpass(left);
  748. if codegenerror then
  749. goto errorexit;
  750. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil);
  751. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1));
  752. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  753. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
  754. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  755. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
  756. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  757. { on statements }
  758. if assigned(right) then
  759. secondpass(right);
  760. afteronflowcontrol:=flowcontrol;
  761. { default handling except handling }
  762. if assigned(t1) then
  763. begin
  764. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  765. it doesn't change any state and its return value is ignored (Sergei)
  766. }
  767. { the destruction of the exception object must be also }
  768. { guarded by an exception frame, but it can be omitted }
  769. { if there's no user code in 'except' block }
  770. if not (has_no_code(t1)) then
  771. begin
  772. { if there is an outer frame that catches exceptions, remember this for the "except"
  773. part of this try/except }
  774. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  775. { Exception temps? We don't need no stinking exception temps! :) }
  776. fillchar(excepttemps,sizeof(destroytemps),0);
  777. reference_reset(destroytemps.envbuf,0,[]);
  778. reference_reset(destroytemps.jmpbuf,0,[]);
  779. reference_reset(destroytemps.reasonbuf,0,[]);
  780. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  781. { the flowcontrol from the default except-block must be merged
  782. with the flowcontrol flags potentially set by the
  783. on-statements handled above (secondpass(right)), as they are
  784. at the same program level }
  785. flowcontrol:=
  786. flowcontrol+
  787. afteronflowcontrol;
  788. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  789. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  790. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  791. current_asmdata.getjumplabel(NewCurrRaiseLabel);
  792. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
  793. { the 'exit' block }
  794. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  795. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  796. current_asmdata.getjumplabel(NewCurrExitLabel);
  797. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  798. { the 'break' block }
  799. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  800. if in_loop then
  801. begin
  802. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  803. current_asmdata.getjumplabel(NewBreakLabel);
  804. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  805. end;
  806. { the 'continue' block }
  807. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  808. if in_loop then
  809. begin
  810. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  811. current_asmdata.getjumplabel(NewContinueLabel);
  812. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  813. end;
  814. secondpass(t1);
  815. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,destroytemps,doobjectdestroyandreraisestate,nil);
  816. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  817. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4));
  818. { exit the 'continue' block }
  819. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  820. if in_loop then
  821. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  822. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  823. begin
  824. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  825. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,OldContinueLabel));
  826. end;
  827. { exit the 'break' block }
  828. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  829. if in_loop then
  830. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  831. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  832. begin
  833. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  834. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,OldBreakLabel));
  835. end;
  836. { exit the 'exit' block }
  837. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  838. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  839. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  840. begin
  841. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  842. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  843. end;
  844. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  845. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
  846. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  847. if in_loop then
  848. begin
  849. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  850. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  851. end;
  852. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
  853. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  854. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  855. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  856. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  857. end
  858. else
  859. begin
  860. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  861. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  862. end;
  863. end
  864. else
  865. begin
  866. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  867. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  868. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  869. end;
  870. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  871. errorexit:
  872. { return all used control flow statements }
  873. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  874. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  875. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
  876. end;
  877. procedure twasmtryexceptnode.pass_generate_code;
  878. begin
  879. if ts_wasm_no_exceptions in current_settings.targetswitches then
  880. pass_generate_code_no_exceptions
  881. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  882. pass_generate_code_native_exnref_exceptions
  883. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  884. pass_generate_code_native_legacy_exceptions
  885. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  886. pass_generate_code_bf_exceptions
  887. else
  888. internalerror(2021091705);
  889. end;
  890. {*****************************************************************************
  891. twasmtryfinallynode
  892. *****************************************************************************}
  893. procedure twasmtryfinallynode.pass_generate_code_no_exceptions;
  894. var
  895. exitfinallylabel,
  896. continuefinallylabel,
  897. breakfinallylabel,
  898. oldCurrExitLabel,
  899. oldContinueLabel,
  900. oldBreakLabel: tasmlabel;
  901. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  902. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  903. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  904. in_loop: Boolean;
  905. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  906. var
  907. reasonreg : tregister;
  908. begin
  909. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  910. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  911. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  912. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  913. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  914. end;
  915. procedure generate_exceptreason_check_br(reason: tcgint; l: TAsmLabel);
  916. var
  917. reasonreg : tregister;
  918. begin
  919. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  920. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  921. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  922. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  923. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  924. end;
  925. begin
  926. location_reset(location,LOC_VOID,OS_NO);
  927. oldBreakLabel:=nil;
  928. oldContinueLabel:=nil;
  929. continuefinallylabel:=nil;
  930. breakfinallylabel:=nil;
  931. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  932. if not implicitframe then
  933. exceptframekind:=tek_normalfinally
  934. else
  935. exceptframekind:=tek_implicitfinally;
  936. { in 'no exceptions' mode, we still want to handle properly exit,
  937. continue and break (they still need to execute the 'finally'
  938. statements), so for this we need excepttemps.reasonbuf, and for this
  939. reason, we need to allocate excepttemps }
  940. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  941. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  942. { the finally block must catch break, continue and exit }
  943. { statements }
  944. { the outer 'try..finally' block }
  945. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  946. { the 'exit' block }
  947. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  948. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  949. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  950. current_procinfo.CurrExitLabel:=exitfinallylabel;
  951. { the 'break' block }
  952. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  953. if in_loop then
  954. begin
  955. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  956. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  957. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  958. end;
  959. { the 'continue' block }
  960. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  961. if in_loop then
  962. begin
  963. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  964. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  965. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  966. end;
  967. { try code }
  968. if assigned(left) then
  969. begin
  970. secondpass(left);
  971. if codegenerror then
  972. exit;
  973. end;
  974. { don't generate line info for internal cleanup }
  975. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  976. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  977. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  978. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  979. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,3)); // jump to the 'finally' section
  980. { exit the 'continue' block }
  981. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  982. if in_loop then
  983. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  984. { exceptionreason:=4 (continue) }
  985. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  986. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  987. { exit the 'break' block }
  988. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  989. if in_loop then
  990. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  991. { exceptionreason:=3 (break) }
  992. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  993. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  994. { exit the 'exit' block }
  995. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  996. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  997. { exceptionreason:=2 (exit) }
  998. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  999. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1000. { exit the outer 'try..finally' block }
  1001. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1002. { end cleanup }
  1003. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1004. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1005. finally code is unconditionally executed; we do have to filter out
  1006. flags regarding break/contrinue/etc. because we have to give an
  1007. error in case one of those is used in the finally-code }
  1008. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1009. secondpass(right);
  1010. { goto is allowed if it stays inside the finally block,
  1011. this is checked using the exception block number }
  1012. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1013. CGMessage(cg_e_control_flow_outside_finally);
  1014. if codegenerror then
  1015. exit;
  1016. { don't generate line info for internal cleanup }
  1017. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1018. if fc_exit in finallyexceptionstate.newflowcontrol then
  1019. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1020. if fc_break in finallyexceptionstate.newflowcontrol then
  1021. generate_exceptreason_check_br(3,oldBreakLabel);
  1022. if fc_continue in finallyexceptionstate.newflowcontrol then
  1023. generate_exceptreason_check_br(4,oldContinueLabel);
  1024. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1025. { end cleanup }
  1026. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1027. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1028. if assigned(current_procinfo.CurrBreakLabel) then
  1029. begin
  1030. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1031. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1032. end;
  1033. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1034. end;
  1035. procedure twasmtryfinallynode.pass_generate_code_native_exnref_exceptions;
  1036. var
  1037. exitfinallylabel,
  1038. continuefinallylabel,
  1039. breakfinallylabel,
  1040. oldCurrExitLabel,
  1041. oldContinueLabel,
  1042. oldBreakLabel: tasmlabel;
  1043. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  1044. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  1045. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  1046. in_loop: Boolean;
  1047. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  1048. var
  1049. reasonreg : tregister;
  1050. begin
  1051. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1052. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1053. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1054. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  1055. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1056. end;
  1057. procedure generate_exceptreason_check_br(reason: tcgint; l: tasmlabel);
  1058. var
  1059. reasonreg : tregister;
  1060. begin
  1061. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1062. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1063. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1064. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  1065. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1066. end;
  1067. procedure generate_exceptreason_throw(reason: tcgint);
  1068. var
  1069. reasonreg : tregister;
  1070. begin
  1071. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1072. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1073. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1074. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  1075. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1076. current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_throw,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1077. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  1078. end;
  1079. begin
  1080. location_reset(location,LOC_VOID,OS_NO);
  1081. oldBreakLabel:=nil;
  1082. oldContinueLabel:=nil;
  1083. continuefinallylabel:=nil;
  1084. breakfinallylabel:=nil;
  1085. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1086. if not implicitframe then
  1087. exceptframekind:=tek_normalfinally
  1088. else
  1089. exceptframekind:=tek_implicitfinally;
  1090. { in 'no exceptions' mode, we still want to handle properly exit,
  1091. continue and break (they still need to execute the 'finally'
  1092. statements), so for this we need excepttemps.reasonbuf, and for this
  1093. reason, we need to allocate excepttemps }
  1094. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1095. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  1096. { the finally block must catch break, continue and exit }
  1097. { statements }
  1098. { the outer 'try..finally' block }
  1099. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1100. { the 'exit' block }
  1101. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1102. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1103. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1104. current_procinfo.CurrExitLabel:=exitfinallylabel;
  1105. { the 'break' block }
  1106. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1107. if in_loop then
  1108. begin
  1109. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1110. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1111. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  1112. end;
  1113. { the 'continue' block }
  1114. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1115. if in_loop then
  1116. begin
  1117. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1118. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1119. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  1120. end;
  1121. { the 'catch' block }
  1122. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1123. { the inner 'try_table..end_try_table' block }
  1124. current_asmdata.CurrAsmList.concat(taicpu.op_catch(a_try_table,[taicpu.op_sym_const(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG),0)]));
  1125. { try code }
  1126. if assigned(left) then
  1127. begin
  1128. secondpass(left);
  1129. if codegenerror then
  1130. exit;
  1131. end;
  1132. { don't generate line info for internal cleanup }
  1133. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1134. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  1135. { exit the inner 'try_table..end_try_table' block }
  1136. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try_table));
  1137. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  1138. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  1139. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1140. { exit the 'catch' block }
  1141. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1142. { exceptionreason:=1 (exception) }
  1143. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,1,excepttemps.reasonbuf);
  1144. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,3)); // jump to the 'finally' section
  1145. { exit the 'continue' block }
  1146. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1147. if in_loop then
  1148. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  1149. { exceptionreason:=4 (continue) }
  1150. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  1151. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  1152. { exit the 'break' block }
  1153. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1154. if in_loop then
  1155. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  1156. { exceptionreason:=3 (break) }
  1157. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  1158. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  1159. { exit the 'exit' block }
  1160. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1161. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  1162. { exceptionreason:=2 (exit) }
  1163. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  1164. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1165. { exit the outer 'try..finally' block }
  1166. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1167. { end cleanup }
  1168. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1169. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1170. finally code is unconditionally executed; we do have to filter out
  1171. flags regarding break/contrinue/etc. because we have to give an
  1172. error in case one of those is used in the finally-code }
  1173. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1174. secondpass(right);
  1175. { goto is allowed if it stays inside the finally block,
  1176. this is checked using the exception block number }
  1177. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1178. CGMessage(cg_e_control_flow_outside_finally);
  1179. if codegenerror then
  1180. exit;
  1181. { don't generate line info for internal cleanup }
  1182. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1183. if fc_exit in finallyexceptionstate.newflowcontrol then
  1184. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1185. if fc_break in finallyexceptionstate.newflowcontrol then
  1186. generate_exceptreason_check_br(3,oldBreakLabel);
  1187. if fc_continue in finallyexceptionstate.newflowcontrol then
  1188. generate_exceptreason_check_br(4,oldContinueLabel);
  1189. generate_exceptreason_throw(1);
  1190. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1191. { end cleanup }
  1192. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1193. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1194. if assigned(current_procinfo.CurrBreakLabel) then
  1195. begin
  1196. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1197. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1198. end;
  1199. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1200. end;
  1201. procedure twasmtryfinallynode.pass_generate_code_native_legacy_exceptions;
  1202. var
  1203. exitfinallylabel,
  1204. continuefinallylabel,
  1205. breakfinallylabel,
  1206. oldCurrExitLabel,
  1207. oldContinueLabel,
  1208. oldBreakLabel: tasmlabel;
  1209. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  1210. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  1211. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  1212. in_loop: Boolean;
  1213. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  1214. var
  1215. reasonreg : tregister;
  1216. begin
  1217. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1218. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1219. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1220. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  1221. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1222. end;
  1223. procedure generate_exceptreason_check_br(reason: tcgint; l: tasmlabel);
  1224. var
  1225. reasonreg : tregister;
  1226. begin
  1227. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1228. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1229. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1230. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  1231. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1232. end;
  1233. procedure generate_exceptreason_throw(reason: tcgint);
  1234. var
  1235. reasonreg : tregister;
  1236. begin
  1237. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1238. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1239. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1240. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  1241. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1242. current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_legacy_throw,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1243. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  1244. end;
  1245. begin
  1246. location_reset(location,LOC_VOID,OS_NO);
  1247. oldBreakLabel:=nil;
  1248. oldContinueLabel:=nil;
  1249. continuefinallylabel:=nil;
  1250. breakfinallylabel:=nil;
  1251. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1252. if not implicitframe then
  1253. exceptframekind:=tek_normalfinally
  1254. else
  1255. exceptframekind:=tek_implicitfinally;
  1256. { in 'no exceptions' mode, we still want to handle properly exit,
  1257. continue and break (they still need to execute the 'finally'
  1258. statements), so for this we need excepttemps.reasonbuf, and for this
  1259. reason, we need to allocate excepttemps }
  1260. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1261. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  1262. { the finally block must catch break, continue and exit }
  1263. { statements }
  1264. { the outer 'try..finally' block }
  1265. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1266. { the 'exit' block }
  1267. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1268. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1269. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1270. current_procinfo.CurrExitLabel:=exitfinallylabel;
  1271. { the 'break' block }
  1272. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1273. if in_loop then
  1274. begin
  1275. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1276. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1277. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  1278. end;
  1279. { the 'continue' block }
  1280. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1281. if in_loop then
  1282. begin
  1283. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1284. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1285. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  1286. end;
  1287. { the inner 'try..end_try' block }
  1288. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  1289. { try code }
  1290. if assigned(left) then
  1291. begin
  1292. secondpass(left);
  1293. if codegenerror then
  1294. exit;
  1295. end;
  1296. { don't generate line info for internal cleanup }
  1297. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1298. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  1299. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  1300. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  1301. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1302. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1303. { exceptionreason:=1 (exception) }
  1304. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,1,excepttemps.reasonbuf);
  1305. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1306. { exit the inner 'try..end_try' block }
  1307. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  1308. { exit the 'continue' block }
  1309. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1310. if in_loop then
  1311. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  1312. { exceptionreason:=4 (continue) }
  1313. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  1314. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  1315. { exit the 'break' block }
  1316. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1317. if in_loop then
  1318. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  1319. { exceptionreason:=3 (break) }
  1320. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  1321. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  1322. { exit the 'exit' block }
  1323. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1324. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  1325. { exceptionreason:=2 (exit) }
  1326. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  1327. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1328. { exit the outer 'try..finally' block }
  1329. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1330. { end cleanup }
  1331. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1332. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1333. finally code is unconditionally executed; we do have to filter out
  1334. flags regarding break/contrinue/etc. because we have to give an
  1335. error in case one of those is used in the finally-code }
  1336. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1337. secondpass(right);
  1338. { goto is allowed if it stays inside the finally block,
  1339. this is checked using the exception block number }
  1340. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1341. CGMessage(cg_e_control_flow_outside_finally);
  1342. if codegenerror then
  1343. exit;
  1344. { don't generate line info for internal cleanup }
  1345. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1346. if fc_exit in finallyexceptionstate.newflowcontrol then
  1347. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1348. if fc_break in finallyexceptionstate.newflowcontrol then
  1349. generate_exceptreason_check_br(3,oldBreakLabel);
  1350. if fc_continue in finallyexceptionstate.newflowcontrol then
  1351. generate_exceptreason_check_br(4,oldContinueLabel);
  1352. generate_exceptreason_throw(1);
  1353. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1354. { end cleanup }
  1355. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1356. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1357. if assigned(current_procinfo.CurrBreakLabel) then
  1358. begin
  1359. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1360. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1361. end;
  1362. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1363. end;
  1364. procedure twasmtryfinallynode.pass_generate_code_bf_exceptions;
  1365. var
  1366. raisefinallylabel,
  1367. exitfinallylabel,
  1368. continuefinallylabel,
  1369. breakfinallylabel,
  1370. oldCurrRaiseLabel,
  1371. oldCurrExitLabel,
  1372. oldContinueLabel,
  1373. oldBreakLabel: tasmlabel;
  1374. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  1375. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  1376. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  1377. in_loop: Boolean;
  1378. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  1379. var
  1380. reasonreg : tregister;
  1381. begin
  1382. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1383. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1384. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1385. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  1386. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1387. end;
  1388. procedure generate_exceptreason_check_br(reason: tcgint; l: tasmsymbol);
  1389. var
  1390. reasonreg : tregister;
  1391. begin
  1392. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1393. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1394. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1395. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  1396. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1397. end;
  1398. procedure generate_exceptreason_reraise(reason: tcgint);
  1399. var
  1400. reasonreg : tregister;
  1401. begin
  1402. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1403. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1404. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1405. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  1406. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1407. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  1408. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  1409. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  1410. end;
  1411. begin
  1412. location_reset(location,LOC_VOID,OS_NO);
  1413. oldCurrRaiseLabel:=nil;
  1414. oldBreakLabel:=nil;
  1415. oldContinueLabel:=nil;
  1416. continuefinallylabel:=nil;
  1417. breakfinallylabel:=nil;
  1418. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1419. if not implicitframe then
  1420. exceptframekind:=tek_normalfinally
  1421. else
  1422. exceptframekind:=tek_implicitfinally;
  1423. { in 'no exceptions' mode, we still want to handle properly exit,
  1424. continue and break (they still need to execute the 'finally'
  1425. statements), so for this we need excepttemps.reasonbuf, and for this
  1426. reason, we need to allocate excepttemps }
  1427. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1428. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  1429. { the finally block must catch break, continue and exit }
  1430. { statements }
  1431. { the outer 'try..finally' block }
  1432. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1433. { the 'exit' block }
  1434. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1435. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1436. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1437. current_procinfo.CurrExitLabel:=exitfinallylabel;
  1438. { the 'break' block }
  1439. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1440. if in_loop then
  1441. begin
  1442. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1443. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1444. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  1445. end;
  1446. { the 'continue' block }
  1447. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1448. if in_loop then
  1449. begin
  1450. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1451. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1452. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  1453. end;
  1454. { the inner 'try..end_try' block }
  1455. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1456. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  1457. current_asmdata.getjumplabel(raisefinallylabel);
  1458. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=raisefinallylabel;
  1459. { try code }
  1460. if assigned(left) then
  1461. begin
  1462. secondpass(left);
  1463. if codegenerror then
  1464. exit;
  1465. end;
  1466. { don't generate line info for internal cleanup }
  1467. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1468. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  1469. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  1470. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  1471. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1472. { exit the inner 'try..end_try' block }
  1473. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1474. hlcg.a_label(current_asmdata.CurrAsmList,raisefinallylabel);
  1475. { exceptionreason:=1 (exception) }
  1476. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  1477. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,1,excepttemps.reasonbuf);
  1478. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,3)); // jump to the 'finally' section
  1479. { exit the 'continue' block }
  1480. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1481. if in_loop then
  1482. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  1483. { exceptionreason:=4 (continue) }
  1484. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  1485. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  1486. { exit the 'break' block }
  1487. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1488. if in_loop then
  1489. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  1490. { exceptionreason:=3 (break) }
  1491. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  1492. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  1493. { exit the 'exit' block }
  1494. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1495. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  1496. { exceptionreason:=2 (exit) }
  1497. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  1498. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1499. { exit the outer 'try..finally' block }
  1500. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1501. { end cleanup }
  1502. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1503. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=oldCurrRaiseLabel;
  1504. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1505. finally code is unconditionally executed; we do have to filter out
  1506. flags regarding break/contrinue/etc. because we have to give an
  1507. error in case one of those is used in the finally-code }
  1508. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1509. secondpass(right);
  1510. { goto is allowed if it stays inside the finally block,
  1511. this is checked using the exception block number }
  1512. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1513. CGMessage(cg_e_control_flow_outside_finally);
  1514. if codegenerror then
  1515. exit;
  1516. { don't generate line info for internal cleanup }
  1517. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1518. if fc_exit in finallyexceptionstate.newflowcontrol then
  1519. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1520. if fc_break in finallyexceptionstate.newflowcontrol then
  1521. generate_exceptreason_check_br(3,oldBreakLabel);
  1522. if fc_continue in finallyexceptionstate.newflowcontrol then
  1523. generate_exceptreason_check_br(4,oldContinueLabel);
  1524. generate_exceptreason_reraise(1);
  1525. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1526. { end cleanup }
  1527. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1528. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1529. if assigned(current_procinfo.CurrBreakLabel) then
  1530. begin
  1531. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1532. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1533. end;
  1534. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1535. end;
  1536. procedure twasmtryfinallynode.pass_generate_code;
  1537. begin
  1538. if ts_wasm_no_exceptions in current_settings.targetswitches then
  1539. pass_generate_code_no_exceptions
  1540. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  1541. pass_generate_code_native_exnref_exceptions
  1542. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  1543. pass_generate_code_native_legacy_exceptions
  1544. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  1545. pass_generate_code_bf_exceptions
  1546. else
  1547. internalerror(2021091704);
  1548. end;
  1549. {*****************************************************************************
  1550. twasmonnode
  1551. *****************************************************************************}
  1552. procedure twasmonnode.pass_generate_code_no_exceptions;
  1553. begin
  1554. { should not be called }
  1555. internalerror(2021092803);
  1556. end;
  1557. procedure twasmonnode.pass_generate_code_native_exnref_exceptions;
  1558. var
  1559. exceptvarsym : tlocalvarsym;
  1560. exceptlocdef: tdef;
  1561. exceptlocreg: tregister;
  1562. oldCurrExitLabel,
  1563. oldContinueLabel,
  1564. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  1565. NewCurrExitLabel: tasmlabel;
  1566. in_loop: Boolean;
  1567. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  1568. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  1569. begin
  1570. oldCurrExitLabel:=nil;
  1571. oldContinueLabel:=nil;
  1572. oldBreakLabel:=nil;
  1573. NewBreakLabel:=nil;
  1574. NewContinueLabel:=nil;
  1575. location_reset(location,LOC_VOID,OS_NO);
  1576. { Exception temps? We don't need no stinking exception temps! :) }
  1577. fillchar(excepttemps,sizeof(excepttemps),0);
  1578. reference_reset(excepttemps.envbuf,0,[]);
  1579. reference_reset(excepttemps.jmpbuf,0,[]);
  1580. reference_reset(excepttemps.reasonbuf,0,[]);
  1581. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1582. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nil,exceptlocdef,exceptlocreg);
  1583. { Retrieve exception variable }
  1584. if assigned(excepTSymtable) then
  1585. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  1586. else
  1587. internalerror(2011020401);
  1588. if assigned(exceptvarsym) then
  1589. begin
  1590. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  1591. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  1592. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  1593. end;
  1594. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  1595. { in the case that another exception is risen
  1596. we've to destroy the old one, so create a new
  1597. exception frame for the catch-handler }
  1598. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1599. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1600. current_asmdata.CurrAsmList.concat(taicpu.op_catch(a_try_table,[taicpu.op_sym_const(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG),0)]));
  1601. { the 'exit' block }
  1602. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1603. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1604. current_asmdata.getjumplabel(NewCurrExitLabel);
  1605. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  1606. { the 'break' block }
  1607. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1608. if in_loop then
  1609. begin
  1610. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1611. current_asmdata.getjumplabel(NewBreakLabel);
  1612. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  1613. end;
  1614. { the 'continue' block }
  1615. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1616. if in_loop then
  1617. begin
  1618. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1619. current_asmdata.getjumplabel(NewContinueLabel);
  1620. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  1621. end;
  1622. if assigned(right) then
  1623. secondpass(right);
  1624. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,doobjectdestroyandreraisestate,nil);
  1625. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1626. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,7));
  1627. { exit the 'continue' block }
  1628. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1629. if in_loop then
  1630. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  1631. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  1632. begin
  1633. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1634. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  1635. end;
  1636. { exit the 'break' block }
  1637. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  1638. if in_loop then
  1639. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  1640. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  1641. begin
  1642. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1643. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  1644. end;
  1645. { exit the 'exit' block }
  1646. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  1647. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  1648. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  1649. begin
  1650. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1651. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  1652. end;
  1653. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1654. if in_loop then
  1655. begin
  1656. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1657. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1658. end;
  1659. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try_table));
  1660. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1));
  1661. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1662. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  1663. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1664. { clear some stuff }
  1665. if assigned(exceptvarsym) then
  1666. begin
  1667. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  1668. exceptvarsym.localloc.loc:=LOC_INVALID;
  1669. end;
  1670. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  1671. { propagate exit/break/continue }
  1672. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1673. { next on node }
  1674. if assigned(left) then
  1675. secondpass(left);
  1676. end;
  1677. procedure twasmonnode.pass_generate_code_native_legacy_exceptions;
  1678. var
  1679. exceptvarsym : tlocalvarsym;
  1680. exceptlocdef: tdef;
  1681. exceptlocreg: tregister;
  1682. oldCurrExitLabel,
  1683. oldContinueLabel,
  1684. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  1685. NewCurrExitLabel: tasmlabel;
  1686. in_loop: Boolean;
  1687. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  1688. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  1689. begin
  1690. oldCurrExitLabel:=nil;
  1691. oldContinueLabel:=nil;
  1692. oldBreakLabel:=nil;
  1693. NewBreakLabel:=nil;
  1694. NewContinueLabel:=nil;
  1695. location_reset(location,LOC_VOID,OS_NO);
  1696. { Exception temps? We don't need no stinking exception temps! :) }
  1697. fillchar(excepttemps,sizeof(excepttemps),0);
  1698. reference_reset(excepttemps.envbuf,0,[]);
  1699. reference_reset(excepttemps.jmpbuf,0,[]);
  1700. reference_reset(excepttemps.reasonbuf,0,[]);
  1701. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1702. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nil,exceptlocdef,exceptlocreg);
  1703. { Retrieve exception variable }
  1704. if assigned(excepTSymtable) then
  1705. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  1706. else
  1707. internalerror(2011020401);
  1708. if assigned(exceptvarsym) then
  1709. begin
  1710. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  1711. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  1712. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  1713. end;
  1714. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  1715. { in the case that another exception is risen
  1716. we've to destroy the old one, so create a new
  1717. exception frame for the catch-handler }
  1718. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  1719. { the 'exit' block }
  1720. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1721. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1722. current_asmdata.getjumplabel(NewCurrExitLabel);
  1723. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  1724. { the 'break' block }
  1725. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1726. if in_loop then
  1727. begin
  1728. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1729. current_asmdata.getjumplabel(NewBreakLabel);
  1730. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  1731. end;
  1732. { the 'continue' block }
  1733. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1734. if in_loop then
  1735. begin
  1736. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1737. current_asmdata.getjumplabel(NewContinueLabel);
  1738. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  1739. end;
  1740. if assigned(right) then
  1741. secondpass(right);
  1742. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,doobjectdestroyandreraisestate,nil);
  1743. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1744. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,5));
  1745. { exit the 'continue' block }
  1746. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1747. if in_loop then
  1748. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  1749. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  1750. begin
  1751. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1752. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  1753. end;
  1754. { exit the 'break' block }
  1755. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  1756. if in_loop then
  1757. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  1758. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  1759. begin
  1760. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1761. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  1762. end;
  1763. { exit the 'exit' block }
  1764. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  1765. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  1766. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  1767. begin
  1768. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1769. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  1770. end;
  1771. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1772. if in_loop then
  1773. begin
  1774. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1775. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1776. end;
  1777. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1778. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  1779. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  1780. { clear some stuff }
  1781. if assigned(exceptvarsym) then
  1782. begin
  1783. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  1784. exceptvarsym.localloc.loc:=LOC_INVALID;
  1785. end;
  1786. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  1787. { propagate exit/break/continue }
  1788. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1789. { next on node }
  1790. if assigned(left) then
  1791. secondpass(left);
  1792. end;
  1793. procedure twasmonnode.pass_generate_code_bf_exceptions;
  1794. var
  1795. exceptvarsym : tlocalvarsym;
  1796. exceptlocdef: tdef;
  1797. exceptlocreg: tregister;
  1798. oldCurrRaiseLabel,
  1799. oldCurrExitLabel,
  1800. oldContinueLabel,
  1801. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  1802. NewCurrRaiseLabel, NewCurrExitLabel: tasmlabel;
  1803. in_loop: Boolean;
  1804. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  1805. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  1806. begin
  1807. oldCurrRaiseLabel:=nil;
  1808. oldCurrExitLabel:=nil;
  1809. oldContinueLabel:=nil;
  1810. oldBreakLabel:=nil;
  1811. NewCurrRaiseLabel:=nil;
  1812. NewBreakLabel:=nil;
  1813. NewContinueLabel:=nil;
  1814. location_reset(location,LOC_VOID,OS_NO);
  1815. { Exception temps? We don't need no stinking exception temps! :) }
  1816. fillchar(excepttemps,sizeof(excepttemps),0);
  1817. reference_reset(excepttemps.envbuf,0,[]);
  1818. reference_reset(excepttemps.jmpbuf,0,[]);
  1819. reference_reset(excepttemps.reasonbuf,0,[]);
  1820. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1821. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nil,exceptlocdef,exceptlocreg);
  1822. { Retrieve exception variable }
  1823. if assigned(excepTSymtable) then
  1824. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  1825. else
  1826. internalerror(2011020401);
  1827. if assigned(exceptvarsym) then
  1828. begin
  1829. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  1830. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  1831. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  1832. end;
  1833. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  1834. { in the case that another exception is risen
  1835. we've to destroy the old one, so create a new
  1836. exception frame for the catch-handler }
  1837. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1838. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1839. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  1840. current_asmdata.getjumplabel(NewCurrRaiseLabel);
  1841. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
  1842. { the 'exit' block }
  1843. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1844. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1845. current_asmdata.getjumplabel(NewCurrExitLabel);
  1846. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  1847. { the 'break' block }
  1848. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1849. if in_loop then
  1850. begin
  1851. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1852. current_asmdata.getjumplabel(NewBreakLabel);
  1853. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  1854. end;
  1855. { the 'continue' block }
  1856. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1857. if in_loop then
  1858. begin
  1859. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1860. current_asmdata.getjumplabel(NewContinueLabel);
  1861. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  1862. end;
  1863. if assigned(right) then
  1864. secondpass(right);
  1865. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,doobjectdestroyandreraisestate,nil);
  1866. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1867. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,6));
  1868. { exit the 'continue' block }
  1869. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1870. if in_loop then
  1871. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  1872. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  1873. begin
  1874. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1875. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  1876. end;
  1877. { exit the 'break' block }
  1878. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  1879. if in_loop then
  1880. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  1881. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  1882. begin
  1883. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1884. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  1885. end;
  1886. { exit the 'exit' block }
  1887. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  1888. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  1889. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  1890. begin
  1891. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1892. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  1893. end;
  1894. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1895. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
  1896. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1897. if in_loop then
  1898. begin
  1899. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1900. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1901. end;
  1902. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=oldCurrRaiseLabel;
  1903. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  1904. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  1905. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  1906. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1907. { clear some stuff }
  1908. if assigned(exceptvarsym) then
  1909. begin
  1910. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  1911. exceptvarsym.localloc.loc:=LOC_INVALID;
  1912. end;
  1913. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  1914. { propagate exit/break/continue }
  1915. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1916. { next on node }
  1917. if assigned(left) then
  1918. secondpass(left);
  1919. end;
  1920. procedure twasmonnode.pass_generate_code;
  1921. begin
  1922. if ts_wasm_no_exceptions in current_settings.targetswitches then
  1923. pass_generate_code_no_exceptions
  1924. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  1925. pass_generate_code_native_exnref_exceptions
  1926. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  1927. pass_generate_code_native_legacy_exceptions
  1928. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  1929. pass_generate_code_bf_exceptions
  1930. else
  1931. internalerror(2021092802);
  1932. end;
  1933. initialization
  1934. cifnode:=twasmifnode;
  1935. cwhilerepeatnode:=twasmwhilerepeatnode;
  1936. craisenode:=twasmraisenode;
  1937. ctryexceptnode:=twasmtryexceptnode;
  1938. ctryfinallynode:=twasmtryfinallynode;
  1939. connode:=twasmonnode;
  1940. end.