diff --git a/src/c-writer.cc b/src/c-writer.cc index 7a0c548bc..0365a3283 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -483,10 +483,12 @@ class CWriter { void Write(const AtomicRmwExpr& expr); void Write(const AtomicRmwCmpxchgExpr& expr); - size_t BeginTry(const TryExpr& tryexpr); + size_t BeginTry(const Block& block); void WriteTryCatch(const TryExpr& tryexpr); void WriteTryDelegate(const TryExpr& tryexpr); + void Write(const TryTableExpr& try_table_expr); void Write(const Catch& c); + void Write(const TableCatch& c); void WriteThrow(); void PushTryCatch(const std::string& name); @@ -646,6 +648,7 @@ constexpr char CWriter::MangleType(Type type) { case Type::V128: return 'o'; case Type::FuncRef: return 'r'; case Type::ExternRef: return 'e'; + case Type::ExnRef: return 'x'; default: WABT_UNREACHABLE; } @@ -1218,6 +1221,7 @@ const char* CWriter::GetCTypeName(const Type& type) { case Type::V128: return "v128"; case Type::FuncRef: return "wasm_rt_funcref_t"; case Type::ExternRef: return "wasm_rt_externref_t"; + case Type::ExnRef: return "wasm_rt_exnref_t"; default: WABT_UNREACHABLE; } @@ -1238,6 +1242,7 @@ void CWriter::Write(TypeEnum type) { case Type::V128: Write("WASM_RT_V128"); break; case Type::FuncRef: Write("WASM_RT_FUNCREF"); break; case Type::ExternRef: Write("WASM_RT_EXTERNREF"); break; + case Type::ExnRef: Write("WASM_RT_EXNREF"); break; default: WABT_UNREACHABLE; } @@ -2284,7 +2289,8 @@ void CWriter::WriteElemInitializerDecls() { continue; } - if (elem_segment->elem_type == Type::ExternRef) { + if (elem_segment->elem_type == Type::ExternRef || + elem_segment->elem_type == Type::ExnRef) { // no need to store externref elem initializers because only // ref.null is possible continue; @@ -2356,7 +2362,8 @@ void CWriter::WriteElemInitializers() { continue; } - if (elem_segment->elem_type == Type::ExternRef) { + if (elem_segment->elem_type == Type::ExternRef || + elem_segment->elem_type == Type::ExnRef) { // no need to store externref elem initializers because only // ref.null is possible continue; @@ -2460,7 +2467,8 @@ void CWriter::WriteElemTableInit(bool active_initialization, const ElemSegment* src_segment, const Table* dst_table) { assert(dst_table->elem_type == Type::FuncRef || - dst_table->elem_type == Type::ExternRef); + dst_table->elem_type == Type::ExternRef || + dst_table->elem_type == Type::ExnRef); assert(dst_table->elem_type == src_segment->elem_type); Write(GetReferenceTypeName(dst_table->elem_type), "_table_init(", @@ -3108,7 +3116,7 @@ void CWriter::WriteVarsByType(const Vars& vars, const ToDo& todo, bool setjmp_safe) { for (Type type : {Type::I32, Type::I64, Type::F32, Type::F64, Type::V128, - Type::FuncRef, Type::ExternRef}) { + Type::FuncRef, Type::ExternRef, Type::ExnRef}) { Index var_index = 0; size_t count = 0; for (const auto& var : vars) { @@ -3252,7 +3260,8 @@ void CWriter::WriteLocals(const std::vector& index_to_name) { func_->local_types, [](auto x) { return x; }, [&](Index local_index, Type local_type) { Write(DefineParamName(index_to_name[num_params + local_index]), " = "); - if (local_type == Type::FuncRef || local_type == Type::ExternRef) { + if (local_type == Type::FuncRef || local_type == Type::ExternRef || + local_type == Type::ExnRef) { Write(GetReferenceNullValue(local_type)); } else if (local_type == Type::V128) { Write("simde_wasm_i64x2_make(0, 0)"); @@ -3284,27 +3293,27 @@ void CWriter::Write(const Block& block) { PushTypes(block.decl.sig.result_types); } -size_t CWriter::BeginTry(const TryExpr& tryexpr) { +size_t CWriter::BeginTry(const Block& block) { func_includes_.insert("exceptions"); - Write(OpenBrace()); /* beginning of try-catch */ - const std::string tlabel = DefineLabelName(tryexpr.block.label); + Write(OpenBrace()); /* beginning of try-catch or try_table */ + const std::string tlabel = DefineLabelName(block.label); Write("WASM_RT_UNWIND_TARGET *", tlabel, "_outer_target = wasm_rt_get_unwind_target();", Newline()); Write("WASM_RT_UNWIND_TARGET ", tlabel, "_unwind_target;", Newline()); Write("if (!wasm_rt_try(", tlabel, "_unwind_target)) "); - Write(OpenBrace()); /* beginning of try block */ - DropTypes(tryexpr.block.decl.GetNumParams()); + Write(OpenBrace()); /* beginning of try or try_table block */ + DropTypes(block.decl.GetNumParams()); const size_t mark = MarkTypeStack(); - PushLabel(LabelType::Try, tryexpr.block.label, tryexpr.block.decl.sig); - PushTypes(tryexpr.block.decl.sig.param_types); + PushLabel(LabelType::Try, block.label, block.decl.sig); + PushTypes(block.decl.sig.param_types); Write("wasm_rt_set_unwind_target(&", tlabel, "_unwind_target);", Newline()); PushTryCatch(tlabel); - Write(tryexpr.block.exprs); + Write(block.exprs); ResetTypeStack(mark); Write("wasm_rt_set_unwind_target(", tlabel, "_outer_target);", Newline()); - Write(CloseBrace()); /* end of try block */ + Write(CloseBrace()); /* end of try or try_table block */ Write(" else ", OpenBrace()); /* beginning of catch blocks or delegate */ - assert(label_stack_.back().name == tryexpr.block.label); + assert(label_stack_.back().name == block.label); assert(label_stack_.back().label_type == LabelType::Try); label_stack_.back().label_type = LabelType::Catch; if (try_catch_stack_.back().used) { @@ -3315,7 +3324,7 @@ size_t CWriter::BeginTry(const TryExpr& tryexpr) { } void CWriter::WriteTryCatch(const TryExpr& tryexpr) { - const size_t mark = BeginTry(tryexpr); + const size_t mark = BeginTry(tryexpr.block); /* exception has been thrown -- do we catch it? */ @@ -3413,7 +3422,7 @@ void CWriter::PopTryCatch() { } void CWriter::WriteTryDelegate(const TryExpr& tryexpr) { - const size_t mark = BeginTry(tryexpr); + const size_t mark = BeginTry(tryexpr.block); /* exception has been thrown -- where do we delegate it? */ @@ -3460,6 +3469,85 @@ void CWriter::WriteTryDelegate(const TryExpr& tryexpr) { PushTypes(tryexpr.block.decl.sig.result_types); } +void CWriter::Write(const TryTableExpr& try_table_expr) { + const size_t mark = BeginTry(try_table_expr.block); + + /* exception has been thrown -- do we catch it? */ + + const LabelName tlabel = LabelName(try_table_expr.block.label); + + Write("wasm_rt_set_unwind_target(", tlabel, "_outer_target);", Newline()); + PopTryCatch(); + + ResetTypeStack(mark); + assert(!label_stack_.empty()); + assert(label_stack_.back().name == try_table_expr.block.label); + Write(LabelDecl(GetLocalName(try_table_expr.block.label, true))); + PopLabel(); + + assert(!try_table_expr.catches.empty()); + bool has_catch_all{}; + for (auto it = try_table_expr.catches.cbegin(); + it != try_table_expr.catches.cend(); ++it) { + if (it == try_table_expr.catches.cbegin()) { + Write(Newline()); + } else { + Write(" else "); + } + ResetTypeStack(mark); + Write(*it); + if (it->IsCatchAll()) { + has_catch_all = true; + break; + } + } + if (!has_catch_all) { + /* if not caught, rethrow */ + Write(" else ", OpenBrace()); + WriteThrow(); + Write(CloseBrace(), Newline()); + } + Write(CloseBrace(), Newline()); /* end of catch blocks */ + Write(CloseBrace(), Newline()); /* end of try-catch */ + + ResetTypeStack(mark); + PushTypes(try_table_expr.block.decl.sig.result_types); +} + +void CWriter::Write(const TableCatch& c) { + if (!c.IsCatchAll()) { + Write("if (wasm_rt_exception_tag() == ", + TagSymbol(module_->GetTag(c.tag)->name), ") ", OpenBrace()); + + const Tag* tag = module_->GetTag(c.tag); + const FuncDeclaration& tag_type = tag->decl; + const Index num_params = tag_type.GetNumParams(); + PushTypes(tag_type.sig.param_types); + if (num_params == 1) { + Write("wasm_rt_memcpy(&", StackVar(0), ", wasm_rt_exception(), sizeof(", + tag_type.GetParamType(0), "));", Newline()); + } else if (num_params > 1) { + Write(OpenBrace(), tag_type.sig.param_types, " tmp;", Newline()); + Write("wasm_rt_memcpy(&tmp, wasm_rt_exception(), sizeof(tmp));", + Newline()); + Unspill(tag_type.sig.param_types); + Write(CloseBrace(), Newline()); + } + } + if (c.IsRef()) { + PushType(Type::ExnRef); + Write(StackVar(0), ".tag = wasm_rt_exception_tag();", Newline()); + Write(StackVar(0), ".size = wasm_rt_exception_size();", Newline()); + Write("wasm_rt_memcpy(&", StackVar(0), + ".data, wasm_rt_exception(), wasm_rt_exception_size());", Newline()); + } + + Write(GotoLabel(c.target), Newline()); + if (!c.IsCatchAll()) { + Write(CloseBrace()); + } +} + void CWriter::Write(const ExprList& exprs) { for (const Expr& expr : exprs) { switch (expr.type()) { @@ -3862,6 +3950,10 @@ void CWriter::Write(const ExprList& exprs) { " == ", GetReferenceNullValue(Type::ExternRef), ");", Newline()); break; + case Type::ExnRef: + Write(StackVar(0, Type::I32), " = (", StackVar(0), ".tag == NULL", + ");", Newline()); + break; default: WABT_UNREACHABLE; } @@ -3978,7 +4070,19 @@ void CWriter::Write(const ExprList& exprs) { } WriteThrow(); - } break; + // Stop processing this ExprList, since the following are unreachable. + return; + } + + case ExprType::ThrowRef: { + Write("if (", StackVar(0), ".tag == NULL) { TRAP(NULL_REF); }"); + Write("wasm_rt_load_exception(", StackVar(0), ".tag, ", StackVar(0), + ".size, ", StackVar(0), ".data);", Newline()); + DropTypes(1); + WriteThrow(); + // Stop processing this ExprList, since the following are unreachable. + return; + } case ExprType::Rethrow: { const RethrowExpr* rethrow = cast(&expr); @@ -4005,6 +4109,15 @@ void CWriter::Write(const ExprList& exprs) { } } break; + case ExprType::TryTable: { + const TryTableExpr& try_table = *cast(&expr); + if (try_table.catches.empty()) { + Write(try_table.block); + } else { + Write(try_table); + } + } break; + case ExprType::AtomicLoad: { Write(*cast(&expr)); break; @@ -4129,8 +4242,6 @@ void CWriter::Write(const ExprList& exprs) { case ExprType::AtomicWait: case ExprType::AtomicNotify: case ExprType::CallRef: - case ExprType::ThrowRef: - case ExprType::TryTable: UNIMPLEMENTED("..."); break; } @@ -5981,6 +6092,8 @@ const char* CWriter::GetReferenceTypeName(const Type& type) { return "funcref"; case Type::ExternRef: return "externref"; + case Type::ExnRef: + return "exnref"; default: WABT_UNREACHABLE; } @@ -5993,6 +6106,8 @@ const char* CWriter::GetReferenceNullValue(const Type& type) { return "wasm_rt_funcref_null_value"; case Type::ExternRef: return "wasm_rt_externref_null_value"; + case Type::ExnRef: + return "wasm_rt_exnref_null_value"; default: WABT_UNREACHABLE; } diff --git a/test/run-spec-wasm2c.py b/test/run-spec-wasm2c.py index 1ff63d8fb..915dc8c5f 100755 --- a/test/run-spec-wasm2c.py +++ b/test/run-spec-wasm2c.py @@ -90,7 +90,7 @@ def F64ToC(f64_bits): def MangleType(t): return {'i32': 'i', 'i64': 'j', 'f32': 'f', 'f64': 'd', 'v128': 'o', - 'externref': 'e', 'funcref': 'r'}[t] + 'externref': 'e', 'funcref': 'r', 'exnref': 'x'}[t] def MangleTypes(types): @@ -321,6 +321,7 @@ def _WriteAssertReturnCommand(self, command): 'i64': 'ASSERT_RETURN_I64', 'f64': 'ASSERT_RETURN_F64', 'externref': 'ASSERT_RETURN_EXTERNREF', + 'exnref': 'ASSERT_RETURN_EXNREF', 'funcref': 'ASSERT_RETURN_FUNCREF', } @@ -385,6 +386,11 @@ def _Constant(self, const): return 'wasm_rt_funcref_null_value' else: assert False # can't make an arbitrary funcref from an integer value + elif type_ == 'exnref': + if value == 'null': + return 'wasm_rt_exnref_null_value' + else: + assert False # can't make an arbitrary exnref from an integer value else: assert False diff --git a/test/spec-wasm2c-prefix.c b/test/spec-wasm2c-prefix.c index c6cfecfa2..c0967d289 100644 --- a/test/spec-wasm2c-prefix.c +++ b/test/spec-wasm2c-prefix.c @@ -168,6 +168,24 @@ static void error(const char* file, int line, const char* format, ...) { } \ } while (0) +#define ASSERT_RETURN_EXNREF(f, expected) \ + do { \ + g_tests_run++; \ + int trap_code = wasm_rt_impl_try(); \ + if (trap_code) { \ + error(__FILE__, __LINE__, #f " trapped (%s).\n", \ + wasm_rt_strerror(trap_code)); \ + } else { \ + wasm_rt_exnref_t actual = f; \ + if (is_equal_wasm_rt_exnref_t(actual, expected)) { \ + g_tests_passed++; \ + } else { \ + error(__FILE__, __LINE__, \ + "in " #f ": mismatch between expected and actual exnref"); \ + } \ + } \ + } while (0) + #define ASSERT_RETURN_NAN_T(type, itype, fmt, f, kind) \ do { \ g_tests_run++; \ @@ -273,6 +291,12 @@ static bool is_equal_wasm_rt_funcref_t(wasm_rt_funcref_t x, (x.func == y.func) && (x.module_instance == y.module_instance); } +#ifdef WASM_EXN_MAX_SIZE +static bool is_equal_wasm_rt_exnref_t(wasm_rt_exnref_t x, wasm_rt_exnref_t y) { + return x.tag == y.tag && x.size == y.size && !memcmp(x.data, y.data, x.size); +} +#endif + wasm_rt_externref_t spectest_make_externref(uintptr_t x) { return (wasm_rt_externref_t)(x + 1); // externref(0) is not null } diff --git a/test/wasm2c/spec/exception-handling/rethrow.txt b/test/wasm2c/spec/exception-handling/legacy/rethrow.txt similarity index 100% rename from test/wasm2c/spec/exception-handling/rethrow.txt rename to test/wasm2c/spec/exception-handling/legacy/rethrow.txt diff --git a/test/wasm2c/spec/exception-handling/legacy/throw.txt b/test/wasm2c/spec/exception-handling/legacy/throw.txt new file mode 100644 index 000000000..f4816ec4b --- /dev/null +++ b/test/wasm2c/spec/exception-handling/legacy/throw.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-spec-wasm2c +;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/legacy/throw.wast +;;; ARGS*: --enable-exceptions +(;; STDOUT ;;; +7/7 tests passed. +;;; STDOUT ;;) diff --git a/test/wasm2c/spec/exception-handling/try_catch.txt b/test/wasm2c/spec/exception-handling/legacy/try_catch.txt similarity index 100% rename from test/wasm2c/spec/exception-handling/try_catch.txt rename to test/wasm2c/spec/exception-handling/legacy/try_catch.txt diff --git a/test/wasm2c/spec/exception-handling/try_delegate.txt b/test/wasm2c/spec/exception-handling/legacy/try_delegate.txt similarity index 100% rename from test/wasm2c/spec/exception-handling/try_delegate.txt rename to test/wasm2c/spec/exception-handling/legacy/try_delegate.txt diff --git a/test/wasm2c/spec/exception-handling/ref_null.txt b/test/wasm2c/spec/exception-handling/ref_null.txt new file mode 100644 index 000000000..c4702c098 --- /dev/null +++ b/test/wasm2c/spec/exception-handling/ref_null.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-spec-wasm2c +;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/ref_null.wast +;;; ARGS*: --enable-exceptions +(;; STDOUT ;;; +3/3 tests passed. +;;; STDOUT ;;) diff --git a/test/wasm2c/spec/exception-handling/throw.txt b/test/wasm2c/spec/exception-handling/throw.txt index f4816ec4b..e26b4af7d 100644 --- a/test/wasm2c/spec/exception-handling/throw.txt +++ b/test/wasm2c/spec/exception-handling/throw.txt @@ -1,6 +1,6 @@ ;;; TOOL: run-spec-wasm2c -;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/legacy/throw.wast +;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/throw.wast ;;; ARGS*: --enable-exceptions (;; STDOUT ;;; -7/7 tests passed. +9/9 tests passed. ;;; STDOUT ;;) diff --git a/test/wasm2c/spec/exception-handling/throw_ref.txt b/test/wasm2c/spec/exception-handling/throw_ref.txt new file mode 100644 index 000000000..68c925d25 --- /dev/null +++ b/test/wasm2c/spec/exception-handling/throw_ref.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-spec-wasm2c +;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/throw_ref.wast +;;; ARGS*: --enable-exceptions +(;; STDOUT ;;; +12/12 tests passed. +;;; STDOUT ;;) diff --git a/test/wasm2c/spec/exception-handling/try_table.txt b/test/wasm2c/spec/exception-handling/try_table.txt new file mode 100644 index 000000000..434d46112 --- /dev/null +++ b/test/wasm2c/spec/exception-handling/try_table.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-spec-wasm2c +;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/try_table.wast +;;; ARGS*: --enable-exceptions --enable-tail-call +(;; STDOUT ;;; +40/40 tests passed. +;;; STDOUT ;;) diff --git a/wasm2c/wasm-rt-exceptions-impl.c b/wasm2c/wasm-rt-exceptions-impl.c index 8eee492e1..73e97201c 100644 --- a/wasm2c/wasm-rt-exceptions-impl.c +++ b/wasm2c/wasm-rt-exceptions-impl.c @@ -66,3 +66,8 @@ uint32_t wasm_rt_exception_size(void) { void* wasm_rt_exception(void) { return g_active_exception; } + +// Include table operations for exnref +#define WASM_RT_TABLE_OPS_EXNREF +#include "wasm-rt-impl-tableops.inc" +#undef WASM_RT_TABLE_OPS_EXNREF diff --git a/wasm2c/wasm-rt-exceptions.h b/wasm2c/wasm-rt-exceptions.h index 29932c443..9e95c196e 100644 --- a/wasm2c/wasm-rt-exceptions.h +++ b/wasm2c/wasm-rt-exceptions.h @@ -70,6 +70,69 @@ uint32_t wasm_rt_exception_size(void); */ void* wasm_rt_exception(void); +/** + * The maximum size of an exception. + */ +#define WASM_EXN_MAX_SIZE 256 + +/** + * An exception instance (the runtime representation of a function). + * These can be stored in tables of type exnref, or used as values. + */ +typedef struct { + /** The exceptions's tag. */ + wasm_rt_tag_t tag; + /** The size of the exception. */ + uint32_t size; + /** + * The actual contents of the exception are stored inline. + */ + char data[WASM_EXN_MAX_SIZE]; +} wasm_rt_exnref_t; + +/** Default (null) value of an exnref */ +#define wasm_rt_exnref_null_value ((wasm_rt_exnref_t){NULL, 0, {0}}) + +/** A Table of type exnref. */ +typedef struct { + /** The table element data, with an element count of `size`. */ + wasm_rt_exnref_t* data; + /** + * The maximum element count of this Table object. If there is no maximum, + * `max_size` is 0xffffffffu (i.e. UINT32_MAX). + */ + uint32_t max_size; + /** The current element count of the table. */ + uint32_t size; +} wasm_rt_exnref_table_t; + +/** + * Initialize an exnref Table object with an element count of `elements` and a + * maximum size of `max_elements`. + * + * ``` + * wasm_rt_exnref_table_t my_table; + * // 5 elements and a maximum of 10 elements. + * wasm_rt_allocate_exnref_table(&my_table, 5, 10); + * ``` + */ +void wasm_rt_allocate_exnref_table(wasm_rt_exnref_table_t*, + uint32_t elements, + uint32_t max_elements); + +/** Free an exnref Table object. */ +void wasm_rt_free_exnref_table(wasm_rt_exnref_table_t*); + +/** + * Grow a Table object by `delta` elements (giving the new elements the value + * `init`), and return the previous element count. If this new element count is + * greater than the maximum element count, the grow fails and 0xffffffffu + * (UINT32_MAX) is returned instead. + */ +uint32_t wasm_rt_grow_exnref_table(wasm_rt_exnref_table_t*, + uint32_t delta, + wasm_rt_exnref_t init); + #ifdef __cplusplus } #endif diff --git a/wasm2c/wasm-rt-impl-tableops.inc b/wasm2c/wasm-rt-impl-tableops.inc index e53cfa6fe..e8b2e1990 100644 --- a/wasm2c/wasm-rt-impl-tableops.inc +++ b/wasm2c/wasm-rt-impl-tableops.inc @@ -18,23 +18,32 @@ // funcref or externref. For this, the file must be included after defining // either WASM_RT_TABLE_OPS_FUNCREF or WASM_RT_TABLE_OPS_EXTERNREF -#if defined(WASM_RT_TABLE_OPS_FUNCREF) && defined(WASM_RT_TABLE_OPS_EXTERNREF) +#if defined(WASM_RT_TABLE_OPS_FUNCREF) + \ + defined(WASM_RT_TABLE_OPS_EXTERNREF) + \ + defined(WASM_RT_TABLE_OPS_EXNREF) > \ + 1 #error \ "Expected only one of { WASM_RT_TABLE_OPS_FUNCREF, WASM_RT_TABLE_OPS_EXTERNREF } to be defined" -#elif !defined(WASM_RT_TABLE_OPS_FUNCREF) && \ - !defined(WASM_RT_TABLE_OPS_EXTERNREF) +#elif defined(WASM_RT_TABLE_OPS_FUNCREF) + \ + defined(WASM_RT_TABLE_OPS_EXTERNREF) + \ + defined(WASM_RT_TABLE_OPS_EXNREF) < \ + 1 #error \ "Expected one of { WASM_RT_TABLE_OPS_FUNCREF, WASM_RT_TABLE_OPS_EXTERNREF } to be defined" #endif -#ifdef WASM_RT_TABLE_OPS_FUNCREF +#if defined(WASM_RT_TABLE_OPS_FUNCREF) #define WASM_RT_TABLE_TYPE wasm_rt_funcref_table_t #define WASM_RT_TABLE_ELEMENT_TYPE wasm_rt_funcref_t #define WASM_RT_TABLE_APINAME(name) name##_funcref_table -#else +#elif defined(WASM_RT_TABLE_OPS_EXTERNREF) #define WASM_RT_TABLE_TYPE wasm_rt_externref_table_t #define WASM_RT_TABLE_ELEMENT_TYPE wasm_rt_externref_t #define WASM_RT_TABLE_APINAME(name) name##_externref_table +#elif defined(WASM_RT_TABLE_OPS_EXNREF) +#define WASM_RT_TABLE_TYPE wasm_rt_exnref_table_t +#define WASM_RT_TABLE_ELEMENT_TYPE wasm_rt_exnref_t +#define WASM_RT_TABLE_APINAME(name) name##_exnref_table #endif void WASM_RT_TABLE_APINAME(wasm_rt_allocate)(WASM_RT_TABLE_TYPE* table, diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c index 20137b807..cb848b3bd 100644 --- a/wasm2c/wasm-rt-impl.c +++ b/wasm2c/wasm-rt-impl.c @@ -344,6 +344,8 @@ const char* wasm_rt_strerror(wasm_rt_trap_t trap) { return "Uncaught exception"; case WASM_RT_TRAP_UNALIGNED: return "Unaligned atomic memory access"; + case WASM_RT_TRAP_NULL_REF: + return "Null reference"; } return "invalid trap code"; } diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h index 057570877..d32a430ad 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h @@ -386,6 +386,7 @@ typedef enum { WASM_RT_TRAP_INVALID_CONVERSION, /** Conversion from NaN to integer. */ WASM_RT_TRAP_UNREACHABLE, /** Unreachable instruction executed. */ WASM_RT_TRAP_CALL_INDIRECT, /** Invalid call_indirect, for any reason. */ + WASM_RT_TRAP_NULL_REF, /** Null reference. */ WASM_RT_TRAP_UNCAUGHT_EXCEPTION, /** Exception thrown and not caught. */ WASM_RT_TRAP_UNALIGNED, /** Unaligned atomic instruction executed. */ #if WASM_RT_MERGED_OOB_AND_EXHAUSTION_TRAPS @@ -404,6 +405,7 @@ typedef enum { WASM_RT_V128, WASM_RT_FUNCREF, WASM_RT_EXTERNREF, + WASM_RT_EXNREF, } wasm_rt_type_t; /**