Skip to content

Commit 2dd66ad

Browse files
aheejinradekdoulik
authored andcommitted
[EH] Add exnref type back (WebAssembly#6149)
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.
1 parent 0129560 commit 2dd66ad

14 files changed

+198
-18
lines changed

src/binaryen-c.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
8787
case HeapType::func:
8888
case HeapType::struct_:
8989
case HeapType::array:
90+
case HeapType::exn:
9091
WASM_UNREACHABLE("invalid type");
9192
case HeapType::string:
9293
case HeapType::stringview_wtf8:
@@ -96,6 +97,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
9697
case HeapType::none:
9798
case HeapType::noext:
9899
case HeapType::nofunc:
100+
case HeapType::noexn:
99101
// Null.
100102
return ret;
101103
}
@@ -140,6 +142,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
140142
case HeapType::func:
141143
case HeapType::struct_:
142144
case HeapType::array:
145+
case HeapType::exn:
143146
WASM_UNREACHABLE("invalid type");
144147
case HeapType::string:
145148
case HeapType::stringview_wtf8:
@@ -149,6 +152,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
149152
case HeapType::none:
150153
case HeapType::noext:
151154
case HeapType::nofunc:
155+
case HeapType::noexn:
152156
assert(type.isNullable());
153157
return Literal::makeNull(heapType);
154158
}

