From 8e501eec17c7b124a7817f62f9e21cae9bef700a Mon Sep 17 00:00:00 2001 From: Vasily Chekalkin Date: Fri, 13 Mar 2026 07:19:12 +1100 Subject: [PATCH 1/3] Add TagType support for WebAssembly exception-handling proposal - Add `WASM_EXTERN_TAG` to `wasm_externkind_enum` - Add `WASM_DECLARE_TYPE(tagtype)` with constructor and functype accessor - Add cast functions: `wasm_tagtype_as_externtype*` and `wasm_externtype_as_tagtype*` - Add `TAG` to `ExternKind` enum in C++ API - Add `TagType` class extending `ExternType` with `make(own&&)` and `functype()` accessor - Add `tag()` accessors on `ExternType` Tags are described by an associated function type whose parameters are the exception payload types (per the WebAssembly exception-handling proposal). Co-Authored-By: Claude Sonnet 4.6 --- include/wasm.h | 14 ++++++++++++++ include/wasm.hh | 23 ++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/wasm.h b/include/wasm.h index b7f227a..41f7fa3 100644 --- a/include/wasm.h +++ b/include/wasm.h @@ -247,6 +247,15 @@ WASM_API_EXTERN own wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t*) WASM_API_EXTERN const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t*); +// Tag Types + +WASM_DECLARE_TYPE(tagtype) + +WASM_API_EXTERN own wasm_tagtype_t* wasm_tagtype_new(own wasm_functype_t*); + +WASM_API_EXTERN const wasm_functype_t* wasm_tagtype_functype(const wasm_tagtype_t*); + + // Extern Types WASM_DECLARE_TYPE(externtype) @@ -257,6 +266,7 @@ enum wasm_externkind_enum { WASM_EXTERN_GLOBAL, WASM_EXTERN_TABLE, WASM_EXTERN_MEMORY, + WASM_EXTERN_TAG, }; WASM_API_EXTERN wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t*); @@ -265,21 +275,25 @@ WASM_API_EXTERN wasm_externtype_t* wasm_functype_as_externtype(wasm_functype_t*) WASM_API_EXTERN wasm_externtype_t* wasm_globaltype_as_externtype(wasm_globaltype_t*); WASM_API_EXTERN wasm_externtype_t* wasm_tabletype_as_externtype(wasm_tabletype_t*); WASM_API_EXTERN wasm_externtype_t* wasm_memorytype_as_externtype(wasm_memorytype_t*); +WASM_API_EXTERN wasm_externtype_t* wasm_tagtype_as_externtype(wasm_tagtype_t*); WASM_API_EXTERN wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t*); WASM_API_EXTERN wasm_globaltype_t* wasm_externtype_as_globaltype(wasm_externtype_t*); WASM_API_EXTERN wasm_tabletype_t* wasm_externtype_as_tabletype(wasm_externtype_t*); WASM_API_EXTERN wasm_memorytype_t* wasm_externtype_as_memorytype(wasm_externtype_t*); +WASM_API_EXTERN wasm_tagtype_t* wasm_externtype_as_tagtype(wasm_externtype_t*); WASM_API_EXTERN const wasm_externtype_t* wasm_functype_as_externtype_const(const wasm_functype_t*); WASM_API_EXTERN const wasm_externtype_t* wasm_globaltype_as_externtype_const(const wasm_globaltype_t*); WASM_API_EXTERN const wasm_externtype_t* wasm_tabletype_as_externtype_const(const wasm_tabletype_t*); WASM_API_EXTERN const wasm_externtype_t* wasm_memorytype_as_externtype_const(const wasm_memorytype_t*); +WASM_API_EXTERN const wasm_externtype_t* wasm_tagtype_as_externtype_const(const wasm_tagtype_t*); WASM_API_EXTERN const wasm_functype_t* wasm_externtype_as_functype_const(const wasm_externtype_t*); WASM_API_EXTERN const wasm_globaltype_t* wasm_externtype_as_globaltype_const(const wasm_externtype_t*); WASM_API_EXTERN const wasm_tabletype_t* wasm_externtype_as_tabletype_const(const wasm_externtype_t*); WASM_API_EXTERN const wasm_memorytype_t* wasm_externtype_as_memorytype_const(const wasm_externtype_t*); +WASM_API_EXTERN const wasm_tagtype_t* wasm_externtype_as_tagtype_const(const wasm_externtype_t*); // Import Types diff --git a/include/wasm.hh b/include/wasm.hh index c98a1f4..047c6cf 100644 --- a/include/wasm.hh +++ b/include/wasm.hh @@ -294,13 +294,14 @@ public: // External Types enum class ExternKind : uint8_t { - FUNC, GLOBAL, TABLE, MEMORY + FUNC, GLOBAL, TABLE, MEMORY, TAG }; class FuncType; class GlobalType; class TableType; class MemoryType; +class TagType; class WASM_API_EXTERN ExternType { friend class destroyer; @@ -319,11 +320,13 @@ public: auto global() -> GlobalType*; auto table() -> TableType*; auto memory() -> MemoryType*; + auto tag() -> TagType*; auto func() const -> const FuncType*; auto global() const -> const GlobalType*; auto table() const -> const TableType*; auto memory() const -> const MemoryType*; + auto tag() const -> const TagType*; }; @@ -406,6 +409,24 @@ public: }; +// Tag Types + +class WASM_API_EXTERN TagType : public ExternType { + friend class destroyer; + void destroy(); + +protected: + TagType() = default; + ~TagType() = default; + +public: + static auto make(own&&) -> own; + auto copy() const -> own; + + auto functype() const -> const FuncType*; +}; + + // Import Types using Name = vec; From 6d7605225211797c777f3a8bae04ddd2d0cdd391 Mon Sep 17 00:00:00 2001 From: Vasily Chekalkin Date: Wed, 18 Mar 2026 05:05:40 +1100 Subject: [PATCH 2/3] Fix V8 backend: handle TAG extern kind in switch statements Add TagTypeImpl and implement TagType::make/copy/destroy/functype. Add ExternType::tag() accessors. Handle ExternKind::TAG in all four switch statements that previously caused -Werror,-Wswitch failures: - ExternType::copy() - ExternType::destroy() - Extern::type() - Instance exports construction Co-Authored-By: Claude Sonnet 4.6 --- src/wasm-v8.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/wasm-v8.cc b/src/wasm-v8.cc index e7246b1..ca7703c 100644 --- a/src/wasm-v8.cc +++ b/src/wasm-v8.cc @@ -590,6 +590,7 @@ auto ExternType::copy() const -> own { case ExternKind::GLOBAL: return global()->copy(); case ExternKind::TABLE: return table()->copy(); case ExternKind::MEMORY: return memory()->copy(); + case ExternKind::TAG: return tag()->copy(); } } @@ -809,6 +810,36 @@ auto MemoryType::limits() const -> const Limits& { } +// Tag Types + +struct TagTypeImpl : ExternTypeImpl { + own functype; + + explicit TagTypeImpl(own&& functype_) : + ExternTypeImpl(ExternKind::TAG), + functype(std::move(functype_)) + {} +}; + +template<> struct implement { using type = TagTypeImpl; }; + +void TagType::destroy() { + delete impl(this); +} + +auto TagType::make(own&& functype) -> own { + return own(new(std::nothrow) TagTypeImpl(std::move(functype))); +} + +auto TagType::copy() const -> own { + return TagType::make(impl(this)->functype->copy()); +} + +auto TagType::functype() const -> const FuncType* { + return impl(this)->functype.get(); +} + + auto ExternType::memory() -> MemoryType* { return kind() == ExternKind::MEMORY ? static_cast(this) @@ -821,12 +852,25 @@ auto ExternType::memory() const -> const MemoryType* { : nullptr; } +auto ExternType::tag() -> TagType* { + return kind() == ExternKind::TAG + ? static_cast(this) + : nullptr; +} + +auto ExternType::tag() const -> const TagType* { + return kind() == ExternKind::TAG + ? static_cast(this) + : nullptr; +} + void ExternType::destroy() { switch (kind()) { case ExternKind::FUNC: delete static_cast(this); break; case ExternKind::GLOBAL: delete static_cast(this); break; case ExternKind::TABLE: delete static_cast(this); break; case ExternKind::MEMORY: delete static_cast(this); break; + case ExternKind::TAG: delete static_cast(this); break; } } @@ -1499,6 +1543,7 @@ auto Extern::type() const -> own { case ExternKind::GLOBAL: return global()->type(); case ExternKind::TABLE: return table()->type(); case ExternKind::MEMORY: return memory()->type(); + case ExternKind::TAG: return nullptr; } } @@ -2134,6 +2179,9 @@ auto Instance::exports() const -> ownvec { assert(wasm_v8::extern_kind(obj) == wasm_v8::EXTERN_MEMORY); exports[i] = RefImpl::make(store, obj); } break; + case ExternKind::TAG: { + // Tags are not yet supported as first-class externs in the V8 backend. + } break; } } From 8dc666007e92aa0e20397562940380317a9ebce9 Mon Sep 17 00:00:00 2001 From: Vasily Chekalkin Date: Wed, 18 Mar 2026 05:30:27 +1100 Subject: [PATCH 3/3] Handle TAG extern kind in reflect example Co-Authored-By: Claude Sonnet 4.6 --- example/reflect.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/reflect.cc b/example/reflect.cc index f71c359..a700805 100644 --- a/example/reflect.cc +++ b/example/reflect.cc @@ -60,6 +60,9 @@ auto operator<<(std::ostream& out, const wasm::ExternType& type) -> std::ostream case wasm::ExternKind::MEMORY: { out << "memory " << type.memory()->limits(); } break; + case wasm::ExternKind::TAG: { + out << "tag " << type.tag()->functype()->params(); + } break; } return out; }