diff --git a/src/binary-reader.cc b/src/binary-reader.cc index b68562dd50..a0b31787e6 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -557,6 +557,9 @@ bool BinaryReader::IsConcreteType(Type type) { case Type::ExternRef: return options_.features.reference_types_enabled(); + case Type::ExnRef: + return options_.features.exceptions_enabled(); + case Type::Reference: return options_.features.function_references_enabled(); diff --git a/src/binary-writer-spec.cc b/src/binary-writer-spec.cc index 3cb6674de3..edcf0ba58f 100644 --- a/src/binary-writer-spec.cc +++ b/src/binary-writer-spec.cc @@ -256,6 +256,14 @@ void BinaryWriterSpec::WriteConst(const Const& const_) { break; } + case Type::ExnRef: { + WriteString("exnref"); + WriteSeparator(); + WriteKey("value"); + WriteRefBits(const_.ref_bits()); + break; + } + case Type::V128: { WriteString("v128"); WriteSeparator(); diff --git a/src/interp/interp.cc b/src/interp/interp.cc index fe333b4275..97f35f81fb 100644 --- a/src/interp/interp.cc +++ b/src/interp/interp.cc @@ -225,6 +225,8 @@ bool Store::HasValueType(Ref ref, ValueType type) const { case ValueType::FuncRef: return obj->kind() == ObjectKind::DefinedFunc || obj->kind() == ObjectKind::HostFunc; + case ValueType::ExnRef: + return obj->kind() == ObjectKind::Exception; default: return false; } @@ -2733,8 +2735,11 @@ std::string Thread::TraceSource::Pick(Index index, Instr instr) { v.u32(2), v.u32(3)); } + // clang-format off case ValueType::FuncRef: reftype = "funcref"; break; case ValueType::ExternRef: reftype = "externref"; break; + case ValueType::ExnRef: reftype = "exnref"; break; + // clang-format on default: WABT_UNREACHABLE; diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index 9e7e32e33a..2dd4202baf 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -633,6 +633,8 @@ wabt::Result JSONParser::ParseType(Type* out_type) { *out_type = Type::FuncRef; } else if (type_str == "externref") { *out_type = Type::ExternRef; + } else if (type_str == "exnref") { + *out_type = Type::ExnRef; } else { PrintError("unknown type: \"%s\"", type_str.c_str()); return wabt::Result::Error; @@ -863,6 +865,16 @@ wabt::Result JSONParser::ParseConstValue(Type type, } break; + case Type::ExnRef: + if (value_str == "null") { + out_value->Set(Ref::Null); + } else { + // FIXME? + PrintError("NYI"); + return wabt::Result::Error; + } + break; + default: PrintError("unknown concrete type: \"%s\"", type.GetName().c_str()); return wabt::Result::Error; @@ -1914,6 +1926,11 @@ wabt::Result CommandRunner::CheckAssertReturnResult( ok = expected.value.value.Get() == actual.value.Get(); break; + case Type::ExnRef: + // FIXME is this correct? + ok = (actual.type == Type::ExnRef); + break; + default: WABT_UNREACHABLE; } diff --git a/src/wast-parser.cc b/src/wast-parser.cc index c829646128..eb67dcebae 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -657,7 +657,8 @@ bool WastParser::PeekMatchExpr() { } bool WastParser::PeekMatchRefType() { - return options_->features.function_references_enabled() && + return (options_->features.function_references_enabled() || + options_->features.exceptions_enabled()) && PeekMatchLpar(TokenType::Ref); } @@ -934,6 +935,9 @@ Result WastParser::ParseValueType(Var* out_type) { case Type::ExternRef: is_enabled = options_->features.reference_types_enabled(); break; + case Type::ExnRef: + is_enabled = options_->features.exceptions_enabled(); + break; default: is_enabled = true; break; diff --git a/test/spec/exception-handling/ref_null.txt b/test/spec/exception-handling/ref_null.txt new file mode 100644 index 0000000000..4b9201a860 --- /dev/null +++ b/test/spec/exception-handling/ref_null.txt @@ -0,0 +1,6 @@ +;;; TOOL: run-interp-spec +;;; STDIN_FILE: third_party/testsuite/proposals/exception-handling/ref_null.wast +;;; ARGS*: --enable-exceptions +(;; STDOUT ;;; +4/4 tests passed. +;;; STDOUT ;;)