src/tools/fuzzing/fuzzing.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,14 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
24292429
HeapType(Array(Field(Field::PackedType::i8, Immutable)));
24302430
return builder.makeArrayNewFixed(trivialArray, {});
24312431
}
2432+
case HeapType::exn: {
2433+
auto null = builder.makeRefNull(HeapType::ext);
2434+
if (!type.isNullable()) {
2435+
assert(funcContext);
2436+
return builder.makeRefAs(RefAsNonNull, null);
2437+
}
2438+
return null;
2439+
}
24322440
case HeapType::string:
24332441
return builder.makeStringConst(std::to_string(upTo(1024)));
24342442
case HeapType::stringview_wtf8:
@@ -2437,7 +2445,8 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
24372445
WASM_UNREACHABLE("TODO: strings");
24382446
case HeapType::none:
24392447
case HeapType::noext:
2440-
case HeapType::nofunc: {
2448+
case HeapType::nofunc:
2449+
case HeapType::noexn: {
24412450
auto null = builder.makeRefNull(heapType);
24422451
if (!type.isNullable()) {
24432452
assert(funcContext);
@@ -3888,6 +3897,8 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) {
38883897
return pick(HeapType::struct_, HeapType::none);
38893898
case HeapType::array:
38903899
return pick(HeapType::array, HeapType::none);
3900+
case HeapType::exn:
3901+
return HeapType::exn;
38913902
case HeapType::string:
38923903
return HeapType::string;
38933904
case HeapType::stringview_wtf8:
@@ -3897,6 +3908,7 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) {
38973908
case HeapType::none:
38983909
case HeapType::noext:
38993910
case HeapType::nofunc:
3911+
case HeapType::noexn:
39003912
break;
39013913
}
39023914
}

src/tools/fuzzing/heap-types.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,6 @@ struct HeapTypeGeneratorImpl {
378378
return type.getBottom();
379379
}
380380
switch (type.getBasic()) {
381-
case HeapType::ext:
382-
return HeapType::ext;
383381
case HeapType::func:
384382
return pickSubFunc();
385383
case HeapType::any:
@@ -392,13 +390,16 @@ struct HeapTypeGeneratorImpl {
392390
return pickSubStruct();
393391
case HeapType::array:
394392
return pickSubArray();
393+
case HeapType::ext:
394+
case HeapType::exn:
395395
case HeapType::string:
396396
case HeapType::stringview_wtf8:
397397
case HeapType::stringview_wtf16:
398398
case HeapType::stringview_iter:
399399
case HeapType::none:
400400
case HeapType::noext:
401401
case HeapType::nofunc:
402+
case HeapType::noexn:
402403
return type;
403404
}
404405
WASM_UNREACHABLE("unexpected type");
@@ -440,6 +441,7 @@ struct HeapTypeGeneratorImpl {
440441
switch (type.getBasic()) {
441442
case HeapType::ext:
442443
case HeapType::func:
444+
case HeapType::exn:
443445
case HeapType::any:
444446
break;
445447
case HeapType::eq:
@@ -464,6 +466,9 @@ struct HeapTypeGeneratorImpl {
464466
case HeapType::noext:
465467
candidates.push_back(HeapType::ext);
466468
break;
469+
case HeapType::noexn:
470+
candidates.push_back(HeapType::exn);
471+
break;
467472
}
468473
assert(!candidates.empty());
469474
return rand.pick(candidates);

src/wasm-binary.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@ enum EncodedType {
412412
nullable = -0x14, // 0x6c
413413
nonnullable = -0x15, // 0x6b
414414
#endif
415+
// exception handling
416+
exnref = -0x17, // 0x69
417+
nullexnref = -0xff, // TODO
415418
// string reference types
416419
#if STANDARD_GC_ENCODINGS
417420
stringref = -0x19, // 0x67
@@ -449,14 +452,16 @@ enum EncodedHeapType {
449452
noext = -0xe, // 0x72
450453
none = -0xf, // 0x71
451454
#else
452-
noext = -0x17, // 0x69
453-
nofunc = -0x18, // 0x68
454-
none = -0x1b, // 0x65
455+
noext = -0x17, // 0x69
456+
nofunc = -0x18, // 0x68
457+
none = -0x1b, // 0x65
455458
#endif
456-
func = -0x10, // 0x70
457-
ext = -0x11, // 0x6f
458-
any = -0x12, // 0x6e
459-
eq = -0x13, // 0x6d
459+
func = -0x10, // 0x70
460+
ext = -0x11, // 0x6f
461+
any = -0x12, // 0x6e
462+
eq = -0x13, // 0x6d
463+
exn = -0x17, // 0x69
464+
noexn = -0xff, // TODO
460465
#if STANDARD_GC_ENCODINGS
461466
i31 = -0x14, // 0x6c
462467
struct_ = -0x15, // 0x6b

src/wasm-type.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ class Type {
137137
// │ eqref ║ x │ │ x │ x │ n │ │ n_ullable
138138
// │ i31ref ║ x │ │ x │ x │ n │ │
139139
// │ structref ║ x │ │ x │ x │ n │ │
140+
// │ arrayref ║ x │ │ x │ x │ n │ │
141+
// │ exnref ║ x │ │ x │ x │ n │ │
142+
// │ stringref ║ x │ │ x │ x │ n │ │
140143
// ├─ Compound ──╫───┼───┼───┼───┤───────┤ │
141144
// │ Ref ║ │ x │ x │ x │ f? n? │◄┘
142145
// │ Tuple ║ │ x │ │ x │ │
@@ -167,6 +170,7 @@ class Type {
167170
bool isSignature() const;
168171
bool isStruct() const;
169172
bool isArray() const;
173+
bool isException() const;
170174
bool isString() const;
171175
bool isDefaultable() const;
172176

@@ -322,15 +326,17 @@ class HeapType {
322326
i31,
323327
struct_,
324328
array,
329+
exn,
325330
string,
326331
stringview_wtf8,
327332
stringview_wtf16,
328333
stringview_iter,
329334
none,
330335
noext,
331336
nofunc,
337+
noexn,
332338
};
333-
static constexpr BasicHeapType _last_basic_type = nofunc;
339+
static constexpr BasicHeapType _last_basic_type = noexn;
334340

335341
// BasicHeapType can be implicitly upgraded to HeapType
336342
constexpr HeapType(BasicHeapType id) : id(id) {}
@@ -364,6 +370,7 @@ class HeapType {
364370
bool isContinuation() const;
365371
bool isStruct() const;
366372
bool isArray() const;
373+
bool isException() const;
367374
bool isString() const;
368375
bool isBottom() const;
369376
bool isOpen() const;

src/wasm/literal.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ Literal::Literal(const Literal& other) : type(other.type) {
133133
case HeapType::none:
134134
case HeapType::noext:
135135
case HeapType::nofunc:
136+
case HeapType::noexn:
136137
WASM_UNREACHABLE("null literals should already have been handled");
137138
case HeapType::any:
138139
case HeapType::eq:
139140
case HeapType::func:
140141
case HeapType::struct_:
141142
case HeapType::array:
143+
case HeapType::exn:
142144
WASM_UNREACHABLE("invalid type");
143145
case HeapType::string:
144146
case HeapType::stringview_wtf8:
@@ -613,9 +615,15 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
613615
case HeapType::nofunc:
614616
o << "nullfuncref";
615617
break;
618+
case HeapType::noexn:
619+
o << "nullexnref";
620+
break;
616621
case HeapType::ext:
617622
o << "externref";
618623
break;
624+
case HeapType::exn:
625+
o << "exnref";
626+
break;
619627
case HeapType::any:
620628
case HeapType::eq:
621629
case HeapType::func:

src/wasm/wasm-binary.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,10 @@ void WasmBinaryWriter::writeType(Type type) {
14721472
o << S32LEB(BinaryConsts::EncodedType::externref);
14731473
return;
14741474
}
1475+
if (Type::isSubType(type, Type(HeapType::exn, Nullable))) {
1476+
o << S32LEB(BinaryConsts::EncodedType::exnref);
1477+
return;
1478+
}
14751479
if (Type::isSubType(type, Type(HeapType::string, Nullable))) {
14761480
o << S32LEB(BinaryConsts::EncodedType::stringref);
14771481
return;
@@ -1502,6 +1506,9 @@ void WasmBinaryWriter::writeType(Type type) {
15021506
case HeapType::array:
15031507
o << S32LEB(BinaryConsts::EncodedType::arrayref);
15041508
return;
1509+
case HeapType::exn:
1510+
o << S32LEB(BinaryConsts::EncodedType::exnref);
1511+
return;
15051512
case HeapType::string:
15061513
o << S32LEB(BinaryConsts::EncodedType::stringref);
15071514
return;
@@ -1523,6 +1530,9 @@ void WasmBinaryWriter::writeType(Type type) {
15231530
case HeapType::nofunc:
15241531
o << S32LEB(BinaryConsts::EncodedType::nullfuncref);
15251532
return;
1533+
case HeapType::noexn:
1534+
o << S32LEB(BinaryConsts::EncodedType::nullexnref);
1535+
return;
15261536
}
15271537
}
15281538
if (type.isNullable()) {
@@ -1570,6 +1580,8 @@ void WasmBinaryWriter::writeHeapType(HeapType type) {
15701580
type = HeapType::func;
15711581
} else if (HeapType::isSubType(type, HeapType::ext)) {
15721582
type = HeapType::ext;
1583+
} else if (HeapType::isSubType(type, HeapType::exn)) {
1584+
type = HeapType::exn;
15731585
} else if (wasm->features.hasStrings()) {
15741586
// Strings are enabled, and this isn't a func or an ext, so it must be a
15751587
// string type (string or stringview), which we'll emit below, or a bottom
@@ -1609,6 +1621,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) {
16091621
case HeapType::array:
16101622
ret = BinaryConsts::EncodedHeapType::array;
16111623
break;
1624+
case HeapType::exn:
1625+
ret = BinaryConsts::EncodedHeapType::exn;
1626+
break;
16121627
case HeapType::string:
16131628
ret = BinaryConsts::EncodedHeapType::string;
16141629
break;
@@ -1630,6 +1645,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) {
16301645
case HeapType::nofunc:
16311646
ret = BinaryConsts::EncodedHeapType::nofunc;
16321647
break;
1648+
case HeapType::noexn:
1649+
ret = BinaryConsts::EncodedHeapType::noexn;
1650+
break;
16331651
}
16341652
o << S64LEB(ret); // TODO: Actually s33
16351653
}
@@ -1980,6 +1998,9 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) {
19801998
case BinaryConsts::EncodedType::arrayref:
19811999
out = Type(HeapType::array, Nullable);
19822000
return true;
2001+
case BinaryConsts::EncodedType::exnref:
2002+
out = Type(HeapType::exn, Nullable);
2003+
return true;
19832004
case BinaryConsts::EncodedType::stringref:
19842005
out = Type(HeapType::string, Nullable);
19852006
return true;
@@ -2001,6 +2022,9 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) {
20012022
case BinaryConsts::EncodedType::nullfuncref:
20022023
out = Type(HeapType::nofunc, Nullable);
20032024
return true;
2025+
case BinaryConsts::EncodedType::nullexnref:
2026+
out = Type(HeapType::noexn, Nullable);
2027+
return true;
20042028
default:
20052029
return false;
20062030
}
@@ -2029,6 +2053,9 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) {
20292053
case BinaryConsts::EncodedHeapType::array:
20302054
out = HeapType::array;
20312055
return true;
2056+
case BinaryConsts::EncodedHeapType::exn:
2057+
out = HeapType::exn;
2058+
return true;
20322059
case BinaryConsts::EncodedHeapType::string:
20332060
out = HeapType::string;
20342061
return true;
@@ -2050,6 +2077,9 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) {
20502077
case BinaryConsts::EncodedHeapType::nofunc:
20512078
out = HeapType::nofunc;
20522079
return true;
2080+
case BinaryConsts::EncodedHeapType::noexn:
2081+
out = HeapType::noexn;
2082+
return true;
20532083
default:
20542084
return false;
20552085
}

src/wasm/wasm-s-parser.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str,
12791279
if (str.substr(0, 8) == "arrayref" && (prefix || str.size() == 8)) {
12801280
return Type(HeapType::array, Nullable);
12811281
}
1282+
if (str.substr(0, 6) == "exnref" && (prefix || str.size() == 6)) {
1283+
return Type(HeapType::exn, Nullable);
1284+
}
12821285
if (str.substr(0, 9) == "stringref" && (prefix || str.size() == 9)) {
12831286
return Type(HeapType::string, Nullable);
12841287
}
@@ -1300,6 +1303,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str,
13001303
if (str.substr(0, 11) == "nullfuncref" && (prefix || str.size() == 11)) {
13011304
return Type(HeapType::nofunc, Nullable);
13021305
}
1306+
if (str.substr(0, 10) == "nullexnref" && (prefix || str.size() == 10)) {
1307+
return Type(HeapType::noexn, Nullable);
1308+
}
13031309
if (allowError) {
13041310
return Type::none;
13051311
}
@@ -1330,6 +1336,9 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str,
13301336
if (str.substr(0, 5) == "array" && (prefix || str.size() == 5)) {
13311337
return HeapType::array;
13321338
}
1339+
if (str.substr(0, 3) == "exn" && (prefix || str.size() == 3)) {
1340+
return HeapType::exn;
1341+
}
13331342
if (str.substr(0, 6) == "string" && (prefix || str.size() == 6)) {
13341343
return HeapType::string;
13351344
}
@@ -1351,6 +1360,12 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str,
13511360
if (str.substr(0, 6) == "nofunc" && (prefix || str.size() == 6)) {
13521361
return HeapType::nofunc;
13531362
}
1363+
if (str.substr(0, 6) == "nofunc" && (prefix || str.size() == 6)) {
1364+
return HeapType::nofunc;
1365+
}
1366+
if (str.substr(0, 5) == "noexn" && (prefix || str.size() == 5)) {
1367+
return HeapType::noexn;
1368+
}
13541369
throw ParseException(std::string("invalid wasm heap type: ") +
13551370
std::string(str.data(), str.size()));
13561371
}

0 commit comments

Comments
 (0)