nwasmflw.pas 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333
  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_legacy_try));
  439. { try block }
  440. secondpass(left);
  441. if codegenerror then
  442. goto errorexit;
  443. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil);
  444. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  445. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  446. { on statements }
  447. if assigned(right) then
  448. secondpass(right);
  449. afteronflowcontrol:=flowcontrol;
  450. { default handling except handling }
  451. if assigned(t1) then
  452. begin
  453. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  454. it doesn't change any state and its return value is ignored (Sergei)
  455. }
  456. { the destruction of the exception object must be also }
  457. { guarded by an exception frame, but it can be omitted }
  458. { if there's no user code in 'except' block }
  459. if not (has_no_code(t1)) then
  460. begin
  461. { if there is an outer frame that catches exceptions, remember this for the "except"
  462. part of this try/except }
  463. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  464. { Exception temps? We don't need no stinking exception temps! :) }
  465. fillchar(excepttemps,sizeof(destroytemps),0);
  466. reference_reset(destroytemps.envbuf,0,[]);
  467. reference_reset(destroytemps.jmpbuf,0,[]);
  468. reference_reset(destroytemps.reasonbuf,0,[]);
  469. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  470. { the flowcontrol from the default except-block must be merged
  471. with the flowcontrol flags potentially set by the
  472. on-statements handled above (secondpass(right)), as they are
  473. at the same program level }
  474. flowcontrol:=
  475. flowcontrol+
  476. afteronflowcontrol;
  477. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  478. { the 'exit' block }
  479. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  480. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  481. current_asmdata.getjumplabel(NewCurrExitLabel);
  482. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  483. { the 'break' block }
  484. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  485. if in_loop then
  486. begin
  487. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  488. current_asmdata.getjumplabel(NewBreakLabel);
  489. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  490. end;
  491. { the 'continue' block }
  492. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  493. if in_loop then
  494. begin
  495. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  496. current_asmdata.getjumplabel(NewContinueLabel);
  497. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  498. end;
  499. secondpass(t1);
  500. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,destroytemps,doobjectdestroyandreraisestate,nil);
  501. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  502. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4));
  503. { exit the 'continue' block }
  504. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  505. if in_loop then
  506. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  507. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  508. begin
  509. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  510. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  511. end;
  512. { exit the 'break' block }
  513. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  514. if in_loop then
  515. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  516. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  517. begin
  518. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  519. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  520. end;
  521. { exit the 'exit' block }
  522. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  523. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  524. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  525. begin
  526. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  527. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  528. end;
  529. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  530. if in_loop then
  531. begin
  532. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  533. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  534. end;
  535. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  536. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  537. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  538. end
  539. else
  540. begin
  541. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  542. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  543. end;
  544. end
  545. else
  546. begin
  547. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_legacy_rethrow,0));
  548. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  549. end;
  550. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  551. errorexit:
  552. { return all used control flow statements }
  553. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  554. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  555. end;
  556. procedure twasmtryexceptnode.pass_generate_code_native_legacy_exceptions;
  557. var
  558. trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  559. destroytemps,
  560. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  561. afteronflowcontrol: tflowcontrol;
  562. oldCurrExitLabel,
  563. oldContinueLabel,
  564. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  565. NewCurrExitLabel: tasmlabel;
  566. in_loop: Boolean;
  567. label
  568. errorexit;
  569. begin
  570. oldCurrExitLabel:=nil;
  571. oldContinueLabel:=nil;
  572. oldBreakLabel:=nil;
  573. NewContinueLabel:=nil;
  574. NewBreakLabel:=nil;
  575. location_reset(location,LOC_VOID,OS_NO);
  576. doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
  577. { Exception temps? We don't need no stinking exception temps! :) }
  578. fillchar(excepttemps,sizeof(excepttemps),0);
  579. reference_reset(excepttemps.envbuf,0,[]);
  580. reference_reset(excepttemps.jmpbuf,0,[]);
  581. reference_reset(excepttemps.reasonbuf,0,[]);
  582. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  583. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate);
  584. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  585. { try block }
  586. secondpass(left);
  587. if codegenerror then
  588. goto errorexit;
  589. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil);
  590. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  591. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  592. { on statements }
  593. if assigned(right) then
  594. secondpass(right);
  595. afteronflowcontrol:=flowcontrol;
  596. { default handling except handling }
  597. if assigned(t1) then
  598. begin
  599. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  600. it doesn't change any state and its return value is ignored (Sergei)
  601. }
  602. { the destruction of the exception object must be also }
  603. { guarded by an exception frame, but it can be omitted }
  604. { if there's no user code in 'except' block }
  605. if not (has_no_code(t1)) then
  606. begin
  607. { if there is an outer frame that catches exceptions, remember this for the "except"
  608. part of this try/except }
  609. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  610. { Exception temps? We don't need no stinking exception temps! :) }
  611. fillchar(excepttemps,sizeof(destroytemps),0);
  612. reference_reset(destroytemps.envbuf,0,[]);
  613. reference_reset(destroytemps.jmpbuf,0,[]);
  614. reference_reset(destroytemps.reasonbuf,0,[]);
  615. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  616. { the flowcontrol from the default except-block must be merged
  617. with the flowcontrol flags potentially set by the
  618. on-statements handled above (secondpass(right)), as they are
  619. at the same program level }
  620. flowcontrol:=
  621. flowcontrol+
  622. afteronflowcontrol;
  623. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  624. { the 'exit' block }
  625. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  626. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  627. current_asmdata.getjumplabel(NewCurrExitLabel);
  628. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  629. { the 'break' block }
  630. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  631. if in_loop then
  632. begin
  633. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  634. current_asmdata.getjumplabel(NewBreakLabel);
  635. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  636. end;
  637. { the 'continue' block }
  638. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  639. if in_loop then
  640. begin
  641. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  642. current_asmdata.getjumplabel(NewContinueLabel);
  643. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  644. end;
  645. secondpass(t1);
  646. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,destroytemps,doobjectdestroyandreraisestate,nil);
  647. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  648. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4));
  649. { exit the 'continue' block }
  650. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  651. if in_loop then
  652. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  653. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  654. begin
  655. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  656. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  657. end;
  658. { exit the 'break' block }
  659. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  660. if in_loop then
  661. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  662. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  663. begin
  664. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  665. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  666. end;
  667. { exit the 'exit' block }
  668. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  669. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  670. if fc_exit 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,oldCurrExitLabel));
  674. end;
  675. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  676. if in_loop then
  677. begin
  678. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  679. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  680. end;
  681. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  682. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  683. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  684. end
  685. else
  686. begin
  687. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  688. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  689. end;
  690. end
  691. else
  692. begin
  693. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_legacy_rethrow,0));
  694. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  695. end;
  696. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  697. errorexit:
  698. { return all used control flow statements }
  699. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  700. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  701. end;
  702. procedure twasmtryexceptnode.pass_generate_code_bf_exceptions;
  703. var
  704. trystate,doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  705. destroytemps,
  706. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  707. afteronflowcontrol: tflowcontrol;
  708. oldCurrRaiseLabel,
  709. oldCurrExitLabel,
  710. oldContinueLabel,
  711. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  712. NewCurrExitLabel, NewCurrRaiseLabel: tasmlabel;
  713. in_loop: Boolean;
  714. label
  715. errorexit;
  716. begin
  717. oldCurrRaiseLabel:=nil;
  718. oldCurrExitLabel:=nil;
  719. oldContinueLabel:=nil;
  720. oldBreakLabel:=nil;
  721. NewContinueLabel:=nil;
  722. NewBreakLabel:=nil;
  723. NewCurrRaiseLabel:=nil;
  724. location_reset(location,LOC_VOID,OS_NO);
  725. doobjectdestroyandreraisestate:=Default(tcgexceptionstatehandler.texceptionstate);
  726. { Exception temps? We don't need no stinking exception temps! :) }
  727. fillchar(excepttemps,sizeof(excepttemps),0);
  728. reference_reset(excepttemps.envbuf,0,[]);
  729. reference_reset(excepttemps.jmpbuf,0,[]);
  730. reference_reset(excepttemps.reasonbuf,0,[]);
  731. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  732. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,trystate);
  733. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  734. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  735. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  736. current_asmdata.getjumplabel(NewCurrRaiseLabel);
  737. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
  738. { try block }
  739. secondpass(left);
  740. if codegenerror then
  741. goto errorexit;
  742. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,trystate,nil);
  743. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1));
  744. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  745. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
  746. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  747. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
  748. flowcontrol:=[fc_inflowcontrol]+trystate.oldflowcontrol*[fc_catching_exceptions];
  749. { on statements }
  750. if assigned(right) then
  751. secondpass(right);
  752. afteronflowcontrol:=flowcontrol;
  753. { default handling except handling }
  754. if assigned(t1) then
  755. begin
  756. { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
  757. it doesn't change any state and its return value is ignored (Sergei)
  758. }
  759. { the destruction of the exception object must be also }
  760. { guarded by an exception frame, but it can be omitted }
  761. { if there's no user code in 'except' block }
  762. if not (has_no_code(t1)) then
  763. begin
  764. { if there is an outer frame that catches exceptions, remember this for the "except"
  765. part of this try/except }
  766. flowcontrol:=trystate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  767. { Exception temps? We don't need no stinking exception temps! :) }
  768. fillchar(excepttemps,sizeof(destroytemps),0);
  769. reference_reset(destroytemps.envbuf,0,[]);
  770. reference_reset(destroytemps.jmpbuf,0,[]);
  771. reference_reset(destroytemps.reasonbuf,0,[]);
  772. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,destroytemps,tek_except,doobjectdestroyandreraisestate);
  773. { the flowcontrol from the default except-block must be merged
  774. with the flowcontrol flags potentially set by the
  775. on-statements handled above (secondpass(right)), as they are
  776. at the same program level }
  777. flowcontrol:=
  778. flowcontrol+
  779. afteronflowcontrol;
  780. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  781. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  782. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  783. current_asmdata.getjumplabel(NewCurrRaiseLabel);
  784. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
  785. { the 'exit' block }
  786. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  787. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  788. current_asmdata.getjumplabel(NewCurrExitLabel);
  789. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  790. { the 'break' block }
  791. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  792. if in_loop then
  793. begin
  794. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  795. current_asmdata.getjumplabel(NewBreakLabel);
  796. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  797. end;
  798. { the 'continue' block }
  799. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  800. if in_loop then
  801. begin
  802. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  803. current_asmdata.getjumplabel(NewContinueLabel);
  804. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  805. end;
  806. secondpass(t1);
  807. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,destroytemps,doobjectdestroyandreraisestate,nil);
  808. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  809. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4));
  810. { exit the 'continue' block }
  811. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  812. if in_loop then
  813. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  814. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  815. begin
  816. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  817. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,OldContinueLabel));
  818. end;
  819. { exit the 'break' block }
  820. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  821. if in_loop then
  822. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  823. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  824. begin
  825. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  826. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,OldBreakLabel));
  827. end;
  828. { exit the 'exit' block }
  829. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  830. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  831. if fc_exit 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,oldCurrExitLabel));
  835. end;
  836. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  837. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
  838. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  839. if in_loop then
  840. begin
  841. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  842. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  843. end;
  844. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
  845. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  846. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  847. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  848. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  849. end
  850. else
  851. begin
  852. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  853. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  854. end;
  855. end
  856. else
  857. begin
  858. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  859. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  860. doobjectdestroyandreraisestate.newflowcontrol:=afteronflowcontrol;
  861. end;
  862. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  863. errorexit:
  864. { return all used control flow statements }
  865. flowcontrol:=trystate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol +
  866. trystate.newflowcontrol - [fc_inflowcontrol,fc_catching_exceptions]);
  867. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=OldCurrRaiseLabel;
  868. end;
  869. procedure twasmtryexceptnode.pass_generate_code;
  870. begin
  871. if ts_wasm_no_exceptions in current_settings.targetswitches then
  872. pass_generate_code_no_exceptions
  873. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  874. pass_generate_code_native_exnref_exceptions
  875. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  876. pass_generate_code_native_legacy_exceptions
  877. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  878. pass_generate_code_bf_exceptions
  879. else
  880. internalerror(2021091705);
  881. end;
  882. {*****************************************************************************
  883. twasmtryfinallynode
  884. *****************************************************************************}
  885. procedure twasmtryfinallynode.pass_generate_code_no_exceptions;
  886. var
  887. exitfinallylabel,
  888. continuefinallylabel,
  889. breakfinallylabel,
  890. oldCurrExitLabel,
  891. oldContinueLabel,
  892. oldBreakLabel: tasmlabel;
  893. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  894. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  895. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  896. in_loop: Boolean;
  897. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  898. var
  899. reasonreg : tregister;
  900. begin
  901. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  902. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  903. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  904. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  905. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  906. end;
  907. procedure generate_exceptreason_check_br(reason: tcgint; l: TAsmLabel);
  908. var
  909. reasonreg : tregister;
  910. begin
  911. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  912. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  913. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  914. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  915. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  916. end;
  917. begin
  918. location_reset(location,LOC_VOID,OS_NO);
  919. oldBreakLabel:=nil;
  920. oldContinueLabel:=nil;
  921. continuefinallylabel:=nil;
  922. breakfinallylabel:=nil;
  923. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  924. if not implicitframe then
  925. exceptframekind:=tek_normalfinally
  926. else
  927. exceptframekind:=tek_implicitfinally;
  928. { in 'no exceptions' mode, we still want to handle properly exit,
  929. continue and break (they still need to execute the 'finally'
  930. statements), so for this we need excepttemps.reasonbuf, and for this
  931. reason, we need to allocate excepttemps }
  932. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  933. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  934. { the finally block must catch break, continue and exit }
  935. { statements }
  936. { the outer 'try..finally' block }
  937. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  938. { the 'exit' block }
  939. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  940. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  941. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  942. current_procinfo.CurrExitLabel:=exitfinallylabel;
  943. { the 'break' block }
  944. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  945. if in_loop then
  946. begin
  947. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  948. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  949. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  950. end;
  951. { the 'continue' block }
  952. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  953. if in_loop then
  954. begin
  955. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  956. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  957. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  958. end;
  959. { try code }
  960. if assigned(left) then
  961. begin
  962. secondpass(left);
  963. if codegenerror then
  964. exit;
  965. end;
  966. { don't generate line info for internal cleanup }
  967. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  968. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  969. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  970. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  971. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,3)); // jump to the 'finally' section
  972. { exit the 'continue' block }
  973. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  974. if in_loop then
  975. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  976. { exceptionreason:=4 (continue) }
  977. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  978. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  979. { exit the 'break' block }
  980. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  981. if in_loop then
  982. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  983. { exceptionreason:=3 (break) }
  984. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  985. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  986. { exit the 'exit' block }
  987. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  988. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  989. { exceptionreason:=2 (exit) }
  990. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  991. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  992. { exit the outer 'try..finally' block }
  993. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  994. { end cleanup }
  995. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  996. { finally code (don't unconditionally set fc_inflowcontrol, since the
  997. finally code is unconditionally executed; we do have to filter out
  998. flags regarding break/contrinue/etc. because we have to give an
  999. error in case one of those is used in the finally-code }
  1000. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1001. secondpass(right);
  1002. { goto is allowed if it stays inside the finally block,
  1003. this is checked using the exception block number }
  1004. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1005. CGMessage(cg_e_control_flow_outside_finally);
  1006. if codegenerror then
  1007. exit;
  1008. { don't generate line info for internal cleanup }
  1009. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1010. if fc_exit in finallyexceptionstate.newflowcontrol then
  1011. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1012. if fc_break in finallyexceptionstate.newflowcontrol then
  1013. generate_exceptreason_check_br(3,oldBreakLabel);
  1014. if fc_continue in finallyexceptionstate.newflowcontrol then
  1015. generate_exceptreason_check_br(4,oldContinueLabel);
  1016. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1017. { end cleanup }
  1018. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1019. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1020. if assigned(current_procinfo.CurrBreakLabel) then
  1021. begin
  1022. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1023. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1024. end;
  1025. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1026. end;
  1027. procedure twasmtryfinallynode.pass_generate_code_native_exnref_exceptions;
  1028. var
  1029. exitfinallylabel,
  1030. continuefinallylabel,
  1031. breakfinallylabel,
  1032. oldCurrExitLabel,
  1033. oldContinueLabel,
  1034. oldBreakLabel: tasmlabel;
  1035. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  1036. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  1037. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  1038. in_loop: Boolean;
  1039. try_table: taicpu;
  1040. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  1041. var
  1042. reasonreg : tregister;
  1043. begin
  1044. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1045. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1046. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1047. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  1048. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1049. end;
  1050. procedure generate_exceptreason_check_br(reason: tcgint; l: tasmlabel);
  1051. var
  1052. reasonreg : tregister;
  1053. begin
  1054. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1055. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1056. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1057. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  1058. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1059. end;
  1060. procedure generate_exceptreason_throw(reason: tcgint);
  1061. var
  1062. reasonreg : tregister;
  1063. begin
  1064. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1065. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1066. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1067. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  1068. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1069. current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_legacy_throw,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1070. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  1071. end;
  1072. begin
  1073. location_reset(location,LOC_VOID,OS_NO);
  1074. oldBreakLabel:=nil;
  1075. oldContinueLabel:=nil;
  1076. continuefinallylabel:=nil;
  1077. breakfinallylabel:=nil;
  1078. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1079. if not implicitframe then
  1080. exceptframekind:=tek_normalfinally
  1081. else
  1082. exceptframekind:=tek_implicitfinally;
  1083. { in 'no exceptions' mode, we still want to handle properly exit,
  1084. continue and break (they still need to execute the 'finally'
  1085. statements), so for this we need excepttemps.reasonbuf, and for this
  1086. reason, we need to allocate excepttemps }
  1087. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1088. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  1089. { the finally block must catch break, continue and exit }
  1090. { statements }
  1091. { the outer 'try..finally' block }
  1092. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1093. { the 'exit' block }
  1094. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1095. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1096. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1097. current_procinfo.CurrExitLabel:=exitfinallylabel;
  1098. { the 'break' block }
  1099. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1100. if in_loop then
  1101. begin
  1102. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1103. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1104. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  1105. end;
  1106. { the 'continue' block }
  1107. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1108. if in_loop then
  1109. begin
  1110. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1111. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1112. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  1113. end;
  1114. { the 'catch' block }
  1115. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1116. { the inner 'try_table..end_try_table' block }
  1117. try_table:=taicpu.op_none(a_try_table);
  1118. try_table.try_table_catch_clauses.Concat(taicpu.op_sym_const(a_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG),0));
  1119. current_asmdata.CurrAsmList.concat(try_table);
  1120. { try code }
  1121. if assigned(left) then
  1122. begin
  1123. secondpass(left);
  1124. if codegenerror then
  1125. exit;
  1126. end;
  1127. { don't generate line info for internal cleanup }
  1128. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1129. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  1130. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  1131. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  1132. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,5)); // jump to the 'finally' section
  1133. { exit the inner 'try_table..end_try_table' block }
  1134. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_try_table));
  1135. { exceptionreason:=1 (exception) }
  1136. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,1,excepttemps.reasonbuf);
  1137. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1138. { exit the 'catch' block }
  1139. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1140. { exit the 'continue' block }
  1141. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1142. if in_loop then
  1143. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  1144. { exceptionreason:=4 (continue) }
  1145. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  1146. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  1147. { exit the 'break' block }
  1148. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1149. if in_loop then
  1150. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  1151. { exceptionreason:=3 (break) }
  1152. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  1153. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  1154. { exit the 'exit' block }
  1155. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1156. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  1157. { exceptionreason:=2 (exit) }
  1158. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  1159. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1160. { exit the outer 'try..finally' block }
  1161. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1162. { end cleanup }
  1163. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1164. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1165. finally code is unconditionally executed; we do have to filter out
  1166. flags regarding break/contrinue/etc. because we have to give an
  1167. error in case one of those is used in the finally-code }
  1168. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1169. secondpass(right);
  1170. { goto is allowed if it stays inside the finally block,
  1171. this is checked using the exception block number }
  1172. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1173. CGMessage(cg_e_control_flow_outside_finally);
  1174. if codegenerror then
  1175. exit;
  1176. { don't generate line info for internal cleanup }
  1177. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1178. if fc_exit in finallyexceptionstate.newflowcontrol then
  1179. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1180. if fc_break in finallyexceptionstate.newflowcontrol then
  1181. generate_exceptreason_check_br(3,oldBreakLabel);
  1182. if fc_continue in finallyexceptionstate.newflowcontrol then
  1183. generate_exceptreason_check_br(4,oldContinueLabel);
  1184. generate_exceptreason_throw(1);
  1185. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1186. { end cleanup }
  1187. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1188. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1189. if assigned(current_procinfo.CurrBreakLabel) then
  1190. begin
  1191. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1192. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1193. end;
  1194. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1195. end;
  1196. procedure twasmtryfinallynode.pass_generate_code_native_legacy_exceptions;
  1197. var
  1198. exitfinallylabel,
  1199. continuefinallylabel,
  1200. breakfinallylabel,
  1201. oldCurrExitLabel,
  1202. oldContinueLabel,
  1203. oldBreakLabel: tasmlabel;
  1204. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  1205. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  1206. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  1207. in_loop: Boolean;
  1208. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  1209. var
  1210. reasonreg : tregister;
  1211. begin
  1212. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1213. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1214. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1215. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  1216. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1217. end;
  1218. procedure generate_exceptreason_check_br(reason: tcgint; l: tasmlabel);
  1219. var
  1220. reasonreg : tregister;
  1221. begin
  1222. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1223. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1224. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1225. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  1226. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1227. end;
  1228. procedure generate_exceptreason_throw(reason: tcgint);
  1229. var
  1230. reasonreg : tregister;
  1231. begin
  1232. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1233. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1234. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1235. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  1236. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1237. current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_legacy_throw,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1238. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  1239. end;
  1240. begin
  1241. location_reset(location,LOC_VOID,OS_NO);
  1242. oldBreakLabel:=nil;
  1243. oldContinueLabel:=nil;
  1244. continuefinallylabel:=nil;
  1245. breakfinallylabel:=nil;
  1246. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1247. if not implicitframe then
  1248. exceptframekind:=tek_normalfinally
  1249. else
  1250. exceptframekind:=tek_implicitfinally;
  1251. { in 'no exceptions' mode, we still want to handle properly exit,
  1252. continue and break (they still need to execute the 'finally'
  1253. statements), so for this we need excepttemps.reasonbuf, and for this
  1254. reason, we need to allocate excepttemps }
  1255. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1256. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  1257. { the finally block must catch break, continue and exit }
  1258. { statements }
  1259. { the outer 'try..finally' block }
  1260. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1261. { the 'exit' block }
  1262. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1263. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1264. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1265. current_procinfo.CurrExitLabel:=exitfinallylabel;
  1266. { the 'break' block }
  1267. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1268. if in_loop then
  1269. begin
  1270. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1271. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1272. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  1273. end;
  1274. { the 'continue' block }
  1275. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1276. if in_loop then
  1277. begin
  1278. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1279. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1280. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  1281. end;
  1282. { the inner 'try..end_try' block }
  1283. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  1284. { try code }
  1285. if assigned(left) then
  1286. begin
  1287. secondpass(left);
  1288. if codegenerror then
  1289. exit;
  1290. end;
  1291. { don't generate line info for internal cleanup }
  1292. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1293. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  1294. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  1295. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  1296. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1297. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1298. { exceptionreason:=1 (exception) }
  1299. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,1,excepttemps.reasonbuf);
  1300. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1301. { exit the inner 'try..end_try' block }
  1302. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  1303. { exit the 'continue' block }
  1304. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1305. if in_loop then
  1306. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  1307. { exceptionreason:=4 (continue) }
  1308. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  1309. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  1310. { exit the 'break' block }
  1311. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1312. if in_loop then
  1313. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  1314. { exceptionreason:=3 (break) }
  1315. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  1316. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  1317. { exit the 'exit' block }
  1318. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1319. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  1320. { exceptionreason:=2 (exit) }
  1321. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  1322. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1323. { exit the outer 'try..finally' block }
  1324. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1325. { end cleanup }
  1326. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1327. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1328. finally code is unconditionally executed; we do have to filter out
  1329. flags regarding break/contrinue/etc. because we have to give an
  1330. error in case one of those is used in the finally-code }
  1331. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1332. secondpass(right);
  1333. { goto is allowed if it stays inside the finally block,
  1334. this is checked using the exception block number }
  1335. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1336. CGMessage(cg_e_control_flow_outside_finally);
  1337. if codegenerror then
  1338. exit;
  1339. { don't generate line info for internal cleanup }
  1340. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1341. if fc_exit in finallyexceptionstate.newflowcontrol then
  1342. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1343. if fc_break in finallyexceptionstate.newflowcontrol then
  1344. generate_exceptreason_check_br(3,oldBreakLabel);
  1345. if fc_continue in finallyexceptionstate.newflowcontrol then
  1346. generate_exceptreason_check_br(4,oldContinueLabel);
  1347. generate_exceptreason_throw(1);
  1348. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1349. { end cleanup }
  1350. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1351. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1352. if assigned(current_procinfo.CurrBreakLabel) then
  1353. begin
  1354. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1355. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1356. end;
  1357. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1358. end;
  1359. procedure twasmtryfinallynode.pass_generate_code_bf_exceptions;
  1360. var
  1361. raisefinallylabel,
  1362. exitfinallylabel,
  1363. continuefinallylabel,
  1364. breakfinallylabel,
  1365. oldCurrRaiseLabel,
  1366. oldCurrExitLabel,
  1367. oldContinueLabel,
  1368. oldBreakLabel: tasmlabel;
  1369. finallyexceptionstate: tcgexceptionstatehandler.texceptionstate;
  1370. excepttemps : tcgexceptionstatehandler.texceptiontemps;
  1371. exceptframekind: tcgexceptionstatehandler.texceptframekind;
  1372. in_loop: Boolean;
  1373. procedure generate_exceptreason_check_br(reason: tcgint; br: aint);
  1374. var
  1375. reasonreg : tregister;
  1376. begin
  1377. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1378. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1379. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1380. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br_if,br));
  1381. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1382. end;
  1383. procedure generate_exceptreason_check_br(reason: tcgint; l: tasmsymbol);
  1384. var
  1385. reasonreg : tregister;
  1386. begin
  1387. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1388. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1389. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1390. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br_if,l));
  1391. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1392. end;
  1393. procedure generate_exceptreason_reraise(reason: tcgint);
  1394. var
  1395. reasonreg : tregister;
  1396. begin
  1397. reasonreg:=hlcg.getintregister(current_asmdata.CurrAsmList,exceptionreasontype);
  1398. hlcg.g_exception_reason_load(current_asmdata.CurrAsmList,exceptionreasontype,exceptionreasontype,excepttemps.reasonbuf,reasonreg);
  1399. thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,exceptionreasontype,OC_EQ,reason,reasonreg);
  1400. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_if));
  1401. thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  1402. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_reraise',[],nil).resetiftemp;
  1403. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  1404. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_if));
  1405. end;
  1406. begin
  1407. location_reset(location,LOC_VOID,OS_NO);
  1408. oldCurrRaiseLabel:=nil;
  1409. oldBreakLabel:=nil;
  1410. oldContinueLabel:=nil;
  1411. continuefinallylabel:=nil;
  1412. breakfinallylabel:=nil;
  1413. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1414. if not implicitframe then
  1415. exceptframekind:=tek_normalfinally
  1416. else
  1417. exceptframekind:=tek_implicitfinally;
  1418. { in 'no exceptions' mode, we still want to handle properly exit,
  1419. continue and break (they still need to execute the 'finally'
  1420. statements), so for this we need excepttemps.reasonbuf, and for this
  1421. reason, we need to allocate excepttemps }
  1422. cexceptionstatehandler.get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1423. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,exceptframekind,finallyexceptionstate);
  1424. { the finally block must catch break, continue and exit }
  1425. { statements }
  1426. { the outer 'try..finally' block }
  1427. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1428. { the 'exit' block }
  1429. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1430. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1431. exitfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1432. current_procinfo.CurrExitLabel:=exitfinallylabel;
  1433. { the 'break' block }
  1434. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1435. if in_loop then
  1436. begin
  1437. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1438. breakfinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1439. current_procinfo.CurrBreakLabel:=breakfinallylabel;
  1440. end;
  1441. { the 'continue' block }
  1442. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1443. if in_loop then
  1444. begin
  1445. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1446. continuefinallylabel:=get_jump_out_of_try_finally_frame_label(finallyexceptionstate);
  1447. current_procinfo.CurrContinueLabel:=continuefinallylabel;
  1448. end;
  1449. { the inner 'try..end_try' block }
  1450. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1451. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  1452. current_asmdata.getjumplabel(raisefinallylabel);
  1453. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=raisefinallylabel;
  1454. { try code }
  1455. if assigned(left) then
  1456. begin
  1457. secondpass(left);
  1458. if codegenerror then
  1459. exit;
  1460. end;
  1461. { don't generate line info for internal cleanup }
  1462. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1463. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,exceptframekind,excepttemps,finallyexceptionstate,nil);
  1464. { we've reached the end of the 'try' block, with no exceptions/exit/break/continue, so set exceptionreason:=0 }
  1465. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,0,excepttemps.reasonbuf);
  1466. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,4)); // jump to the 'finally' section
  1467. { exit the inner 'try..end_try' block }
  1468. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1469. hlcg.a_label(current_asmdata.CurrAsmList,raisefinallylabel);
  1470. { exceptionreason:=1 (exception) }
  1471. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  1472. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,1,excepttemps.reasonbuf);
  1473. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,3)); // jump to the 'finally' section
  1474. { exit the 'continue' block }
  1475. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1476. if in_loop then
  1477. hlcg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
  1478. { exceptionreason:=4 (continue) }
  1479. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,4,excepttemps.reasonbuf);
  1480. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,2)); // jump to the 'finally' section
  1481. { exit the 'break' block }
  1482. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1483. if in_loop then
  1484. hlcg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
  1485. { exceptionreason:=3 (break) }
  1486. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,3,excepttemps.reasonbuf);
  1487. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,1)); // jump to the 'finally' section
  1488. { exit the 'exit' block }
  1489. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1490. hlcg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
  1491. { exceptionreason:=2 (exit) }
  1492. hlcg.g_exception_reason_save_const(current_asmdata.CurrAsmList,exceptionreasontype,2,excepttemps.reasonbuf);
  1493. { proceed to the 'finally' section, which follow immediately, no need for jumps }
  1494. { exit the outer 'try..finally' block }
  1495. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1496. { end cleanup }
  1497. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1498. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=oldCurrRaiseLabel;
  1499. { finally code (don't unconditionally set fc_inflowcontrol, since the
  1500. finally code is unconditionally executed; we do have to filter out
  1501. flags regarding break/contrinue/etc. because we have to give an
  1502. error in case one of those is used in the finally-code }
  1503. flowcontrol:=finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions];
  1504. secondpass(right);
  1505. { goto is allowed if it stays inside the finally block,
  1506. this is checked using the exception block number }
  1507. if (flowcontrol-[fc_gotolabel])<>(finallyexceptionstate.oldflowcontrol*[fc_inflowcontrol,fc_catching_exceptions]) then
  1508. CGMessage(cg_e_control_flow_outside_finally);
  1509. if codegenerror then
  1510. exit;
  1511. { don't generate line info for internal cleanup }
  1512. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
  1513. if fc_exit in finallyexceptionstate.newflowcontrol then
  1514. generate_exceptreason_check_br(2,oldCurrExitLabel);
  1515. if fc_break in finallyexceptionstate.newflowcontrol then
  1516. generate_exceptreason_check_br(3,oldBreakLabel);
  1517. if fc_continue in finallyexceptionstate.newflowcontrol then
  1518. generate_exceptreason_check_br(4,oldContinueLabel);
  1519. generate_exceptreason_reraise(1);
  1520. cexceptionstatehandler.unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
  1521. { end cleanup }
  1522. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
  1523. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1524. if assigned(current_procinfo.CurrBreakLabel) then
  1525. begin
  1526. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1527. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1528. end;
  1529. flowcontrol:=finallyexceptionstate.oldflowcontrol+(finallyexceptionstate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1530. end;
  1531. procedure twasmtryfinallynode.pass_generate_code;
  1532. begin
  1533. if ts_wasm_no_exceptions in current_settings.targetswitches then
  1534. pass_generate_code_no_exceptions
  1535. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  1536. pass_generate_code_native_exnref_exceptions
  1537. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  1538. pass_generate_code_native_legacy_exceptions
  1539. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  1540. pass_generate_code_bf_exceptions
  1541. else
  1542. internalerror(2021091704);
  1543. end;
  1544. {*****************************************************************************
  1545. twasmonnode
  1546. *****************************************************************************}
  1547. procedure twasmonnode.pass_generate_code_no_exceptions;
  1548. begin
  1549. { should not be called }
  1550. internalerror(2021092803);
  1551. end;
  1552. procedure twasmonnode.pass_generate_code_native_exnref_exceptions;
  1553. var
  1554. exceptvarsym : tlocalvarsym;
  1555. exceptlocdef: tdef;
  1556. exceptlocreg: tregister;
  1557. oldCurrExitLabel,
  1558. oldContinueLabel,
  1559. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  1560. NewCurrExitLabel: tasmlabel;
  1561. in_loop: Boolean;
  1562. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  1563. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  1564. begin
  1565. oldCurrExitLabel:=nil;
  1566. oldContinueLabel:=nil;
  1567. oldBreakLabel:=nil;
  1568. NewBreakLabel:=nil;
  1569. NewContinueLabel:=nil;
  1570. location_reset(location,LOC_VOID,OS_NO);
  1571. { Exception temps? We don't need no stinking exception temps! :) }
  1572. fillchar(excepttemps,sizeof(excepttemps),0);
  1573. reference_reset(excepttemps.envbuf,0,[]);
  1574. reference_reset(excepttemps.jmpbuf,0,[]);
  1575. reference_reset(excepttemps.reasonbuf,0,[]);
  1576. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1577. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nil,exceptlocdef,exceptlocreg);
  1578. { Retrieve exception variable }
  1579. if assigned(excepTSymtable) then
  1580. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  1581. else
  1582. internalerror(2011020401);
  1583. if assigned(exceptvarsym) then
  1584. begin
  1585. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  1586. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  1587. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  1588. end;
  1589. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  1590. { in the case that another exception is risen
  1591. we've to destroy the old one, so create a new
  1592. exception frame for the catch-handler }
  1593. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  1594. { the 'exit' block }
  1595. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1596. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1597. current_asmdata.getjumplabel(NewCurrExitLabel);
  1598. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  1599. { the 'break' block }
  1600. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1601. if in_loop then
  1602. begin
  1603. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1604. current_asmdata.getjumplabel(NewBreakLabel);
  1605. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  1606. end;
  1607. { the 'continue' block }
  1608. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1609. if in_loop then
  1610. begin
  1611. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1612. current_asmdata.getjumplabel(NewContinueLabel);
  1613. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  1614. end;
  1615. if assigned(right) then
  1616. secondpass(right);
  1617. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,doobjectdestroyandreraisestate,nil);
  1618. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1619. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,5));
  1620. { exit the 'continue' block }
  1621. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1622. if in_loop then
  1623. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  1624. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  1625. begin
  1626. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1627. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  1628. end;
  1629. { exit the 'break' block }
  1630. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  1631. if in_loop then
  1632. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  1633. if fc_break in doobjectdestroyandreraisestate.newflowcontrol then
  1634. begin
  1635. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1636. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldBreakLabel));
  1637. end;
  1638. { exit the 'exit' block }
  1639. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  1640. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  1641. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  1642. begin
  1643. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1644. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  1645. end;
  1646. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1647. if in_loop then
  1648. begin
  1649. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1650. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1651. end;
  1652. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1653. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  1654. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  1655. { clear some stuff }
  1656. if assigned(exceptvarsym) then
  1657. begin
  1658. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  1659. exceptvarsym.localloc.loc:=LOC_INVALID;
  1660. end;
  1661. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  1662. { propagate exit/break/continue }
  1663. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1664. { next on node }
  1665. if assigned(left) then
  1666. secondpass(left);
  1667. end;
  1668. procedure twasmonnode.pass_generate_code_native_legacy_exceptions;
  1669. var
  1670. exceptvarsym : tlocalvarsym;
  1671. exceptlocdef: tdef;
  1672. exceptlocreg: tregister;
  1673. oldCurrExitLabel,
  1674. oldContinueLabel,
  1675. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  1676. NewCurrExitLabel: tasmlabel;
  1677. in_loop: Boolean;
  1678. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  1679. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  1680. begin
  1681. oldCurrExitLabel:=nil;
  1682. oldContinueLabel:=nil;
  1683. oldBreakLabel:=nil;
  1684. NewBreakLabel:=nil;
  1685. NewContinueLabel:=nil;
  1686. location_reset(location,LOC_VOID,OS_NO);
  1687. { Exception temps? We don't need no stinking exception temps! :) }
  1688. fillchar(excepttemps,sizeof(excepttemps),0);
  1689. reference_reset(excepttemps.envbuf,0,[]);
  1690. reference_reset(excepttemps.jmpbuf,0,[]);
  1691. reference_reset(excepttemps.reasonbuf,0,[]);
  1692. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1693. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nil,exceptlocdef,exceptlocreg);
  1694. { Retrieve exception variable }
  1695. if assigned(excepTSymtable) then
  1696. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  1697. else
  1698. internalerror(2011020401);
  1699. if assigned(exceptvarsym) then
  1700. begin
  1701. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  1702. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  1703. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  1704. end;
  1705. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  1706. { in the case that another exception is risen
  1707. we've to destroy the old one, so create a new
  1708. exception frame for the catch-handler }
  1709. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_legacy_try));
  1710. { the 'exit' block }
  1711. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1712. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1713. current_asmdata.getjumplabel(NewCurrExitLabel);
  1714. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  1715. { the 'break' block }
  1716. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1717. if in_loop then
  1718. begin
  1719. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1720. current_asmdata.getjumplabel(NewBreakLabel);
  1721. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  1722. end;
  1723. { the 'continue' block }
  1724. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1725. if in_loop then
  1726. begin
  1727. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1728. current_asmdata.getjumplabel(NewContinueLabel);
  1729. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  1730. end;
  1731. if assigned(right) then
  1732. secondpass(right);
  1733. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,doobjectdestroyandreraisestate,nil);
  1734. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1735. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,5));
  1736. { exit the 'continue' block }
  1737. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1738. if in_loop then
  1739. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  1740. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  1741. begin
  1742. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1743. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  1744. end;
  1745. { exit the 'break' block }
  1746. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  1747. if in_loop then
  1748. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  1749. if fc_break 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,oldBreakLabel));
  1753. end;
  1754. { exit the 'exit' block }
  1755. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  1756. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  1757. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  1758. begin
  1759. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1760. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  1761. end;
  1762. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1763. if in_loop then
  1764. begin
  1765. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1766. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1767. end;
  1768. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_legacy_catch,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));
  1769. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  1770. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_legacy_try));
  1771. { clear some stuff }
  1772. if assigned(exceptvarsym) then
  1773. begin
  1774. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  1775. exceptvarsym.localloc.loc:=LOC_INVALID;
  1776. end;
  1777. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  1778. { propagate exit/break/continue }
  1779. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1780. { next on node }
  1781. if assigned(left) then
  1782. secondpass(left);
  1783. end;
  1784. procedure twasmonnode.pass_generate_code_bf_exceptions;
  1785. var
  1786. exceptvarsym : tlocalvarsym;
  1787. exceptlocdef: tdef;
  1788. exceptlocreg: tregister;
  1789. oldCurrRaiseLabel,
  1790. oldCurrExitLabel,
  1791. oldContinueLabel,
  1792. oldBreakLabel, NewContinueLabel, NewBreakLabel,
  1793. NewCurrRaiseLabel, NewCurrExitLabel: tasmlabel;
  1794. in_loop: Boolean;
  1795. doobjectdestroyandreraisestate: tcgexceptionstatehandler.texceptionstate;
  1796. excepttemps: tcgexceptionstatehandler.texceptiontemps;
  1797. begin
  1798. oldCurrRaiseLabel:=nil;
  1799. oldCurrExitLabel:=nil;
  1800. oldContinueLabel:=nil;
  1801. oldBreakLabel:=nil;
  1802. NewCurrRaiseLabel:=nil;
  1803. NewBreakLabel:=nil;
  1804. NewContinueLabel:=nil;
  1805. location_reset(location,LOC_VOID,OS_NO);
  1806. { Exception temps? We don't need no stinking exception temps! :) }
  1807. fillchar(excepttemps,sizeof(excepttemps),0);
  1808. reference_reset(excepttemps.envbuf,0,[]);
  1809. reference_reset(excepttemps.jmpbuf,0,[]);
  1810. reference_reset(excepttemps.reasonbuf,0,[]);
  1811. in_loop:=assigned(current_procinfo.CurrBreakLabel);
  1812. cexceptionstatehandler.begin_catch(current_asmdata.CurrAsmList,excepttype,nil,exceptlocdef,exceptlocreg);
  1813. { Retrieve exception variable }
  1814. if assigned(excepTSymtable) then
  1815. exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
  1816. else
  1817. internalerror(2011020401);
  1818. if assigned(exceptvarsym) then
  1819. begin
  1820. location_reset_ref(exceptvarsym.localloc, LOC_REFERENCE, def_cgsize(voidpointertype), voidpointertype.alignment, []);
  1821. tg.GetLocal(current_asmdata.CurrAsmList, exceptvarsym.vardef.size, exceptvarsym.vardef, exceptvarsym.localloc.reference);
  1822. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList, exceptlocdef, exceptvarsym.vardef, exceptlocreg, exceptvarsym.localloc.reference);
  1823. end;
  1824. cexceptionstatehandler.new_exception(current_asmdata.CurrAsmList,excepttemps,tek_except,doobjectdestroyandreraisestate);
  1825. { in the case that another exception is risen
  1826. we've to destroy the old one, so create a new
  1827. exception frame for the catch-handler }
  1828. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1829. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1830. oldCurrRaiseLabel:=tcpuprocinfo(current_procinfo).CurrRaiseLabel;
  1831. current_asmdata.getjumplabel(NewCurrRaiseLabel);
  1832. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=NewCurrRaiseLabel;
  1833. { the 'exit' block }
  1834. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1835. oldCurrExitLabel:=current_procinfo.CurrExitLabel;
  1836. current_asmdata.getjumplabel(NewCurrExitLabel);
  1837. current_procinfo.CurrExitLabel:=NewCurrExitLabel;
  1838. { the 'break' block }
  1839. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1840. if in_loop then
  1841. begin
  1842. oldBreakLabel:=current_procinfo.CurrBreakLabel;
  1843. current_asmdata.getjumplabel(NewBreakLabel);
  1844. current_procinfo.CurrBreakLabel:=NewBreakLabel;
  1845. end;
  1846. { the 'continue' block }
  1847. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_block));
  1848. if in_loop then
  1849. begin
  1850. oldContinueLabel:=current_procinfo.CurrContinueLabel;
  1851. current_asmdata.getjumplabel(NewContinueLabel);
  1852. current_procinfo.CurrContinueLabel:=NewContinueLabel;
  1853. end;
  1854. if assigned(right) then
  1855. secondpass(right);
  1856. cexceptionstatehandler.end_try_block(current_asmdata.CurrAsmList,tek_except,excepttemps,doobjectdestroyandreraisestate,nil);
  1857. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1858. current_asmdata.CurrAsmList.concat(taicpu.op_const(a_br,6));
  1859. { exit the 'continue' block }
  1860. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1861. if in_loop then
  1862. hlcg.a_label(current_asmdata.CurrAsmList,NewContinueLabel);
  1863. if fc_continue in doobjectdestroyandreraisestate.newflowcontrol then
  1864. begin
  1865. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1866. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldContinueLabel));
  1867. end;
  1868. { exit the 'break' block }
  1869. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // break
  1870. if in_loop then
  1871. hlcg.a_label(current_asmdata.CurrAsmList,NewBreakLabel);
  1872. if fc_break 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,oldBreakLabel));
  1876. end;
  1877. { exit the 'exit' block }
  1878. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block)); // exit
  1879. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrExitLabel);
  1880. if fc_exit in doobjectdestroyandreraisestate.newflowcontrol then
  1881. begin
  1882. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_doneexception',[],nil).resetiftemp;
  1883. current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_br,oldCurrExitLabel));
  1884. end;
  1885. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1886. hlcg.a_label(current_asmdata.CurrAsmList,NewCurrRaiseLabel);
  1887. current_procinfo.CurrExitLabel:=oldCurrExitLabel;
  1888. if in_loop then
  1889. begin
  1890. current_procinfo.CurrContinueLabel:=oldContinueLabel;
  1891. current_procinfo.CurrBreakLabel:=oldBreakLabel;
  1892. end;
  1893. tcpuprocinfo(current_procinfo).CurrRaiseLabel:=oldCurrRaiseLabel;
  1894. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_clear_exception_flag',[],nil).resetiftemp;
  1895. hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_raise_nested',[],nil).resetiftemp;
  1896. hlcg.g_maybe_checkforexceptions(current_asmdata.CurrAsmList);
  1897. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_end_block));
  1898. { clear some stuff }
  1899. if assigned(exceptvarsym) then
  1900. begin
  1901. tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
  1902. exceptvarsym.localloc.loc:=LOC_INVALID;
  1903. end;
  1904. cexceptionstatehandler.end_catch(current_asmdata.CurrAsmList);
  1905. { propagate exit/break/continue }
  1906. flowcontrol:=doobjectdestroyandreraisestate.oldflowcontrol+(doobjectdestroyandreraisestate.newflowcontrol-[fc_inflowcontrol,fc_catching_exceptions]);
  1907. { next on node }
  1908. if assigned(left) then
  1909. secondpass(left);
  1910. end;
  1911. procedure twasmonnode.pass_generate_code;
  1912. begin
  1913. if ts_wasm_no_exceptions in current_settings.targetswitches then
  1914. pass_generate_code_no_exceptions
  1915. else if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  1916. pass_generate_code_native_exnref_exceptions
  1917. else if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  1918. pass_generate_code_native_legacy_exceptions
  1919. else if ts_wasm_bf_exceptions in current_settings.targetswitches then
  1920. pass_generate_code_bf_exceptions
  1921. else
  1922. internalerror(2021092802);
  1923. end;
  1924. initialization
  1925. cifnode:=twasmifnode;
  1926. cwhilerepeatnode:=twasmwhilerepeatnode;
  1927. craisenode:=twasmraisenode;
  1928. ctryexceptnode:=twasmtryexceptnode;
  1929. ctryfinallynode:=twasmtryfinallynode;
  1930. connode:=twasmonnode;
  1931. end.