@@ -488,6 +488,7 @@ class CWriter {
488488 void WriteTryDelegate (const TryExpr& tryexpr);
489489 void Write (const TryTableExpr& try_table_expr);
490490 void Write (const Catch& c);
491+ void Write (const TableCatch& c);
491492 void WriteThrow ();
492493
493494 void PushTryCatch (const std::string& name);
@@ -647,6 +648,7 @@ constexpr char CWriter::MangleType(Type type) {
647648 case Type::V128: return ' o' ;
648649 case Type::FuncRef: return ' r' ;
649650 case Type::ExternRef: return ' e' ;
651+ case Type::ExnRef: return ' x' ;
650652 default :
651653 WABT_UNREACHABLE;
652654 }
@@ -1219,6 +1221,7 @@ const char* CWriter::GetCTypeName(const Type& type) {
12191221 case Type::V128: return " v128" ;
12201222 case Type::FuncRef: return " wasm_rt_funcref_t" ;
12211223 case Type::ExternRef: return " wasm_rt_externref_t" ;
1224+ case Type::ExnRef: return " wasm_rt_exnref_t" ;
12221225 default :
12231226 WABT_UNREACHABLE;
12241227 }
@@ -1239,6 +1242,7 @@ void CWriter::Write(TypeEnum type) {
12391242 case Type::V128: Write (" WASM_RT_V128" ); break ;
12401243 case Type::FuncRef: Write (" WASM_RT_FUNCREF" ); break ;
12411244 case Type::ExternRef: Write (" WASM_RT_EXTERNREF" ); break ;
1245+ case Type::ExnRef: Write (" WASM_RT_EXNREF" ); break ;
12421246 default :
12431247 WABT_UNREACHABLE;
12441248 }
@@ -2285,7 +2289,8 @@ void CWriter::WriteElemInitializerDecls() {
22852289 continue ;
22862290 }
22872291
2288- if (elem_segment->elem_type == Type::ExternRef) {
2292+ if (elem_segment->elem_type == Type::ExternRef ||
2293+ elem_segment->elem_type == Type::ExnRef) {
22892294 // no need to store externref elem initializers because only
22902295 // ref.null is possible
22912296 continue ;
@@ -2357,7 +2362,8 @@ void CWriter::WriteElemInitializers() {
23572362 continue ;
23582363 }
23592364
2360- if (elem_segment->elem_type == Type::ExternRef) {
2365+ if (elem_segment->elem_type == Type::ExternRef ||
2366+ elem_segment->elem_type == Type::ExnRef) {
23612367 // no need to store externref elem initializers because only
23622368 // ref.null is possible
23632369 continue ;
@@ -2461,7 +2467,8 @@ void CWriter::WriteElemTableInit(bool active_initialization,
24612467 const ElemSegment* src_segment,
24622468 const Table* dst_table) {
24632469 assert (dst_table->elem_type == Type::FuncRef ||
2464- dst_table->elem_type == Type::ExternRef);
2470+ dst_table->elem_type == Type::ExternRef ||
2471+ dst_table->elem_type == Type::ExnRef);
24652472 assert (dst_table->elem_type == src_segment->elem_type );
24662473
24672474 Write (GetReferenceTypeName (dst_table->elem_type ), " _table_init(" ,
@@ -3106,7 +3113,7 @@ void CWriter::WriteVarsByType(const Vars& vars,
31063113 const ToDo& todo,
31073114 bool setjmp_safe) {
31083115 for (Type type : {Type::I32, Type::I64, Type::F32, Type::F64, Type::V128,
3109- Type::FuncRef, Type::ExternRef}) {
3116+ Type::FuncRef, Type::ExternRef, Type::ExnRef }) {
31103117 Index var_index = 0 ;
31113118 size_t count = 0 ;
31123119 for (const auto & var : vars) {
@@ -3250,7 +3257,8 @@ void CWriter::WriteLocals(const std::vector<std::string>& index_to_name) {
32503257 func_->local_types , [](auto x) { return x; },
32513258 [&](Index local_index, Type local_type) {
32523259 Write (DefineParamName (index_to_name[num_params + local_index]), " = " );
3253- if (local_type == Type::FuncRef || local_type == Type::ExternRef) {
3260+ if (local_type == Type::FuncRef || local_type == Type::ExternRef ||
3261+ local_type == Type::ExnRef) {
32543262 Write (GetReferenceNullValue (local_type));
32553263 } else if (local_type == Type::V128) {
32563264 Write (" simde_wasm_i64x2_make(0, 0)" );
@@ -3465,9 +3473,82 @@ void CWriter::WriteTryDelegate(const TryExpr& tryexpr) {
34653473}
34663474
34673475void CWriter::Write (const TryTableExpr& try_table_expr) {
3468- // const size_t mark = BeginTry(try_table_expr.block);
3476+ const size_t mark = BeginTry (try_table_expr.block );
34693477
3470- assert (false && " NYI" );
3478+ /* exception has been thrown -- do we catch it? */
3479+
3480+ const LabelName tlabel = LabelName (try_table_expr.block .label );
3481+
3482+ Write (" wasm_rt_set_unwind_target(" , tlabel, " _outer_target);" , Newline ());
3483+ PopTryCatch ();
3484+
3485+ ResetTypeStack (mark);
3486+ assert (!label_stack_.empty ());
3487+ assert (label_stack_.back ().name == try_table_expr.block .label );
3488+ Write (LabelDecl (GetLocalName (try_table_expr.block .label , true )));
3489+ PopLabel ();
3490+
3491+ assert (!try_table_expr.catches .empty ());
3492+ bool has_catch_all{};
3493+ for (auto it = try_table_expr.catches .cbegin ();
3494+ it != try_table_expr.catches .cend (); ++it) {
3495+ if (it == try_table_expr.catches .cbegin ()) {
3496+ Write (Newline ());
3497+ } else {
3498+ Write (" else " );
3499+ }
3500+ ResetTypeStack (mark);
3501+ Write (*it);
3502+ if (it->IsCatchAll ()) {
3503+ has_catch_all = true ;
3504+ break ;
3505+ }
3506+ }
3507+ if (!has_catch_all) {
3508+ /* if not caught, rethrow */
3509+ Write (" else " , OpenBrace ());
3510+ WriteThrow ();
3511+ Write (CloseBrace (), Newline ());
3512+ }
3513+ Write (CloseBrace (), Newline ()); /* end of catch blocks */
3514+ Write (CloseBrace (), Newline ()); /* end of try-catch */
3515+
3516+ ResetTypeStack (mark);
3517+ PushTypes (try_table_expr.block .decl .sig .result_types );
3518+ }
3519+
3520+ void CWriter::Write (const TableCatch& c) {
3521+ if (!c.IsCatchAll ()) {
3522+ Write (" if (wasm_rt_exception_tag() == " ,
3523+ TagSymbol (module_->GetTag (c.tag )->name ), " ) " , OpenBrace ());
3524+
3525+ const Tag* tag = module_->GetTag (c.tag );
3526+ const FuncDeclaration& tag_type = tag->decl ;
3527+ const Index num_params = tag_type.GetNumParams ();
3528+ PushTypes (tag_type.sig .param_types );
3529+ if (num_params == 1 ) {
3530+ Write (" wasm_rt_memcpy(&" , StackVar (0 ), " , wasm_rt_exception(), sizeof(" ,
3531+ tag_type.GetParamType (0 ), " ));" , Newline ());
3532+ } else if (num_params > 1 ) {
3533+ Write (OpenBrace (), tag_type.sig .param_types , " tmp;" , Newline ());
3534+ Write (" wasm_rt_memcpy(&tmp, wasm_rt_exception(), sizeof(tmp));" ,
3535+ Newline ());
3536+ Unspill (tag_type.sig .param_types );
3537+ Write (CloseBrace (), Newline ());
3538+ }
3539+ }
3540+ if (c.IsRef ()) {
3541+ PushType (Type::ExnRef);
3542+ Write (StackVar (0 ), " .tag = wasm_rt_exception_tag();" , Newline ());
3543+ Write (StackVar (0 ), " .size = wasm_rt_exception_size();" , Newline ());
3544+ Write (" wasm_rt_memcpy(&" , StackVar (0 ),
3545+ " .data, wasm_rt_exception(), wasm_rt_exception_size());" , Newline ());
3546+ }
3547+
3548+ Write (GotoLabel (c.target ), Newline ());
3549+ if (!c.IsCatchAll ()) {
3550+ Write (CloseBrace ());
3551+ }
34713552}
34723553
34733554void CWriter::Write (const ExprList& exprs) {
@@ -3869,6 +3950,10 @@ void CWriter::Write(const ExprList& exprs) {
38693950 " == " , GetReferenceNullValue (Type::ExternRef), " );" ,
38703951 Newline ());
38713952 break ;
3953+ case Type::ExnRef:
3954+ Write (StackVar (0 , Type::I32), " = (" , StackVar (0 ), " .tag == NULL" ,
3955+ " );" , Newline ());
3956+ break ;
38723957 default :
38733958 WABT_UNREACHABLE;
38743959 }
@@ -3985,7 +4070,19 @@ void CWriter::Write(const ExprList& exprs) {
39854070 }
39864071
39874072 WriteThrow ();
3988- } break ;
4073+ // Stop processing this ExprList, since the following are unreachable.
4074+ }
4075+ return ;
4076+
4077+ case ExprType::ThrowRef: {
4078+ Write (" if (" , StackVar (0 ), " .tag == NULL) { TRAP(NULL_REF); }" );
4079+ Write (" wasm_rt_load_exception(" , StackVar (0 ), " .tag, " , StackVar (0 ),
4080+ " .size, " , StackVar (0 ), " .data);" , Newline ());
4081+ DropTypes (1 );
4082+ WriteThrow ();
4083+ // Stop processing this ExprList, since the following are unreachable.
4084+ }
4085+ return ;
39894086
39904087 case ExprType::Rethrow: {
39914088 const RethrowExpr* rethrow = cast<RethrowExpr>(&expr);
@@ -4145,7 +4242,6 @@ void CWriter::Write(const ExprList& exprs) {
41454242 case ExprType::AtomicWait:
41464243 case ExprType::AtomicNotify:
41474244 case ExprType::CallRef:
4148- case ExprType::ThrowRef:
41494245 UNIMPLEMENTED (" ..." );
41504246 break ;
41514247 }
@@ -5996,6 +6092,8 @@ const char* CWriter::GetReferenceTypeName(const Type& type) {
59966092 return " funcref" ;
59976093 case Type::ExternRef:
59986094 return " externref" ;
6095+ case Type::ExnRef:
6096+ return " exnref" ;
59996097 default :
60006098 WABT_UNREACHABLE;
60016099 }
@@ -6008,6 +6106,8 @@ const char* CWriter::GetReferenceNullValue(const Type& type) {
60086106 return " wasm_rt_funcref_null_value" ;
60096107 case Type::ExternRef:
60106108 return " wasm_rt_externref_null_value" ;
6109+ case Type::ExnRef:
6110+ return " wasm_rt_exnref_null_value" ;
60116111 default :
60126112 WABT_UNREACHABLE;
60136113 }
0 commit comments