Skip to content

Commit

Permalink
[EH] Add exnref type back (#6149)
Browse files Browse the repository at this point in the history
At the Oct hybrid CG meeting, we decided to add back `exnref`, which was
removed in 2020:
https://github.com/WebAssembly/meetings/blob/main/main/2023/CG-10.md

The new version of the proposal reflected in the explainer:
https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md

While adding support for `exnref` in the current codebase which has all
GC subtype hierarchies, I noticed we might need `noexn` heap type for
the bottom type of `exn`. We don't have it now so I just set it to 0xff
for the moment.
  • Loading branch information
aheejin committed Dec 8, 2023
1 parent 48373b6 commit 1d615b3
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 18 deletions.
4 changes: 4 additions & 0 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case HeapType::func:
case HeapType::struct_:
case HeapType::array:
case HeapType::exn:
WASM_UNREACHABLE("invalid type");
case HeapType::string:
case HeapType::stringview_wtf8:
Expand All @@ -96,6 +97,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc:
case HeapType::noexn:
// Null.
return ret;
}
Expand Down Expand Up @@ -140,6 +142,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
case HeapType::func:
case HeapType::struct_:
case HeapType::array:
case HeapType::exn:
WASM_UNREACHABLE("invalid type");
case HeapType::string:
case HeapType::stringview_wtf8:
Expand All @@ -149,6 +152,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc:
case HeapType::noexn:
assert(type.isNullable());
return Literal::makeNull(heapType);
}
Expand Down
14 changes: 13 additions & 1 deletion src/tools/fuzzing/fuzzing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2429,6 +2429,14 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
HeapType(Array(Field(Field::PackedType::i8, Immutable)));
return builder.makeArrayNewFixed(trivialArray, {});
}
case HeapType::exn: {
auto null = builder.makeRefNull(HeapType::ext);
if (!type.isNullable()) {
assert(funcContext);
return builder.makeRefAs(RefAsNonNull, null);
}
return null;
}
case HeapType::string:
return builder.makeStringConst(std::to_string(upTo(1024)));
case HeapType::stringview_wtf8:
Expand All @@ -2437,7 +2445,8 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
WASM_UNREACHABLE("TODO: strings");
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc: {
case HeapType::nofunc:
case HeapType::noexn: {
auto null = builder.makeRefNull(heapType);
if (!type.isNullable()) {
assert(funcContext);
Expand Down Expand Up @@ -3888,6 +3897,8 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) {
return pick(HeapType::struct_, HeapType::none);
case HeapType::array:
return pick(HeapType::array, HeapType::none);
case HeapType::exn:
return HeapType::exn;
case HeapType::string:
return HeapType::string;
case HeapType::stringview_wtf8:
Expand All @@ -3897,6 +3908,7 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) {
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc:
case HeapType::noexn:
break;
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/tools/fuzzing/heap-types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,6 @@ struct HeapTypeGeneratorImpl {
return type.getBottom();
}
switch (type.getBasic()) {
case HeapType::ext:
return HeapType::ext;
case HeapType::func:
return pickSubFunc();
case HeapType::any:
Expand All @@ -392,13 +390,16 @@ struct HeapTypeGeneratorImpl {
return pickSubStruct();
case HeapType::array:
return pickSubArray();
case HeapType::ext:
case HeapType::exn:
case HeapType::string:
case HeapType::stringview_wtf8:
case HeapType::stringview_wtf16:
case HeapType::stringview_iter:
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc:
case HeapType::noexn:
return type;
}
WASM_UNREACHABLE("unexpected type");
Expand Down Expand Up @@ -440,6 +441,7 @@ struct HeapTypeGeneratorImpl {
switch (type.getBasic()) {
case HeapType::ext:
case HeapType::func:
case HeapType::exn:
case HeapType::any:
break;
case HeapType::eq:
Expand All @@ -464,6 +466,9 @@ struct HeapTypeGeneratorImpl {
case HeapType::noext:
candidates.push_back(HeapType::ext);
break;
case HeapType::noexn:
candidates.push_back(HeapType::exn);
break;
}
assert(!candidates.empty());
return rand.pick(candidates);
Expand Down
19 changes: 12 additions & 7 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,9 @@ enum EncodedType {
nullable = -0x14, // 0x6c
nonnullable = -0x15, // 0x6b
#endif
// exception handling
exnref = -0x17, // 0x69
nullexnref = -0xff, // TODO
// string reference types
#if STANDARD_GC_ENCODINGS
stringref = -0x19, // 0x67
Expand Down Expand Up @@ -449,14 +452,16 @@ enum EncodedHeapType {
noext = -0xe, // 0x72
none = -0xf, // 0x71
#else
noext = -0x17, // 0x69
nofunc = -0x18, // 0x68
none = -0x1b, // 0x65
noext = -0x17, // 0x69
nofunc = -0x18, // 0x68
none = -0x1b, // 0x65
#endif
func = -0x10, // 0x70
ext = -0x11, // 0x6f
any = -0x12, // 0x6e
eq = -0x13, // 0x6d
func = -0x10, // 0x70
ext = -0x11, // 0x6f
any = -0x12, // 0x6e
eq = -0x13, // 0x6d
exn = -0x17, // 0x69
noexn = -0xff, // TODO
#if STANDARD_GC_ENCODINGS
i31 = -0x14, // 0x6c
struct_ = -0x15, // 0x6b
Expand Down
9 changes: 8 additions & 1 deletion src/wasm-type.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ class Type {
// │ eqref ║ x │ │ x │ x │ n │ │ n_ullable
// │ i31ref ║ x │ │ x │ x │ n │ │
// │ structref ║ x │ │ x │ x │ n │ │
// │ arrayref ║ x │ │ x │ x │ n │ │
// │ exnref ║ x │ │ x │ x │ n │ │
// │ stringref ║ x │ │ x │ x │ n │ │
// ├─ Compound ──╫───┼───┼───┼───┤───────┤ │
// │ Ref ║ │ x │ x │ x │ f? n? │◄┘
// │ Tuple ║ │ x │ │ x │ │
Expand Down Expand Up @@ -167,6 +170,7 @@ class Type {
bool isSignature() const;
bool isStruct() const;
bool isArray() const;
bool isException() const;
bool isString() const;
bool isDefaultable() const;

Expand Down Expand Up @@ -322,15 +326,17 @@ class HeapType {
i31,
struct_,
array,
exn,
string,
stringview_wtf8,
stringview_wtf16,
stringview_iter,
none,
noext,
nofunc,
noexn,
};
static constexpr BasicHeapType _last_basic_type = nofunc;
static constexpr BasicHeapType _last_basic_type = noexn;

// BasicHeapType can be implicitly upgraded to HeapType
constexpr HeapType(BasicHeapType id) : id(id) {}
Expand Down Expand Up @@ -364,6 +370,7 @@ class HeapType {
bool isContinuation() const;
bool isStruct() const;
bool isArray() const;
bool isException() const;
bool isString() const;
bool isBottom() const;
bool isOpen() const;
Expand Down
8 changes: 8 additions & 0 deletions src/wasm/literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,14 @@ Literal::Literal(const Literal& other) : type(other.type) {
case HeapType::none:
case HeapType::noext:
case HeapType::nofunc:
case HeapType::noexn:
WASM_UNREACHABLE("null literals should already have been handled");
case HeapType::any:
case HeapType::eq:
case HeapType::func:
case HeapType::struct_:
case HeapType::array:
case HeapType::exn:
WASM_UNREACHABLE("invalid type");
case HeapType::string:
case HeapType::stringview_wtf8:
Expand Down Expand Up @@ -613,9 +615,15 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
case HeapType::nofunc:
o << "nullfuncref";
break;
case HeapType::noexn:
o << "nullexnref";
break;
case HeapType::ext:
o << "externref";
break;
case HeapType::exn:
o << "exnref";
break;
case HeapType::any:
case HeapType::eq:
case HeapType::func:
Expand Down
30 changes: 30 additions & 0 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,10 @@ void WasmBinaryWriter::writeType(Type type) {
o << S32LEB(BinaryConsts::EncodedType::externref);
return;
}
if (Type::isSubType(type, Type(HeapType::exn, Nullable))) {
o << S32LEB(BinaryConsts::EncodedType::exnref);
return;
}
if (Type::isSubType(type, Type(HeapType::string, Nullable))) {
o << S32LEB(BinaryConsts::EncodedType::stringref);
return;
Expand Down Expand Up @@ -1502,6 +1506,9 @@ void WasmBinaryWriter::writeType(Type type) {
case HeapType::array:
o << S32LEB(BinaryConsts::EncodedType::arrayref);
return;
case HeapType::exn:
o << S32LEB(BinaryConsts::EncodedType::exnref);
return;
case HeapType::string:
o << S32LEB(BinaryConsts::EncodedType::stringref);
return;
Expand All @@ -1523,6 +1530,9 @@ void WasmBinaryWriter::writeType(Type type) {
case HeapType::nofunc:
o << S32LEB(BinaryConsts::EncodedType::nullfuncref);
return;
case HeapType::noexn:
o << S32LEB(BinaryConsts::EncodedType::nullexnref);
return;
}
}
if (type.isNullable()) {
Expand Down Expand Up @@ -1570,6 +1580,8 @@ void WasmBinaryWriter::writeHeapType(HeapType type) {
type = HeapType::func;
} else if (HeapType::isSubType(type, HeapType::ext)) {
type = HeapType::ext;
} else if (HeapType::isSubType(type, HeapType::exn)) {
type = HeapType::exn;
} else if (wasm->features.hasStrings()) {
// Strings are enabled, and this isn't a func or an ext, so it must be a
// string type (string or stringview), which we'll emit below, or a bottom
Expand Down Expand Up @@ -1609,6 +1621,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) {
case HeapType::array:
ret = BinaryConsts::EncodedHeapType::array;
break;
case HeapType::exn:
ret = BinaryConsts::EncodedHeapType::exn;
break;
case HeapType::string:
ret = BinaryConsts::EncodedHeapType::string;
break;
Expand All @@ -1630,6 +1645,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) {
case HeapType::nofunc:
ret = BinaryConsts::EncodedHeapType::nofunc;
break;
case HeapType::noexn:
ret = BinaryConsts::EncodedHeapType::noexn;
break;
}
o << S64LEB(ret); // TODO: Actually s33
}
Expand Down Expand Up @@ -1980,6 +1998,9 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) {
case BinaryConsts::EncodedType::arrayref:
out = Type(HeapType::array, Nullable);
return true;
case BinaryConsts::EncodedType::exnref:
out = Type(HeapType::exn, Nullable);
return true;
case BinaryConsts::EncodedType::stringref:
out = Type(HeapType::string, Nullable);
return true;
Expand All @@ -2001,6 +2022,9 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) {
case BinaryConsts::EncodedType::nullfuncref:
out = Type(HeapType::nofunc, Nullable);
return true;
case BinaryConsts::EncodedType::nullexnref:
out = Type(HeapType::noexn, Nullable);
return true;
default:
return false;
}
Expand Down Expand Up @@ -2029,6 +2053,9 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) {
case BinaryConsts::EncodedHeapType::array:
out = HeapType::array;
return true;
case BinaryConsts::EncodedHeapType::exn:
out = HeapType::exn;
return true;
case BinaryConsts::EncodedHeapType::string:
out = HeapType::string;
return true;
Expand All @@ -2050,6 +2077,9 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) {
case BinaryConsts::EncodedHeapType::nofunc:
out = HeapType::nofunc;
return true;
case BinaryConsts::EncodedHeapType::noexn:
out = HeapType::noexn;
return true;
default:
return false;
}
Expand Down
15 changes: 15 additions & 0 deletions src/wasm/wasm-s-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str,
if (str.substr(0, 8) == "arrayref" && (prefix || str.size() == 8)) {
return Type(HeapType::array, Nullable);
}
if (str.substr(0, 6) == "exnref" && (prefix || str.size() == 6)) {
return Type(HeapType::exn, Nullable);
}
if (str.substr(0, 9) == "stringref" && (prefix || str.size() == 9)) {
return Type(HeapType::string, Nullable);
}
Expand All @@ -1300,6 +1303,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str,
if (str.substr(0, 11) == "nullfuncref" && (prefix || str.size() == 11)) {
return Type(HeapType::nofunc, Nullable);
}
if (str.substr(0, 10) == "nullexnref" && (prefix || str.size() == 10)) {
return Type(HeapType::noexn, Nullable);
}
if (allowError) {
return Type::none;
}
Expand Down Expand Up @@ -1330,6 +1336,9 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str,
if (str.substr(0, 5) == "array" && (prefix || str.size() == 5)) {
return HeapType::array;
}
if (str.substr(0, 3) == "exn" && (prefix || str.size() == 3)) {
return HeapType::exn;
}
if (str.substr(0, 6) == "string" && (prefix || str.size() == 6)) {
return HeapType::string;
}
Expand All @@ -1351,6 +1360,12 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str,
if (str.substr(0, 6) == "nofunc" && (prefix || str.size() == 6)) {
return HeapType::nofunc;
}
if (str.substr(0, 6) == "nofunc" && (prefix || str.size() == 6)) {
return HeapType::nofunc;
}
if (str.substr(0, 5) == "noexn" && (prefix || str.size() == 5)) {
return HeapType::noexn;
}
throw ParseException(std::string("invalid wasm heap type: ") +
std::string(str.data(), str.size()));
}
Expand Down
Loading

0 comments on commit 1d615b3

Please sign in to comment.