summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asmjs/asm_v_wasm.cpp6
-rw-r--r--src/binaryen-c.cpp10
-rw-r--r--src/binaryen-c.h2
-rw-r--r--src/ir/abstract.h4
-rw-r--r--src/js/binaryen.js-post.js14
-rw-r--r--src/literal.h2
-rw-r--r--src/parsing.h2
-rw-r--r--src/passes/ConstHoisting.cpp4
-rw-r--r--src/passes/FuncCastEmulation.cpp8
-rw-r--r--src/passes/InstrumentLocals.cpp24
-rw-r--r--src/shell-interface.h3
-rw-r--r--src/tools/fuzzing.h37
-rw-r--r--src/tools/spec-wrapper.h5
-rw-r--r--src/tools/wasm-reduce.cpp10
-rw-r--r--src/wasm-binary.h18
-rw-r--r--src/wasm-builder.h8
-rw-r--r--src/wasm-interpreter.h4
-rw-r--r--src/wasm-type.h4
-rw-r--r--src/wasm/literal.cpp42
-rw-r--r--src/wasm/wasm-binary.cpp12
-rw-r--r--src/wasm/wasm-s-parser.cpp6
-rw-r--r--src/wasm/wasm-stack.cpp6
-rw-r--r--src/wasm/wasm-type.cpp32
-rw-r--r--src/wasm/wasm-validator.cpp4
24 files changed, 242 insertions, 25 deletions
diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp
index 8d2894f13..e7b4d6edd 100644
--- a/src/asmjs/asm_v_wasm.cpp
+++ b/src/asmjs/asm_v_wasm.cpp
@@ -58,6 +58,8 @@ AsmType wasmToAsmType(Type type) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
assert(false && "reference types are not supported by asm2wasm");
case Type::none:
return ASM_NONE;
@@ -88,6 +90,10 @@ char getSig(Type type) {
return 'E';
case Type::anyref:
return 'A';
+ case Type::eqref:
+ return 'Q';
+ case Type::i31ref:
+ return 'I';
case Type::none:
return 'v';
case Type::unreachable:
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 1c938faab..2f1d3f5ff 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -74,8 +74,11 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case Type::externref:
case Type::exnref:
case Type::anyref:
- assert(x.isNull());
+ case Type::eqref:
+ assert(x.isNull() && "unexpected non-null reference type literal");
break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -100,7 +103,10 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
return Literal::makeNull(Type(x.type));
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -136,6 +142,8 @@ BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; }
BinaryenType BinaryenTypeExternref(void) { return Type::externref; }
BinaryenType BinaryenTypeExnref(void) { return Type::exnref; }
BinaryenType BinaryenTypeAnyref(void) { return Type::anyref; }
+BinaryenType BinaryenTypeEqref(void) { return Type::eqref; }
+BinaryenType BinaryenTypeI31ref(void) { return Type::i31ref; }
BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; }
BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); }
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index f368ad122..3a3be4608 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -102,6 +102,8 @@ BINARYEN_API BinaryenType BinaryenTypeFuncref(void);
BINARYEN_API BinaryenType BinaryenTypeExternref(void);
BINARYEN_API BinaryenType BinaryenTypeExnref(void);
BINARYEN_API BinaryenType BinaryenTypeAnyref(void);
+BINARYEN_API BinaryenType BinaryenTypeEqref(void);
+BINARYEN_API BinaryenType BinaryenTypeI31ref(void);
BINARYEN_API BinaryenType BinaryenTypeUnreachable(void);
// Not a real type. Used as the last parameter to BinaryenBlock to let
// the API figure out the type instead of providing one.
diff --git a/src/ir/abstract.h b/src/ir/abstract.h
index ce5b6b008..ac67a59b3 100644
--- a/src/ir/abstract.h
+++ b/src/ir/abstract.h
@@ -103,6 +103,8 @@ inline UnaryOp getUnary(Type type, Op op) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable: {
return InvalidUnary;
@@ -266,6 +268,8 @@ inline BinaryOp getBinary(Type type, Op op) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable: {
return InvalidBinary;
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 87a6bacda..4703abc54 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -37,6 +37,8 @@ function initializeConstants() {
['externref', 'Externref'],
['exnref', 'Exnref'],
['anyref', 'Anyref'],
+ ['eqref', 'Eqref'],
+ ['i31ref', 'I31ref'],
['unreachable', 'Unreachable'],
['auto', 'Auto']
].forEach(entry => {
@@ -2070,6 +2072,18 @@ function wrapModule(module, self = {}) {
}
};
+ self['eqref'] = {
+ 'pop'() {
+ return Module['_BinaryenPop'](module, Module['eqref']);
+ }
+ };
+
+ self['i31ref'] = {
+ 'pop'() {
+ return Module['_BinaryenPop'](module, Module['i31ref']);
+ }
+ };
+
self['ref'] = {
'null'(type) {
return Module['_BinaryenRefNull'](module, type);
diff --git a/src/literal.h b/src/literal.h
index c617f56f0..698063cbe 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -595,6 +595,8 @@ template<> struct less<wasm::Literal> {
case wasm::Type::externref:
case wasm::Type::exnref:
case wasm::Type::anyref:
+ case wasm::Type::eqref:
+ case wasm::Type::i31ref:
case wasm::Type::none:
case wasm::Type::unreachable:
return false;
diff --git a/src/parsing.h b/src/parsing.h
index d809cbedd..bdc3e63b7 100644
--- a/src/parsing.h
+++ b/src/parsing.h
@@ -267,6 +267,8 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
WASM_UNREACHABLE("unexpected const type");
case Type::none:
case Type::unreachable: {
diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp
index 3b34751ff..a972c05fb 100644
--- a/src/passes/ConstHoisting.cpp
+++ b/src/passes/ConstHoisting.cpp
@@ -97,7 +97,9 @@ private:
case Type::funcref:
case Type::externref:
case Type::exnref:
- case Type::anyref: {
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref: {
return false;
}
case Type::none:
diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp
index 101834790..6f5e9d611 100644
--- a/src/passes/FuncCastEmulation.cpp
+++ b/src/passes/FuncCastEmulation.cpp
@@ -68,7 +68,9 @@ static Expression* toABI(Expression* value, Module* module) {
case Type::funcref:
case Type::externref:
case Type::exnref:
- case Type::anyref: {
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref: {
WASM_UNREACHABLE("reference types cannot be converted to i64");
}
case Type::none: {
@@ -112,7 +114,9 @@ static Expression* fromABI(Expression* value, Type type, Module* module) {
case Type::funcref:
case Type::externref:
case Type::exnref:
- case Type::anyref: {
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref: {
WASM_UNREACHABLE("reference types cannot be converted from i64");
}
case Type::none: {
diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp
index f9c26d788..8803a7811 100644
--- a/src/passes/InstrumentLocals.cpp
+++ b/src/passes/InstrumentLocals.cpp
@@ -60,6 +60,8 @@ Name get_funcref("get_funcref");
Name get_externref("get_externref");
Name get_exnref("get_exnref");
Name get_anyref("get_anyref");
+Name get_eqref("get_eqref");
+Name get_i31ref("get_i31ref");
Name get_v128("get_v128");
Name set_i32("set_i32");
@@ -70,6 +72,8 @@ Name set_funcref("set_funcref");
Name set_externref("set_externref");
Name set_exnref("set_exnref");
Name set_anyref("set_anyref");
+Name set_eqref("set_eqref");
+Name set_i31ref("set_i31ref");
Name set_v128("set_v128");
struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
@@ -104,6 +108,12 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
case Type::anyref:
import = get_anyref;
break;
+ case Type::eqref:
+ import = get_eqref;
+ break;
+ case Type::i31ref:
+ import = get_i31ref;
+ break;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -153,6 +163,12 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
case Type::anyref:
import = set_anyref;
break;
+ case Type::eqref:
+ import = set_eqref;
+ break;
+ case Type::i31ref:
+ import = set_i31ref;
+ break;
case Type::unreachable:
return; // nothing to do here
case Type::none:
@@ -203,6 +219,14 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref);
addImport(
curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref);
+ addImport(
+ curr, get_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref);
+ addImport(
+ curr, set_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref);
+ addImport(
+ curr, get_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref);
+ addImport(
+ curr, set_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref);
}
}
if (curr->features.hasSIMD()) {
diff --git a/src/shell-interface.h b/src/shell-interface.h
index ae86d13ec..8d35905ee 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -119,8 +119,11 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
globals[import->name] = {Literal::makeNull(import->type)};
break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index e6cc4e444..0783588cd 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -324,6 +324,15 @@ private:
if (wasm.features.hasExceptionHandling()) {
options.push_back(Type::exnref);
}
+ if (wasm.features.hasGC()) {
+ options.push_back(Type::eqref);
+ // TODO: i31ref
+ }
+ }
+ break;
+ case Type::eqref:
+ if (wasm.features.hasGC()) {
+ // TODO: i31ref
}
break;
default:
@@ -1362,6 +1371,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -1466,6 +1477,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -1595,6 +1608,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -1640,6 +1655,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1708,6 +1725,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1735,6 +1754,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1845,6 +1866,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
return makeTrivial(type);
case Type::none:
case Type::unreachable:
@@ -1990,6 +2013,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2227,6 +2252,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2434,6 +2461,8 @@ private:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2674,7 +2703,9 @@ private:
.add(FeatureSet::ReferenceTypes, Type::funcref, Type::externref)
.add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling,
Type::exnref)
- .add(FeatureSet::ReferenceTypes | FeatureSet::GC, Type::anyref));
+ .add(FeatureSet::ReferenceTypes | FeatureSet::GC,
+ Type::anyref,
+ Type::eqref)); // TODO: i31ref
}
Type getSingleConcreteType() { return pick(getSingleConcreteTypes()); }
@@ -2685,7 +2716,9 @@ private:
.add(FeatureSet::ReferenceTypes, Type::funcref, Type::externref)
.add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling,
Type::exnref)
- .add(FeatureSet::ReferenceTypes | FeatureSet::GC, Type::anyref));
+ .add(FeatureSet::ReferenceTypes | FeatureSet::GC,
+ Type::anyref,
+ Type::eqref)); // TODO: i31ref
}
Type getReferenceType() { return pick(getReferenceTypes()); }
diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h
index 200571fd0..5a61d72b6 100644
--- a/src/tools/spec-wrapper.h
+++ b/src/tools/spec-wrapper.h
@@ -61,6 +61,11 @@ static std::string generateSpecWrapper(Module& wasm) {
case Type::anyref:
ret += "(ref.null any)";
break;
+ case Type::eqref:
+ ret += "(ref.null eq)";
+ break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index 7410ff91e..7a81007dc 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -599,6 +599,8 @@ struct Reducer
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
continue; // not implemented yet
case Type::none:
case Type::unreachable:
@@ -625,6 +627,8 @@ struct Reducer
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
continue; // not implemented yet
case Type::none:
case Type::unreachable:
@@ -651,6 +655,8 @@ struct Reducer
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
continue; // not implemented yet
case Type::none:
case Type::unreachable:
@@ -677,6 +683,8 @@ struct Reducer
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
continue; // not implemented yet
case Type::none:
case Type::unreachable:
@@ -689,6 +697,8 @@ struct Reducer
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
continue; // not implemented yet
case Type::none:
case Type::unreachable:
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 7666fa842..39980ee04 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -346,6 +346,10 @@ enum EncodedType {
externref = -0x11, // 0x6f
// any reference type
anyref = -0x12, // 0x6e
+ // comparable reference type
+ eqref = -0x13, // 0x6d
+ // integer reference type
+ i31ref = -0x16, // 0x6a
// exception reference type
exnref = -0x18, // 0x68
// func_type form
@@ -358,6 +362,8 @@ enum EncodedHeapType {
func = -0x10, // 0x70
extern_ = -0x11, // 0x6f
any = -0x12, // 0x6e
+ eq = -0x13, // 0x6d
+ i31 = -0x17, // 0x69, != i31ref
exn = -0x18, // 0x68
};
@@ -981,6 +987,12 @@ inline S32LEB binaryType(Type type) {
case Type::anyref:
ret = BinaryConsts::EncodedType::anyref;
break;
+ case Type::eqref:
+ ret = BinaryConsts::EncodedType::eqref;
+ break;
+ case Type::i31ref:
+ ret = BinaryConsts::EncodedType::i31ref;
+ break;
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
}
@@ -1003,11 +1015,15 @@ inline S32LEB binaryHeapType(HeapType type) {
ret = BinaryConsts::EncodedHeapType::any;
break;
case HeapType::EqKind:
+ ret = BinaryConsts::EncodedHeapType::eq;
+ break;
case HeapType::I31Kind:
+ ret = BinaryConsts::EncodedHeapType::i31;
+ break;
case HeapType::SignatureKind:
case HeapType::StructKind:
case HeapType::ArrayKind:
- WASM_UNREACHABLE("TODO: GC types");
+ WASM_UNREACHABLE("TODO: compound GC types");
}
return S32LEB(ret); // TODO: Actually encoded as s33
}
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index b35fde376..737dad16a 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -645,8 +645,11 @@ public:
case Type::externref:
case Type::exnref: // TODO: ExceptionPackage?
case Type::anyref:
- assert(value.isNull());
+ case Type::eqref:
+ assert(value.isNull() && "unexpected non-null reference type literal");
return makeRefNull(value.type);
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
default:
assert(value.type.isNumber());
return makeConst(value);
@@ -840,7 +843,10 @@ public:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
return ExpressionManipulator::refNull(curr, curr->type);
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
return ExpressionManipulator::nop(curr);
case Type::unreachable:
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 51cc24d01..69d6ff771 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1653,6 +1653,8 @@ public:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1710,6 +1712,8 @@ public:
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm-type.h b/src/wasm-type.h
index f3973068f..4a55d7b33 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -51,7 +51,9 @@ public:
externref,
exnref,
anyref,
- _last_basic_id = anyref
+ eqref,
+ i31ref,
+ _last_basic_id = i31ref,
};
Type() = default;
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 39a4cea3c..4a89b5cd1 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -70,7 +70,10 @@ Literal::Literal(const Literal& other) : type(other.type) {
break;
case Type::externref:
case Type::anyref:
+ case Type::eqref:
break; // null
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::funcref:
case Type::exnref:
case Type::unreachable:
@@ -223,10 +226,11 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
- if (isNull()) {
- break;
- }
- // falls through
+ case Type::eqref:
+ assert(isNull() && "unexpected non-null reference type literal");
+ break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -379,6 +383,10 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
o << "funcref(" << literal.getFunc() << ")";
}
break;
+ case Type::externref:
+ assert(literal.isNull() && "unexpected non-null externref literal");
+ o << "externref(null)";
+ break;
case Type::exnref:
if (literal.isNull()) {
o << "exnref(null)";
@@ -387,13 +395,15 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
}
break;
case Type::anyref:
- assert(literal.isNull() && "TODO: non-null anyref values");
+ assert(literal.isNull() && "unexpected non-null anyref literal");
o << "anyref(null)";
break;
- case Type::externref:
- assert(literal.isNull() && "TODO: non-null externref values");
- o << "externref(null)";
+ case Type::eqref:
+ assert(literal.isNull() && "unexpected non-null eqref literal");
+ o << "eqref(null)";
break;
+ case Type::i31ref:
+ WASM_UNREACHABLE("TODO: i31ref");
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
}
@@ -619,6 +629,8 @@ Literal Literal::eqz() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -641,6 +653,8 @@ Literal Literal::neg() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -663,6 +677,8 @@ Literal Literal::abs() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -768,6 +784,8 @@ Literal Literal::add(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -790,6 +808,8 @@ Literal Literal::sub(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -908,6 +928,8 @@ Literal Literal::mul(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1154,6 +1176,8 @@ Literal Literal::eq(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1176,6 +1200,8 @@ Literal Literal::ne(const Literal& other) const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 18a66fb2c..a6299c892 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1206,10 +1206,14 @@ Type WasmBinaryBuilder::getType() {
return Type::exnref;
case BinaryConsts::EncodedType::anyref:
return Type::anyref;
+ case BinaryConsts::EncodedType::eqref:
+ return Type::eqref;
+ case BinaryConsts::EncodedType::i31ref:
+ return Type::i31ref;
default:
throwError("invalid wasm type: " + std::to_string(type));
}
- WASM_UNREACHABLE("unexpeced type");
+ WASM_UNREACHABLE("unexpected type");
}
HeapType WasmBinaryBuilder::getHeapType() {
@@ -1230,10 +1234,14 @@ HeapType WasmBinaryBuilder::getHeapType() {
return HeapType::ExnKind;
case BinaryConsts::EncodedHeapType::any:
return HeapType::AnyKind;
+ case BinaryConsts::EncodedHeapType::eq:
+ return HeapType::EqKind;
+ case BinaryConsts::EncodedHeapType::i31:
+ return HeapType::I31Kind;
default:
throwError("invalid wasm heap type: " + std::to_string(type));
}
- WASM_UNREACHABLE("unexpeced type");
+ WASM_UNREACHABLE("unexpected type");
}
Type WasmBinaryBuilder::getConcreteType() {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 8bbcc9ac0..2aa60979f 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -875,6 +875,12 @@ Type SExpressionWasmBuilder::stringToType(const char* str,
if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) {
return Type::anyref;
}
+ if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) {
+ return Type::eqref;
+ }
+ if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) {
+ return Type::i31ref;
+ }
if (allowError) {
return Type::none;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 30816546a..66f9e02dd 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -192,6 +192,8 @@ void BinaryInstWriter::visitLoad(Load* curr) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
WASM_UNREACHABLE("unexpected type");
}
@@ -294,6 +296,8 @@ void BinaryInstWriter::visitStore(Store* curr) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -697,6 +701,8 @@ void BinaryInstWriter::visitConst(Const* curr) {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index d88b7b027..cf68d92e9 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -260,9 +260,10 @@ std::unordered_map<TypeInfo, uintptr_t> indices = {
{TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref},
{TypeInfo({Type::anyref}), Type::anyref},
{TypeInfo(HeapType(HeapType::AnyKind), true), Type::anyref},
- // TODO (GC): Add canonical ids
- // * `(ref null eq) == eqref`
- // * `(ref i31) == i31ref`
+ {TypeInfo({Type::eqref}), Type::eqref},
+ {TypeInfo(HeapType(HeapType::EqKind), true), Type::eqref},
+ {TypeInfo({Type::i31ref}), Type::i31ref},
+ {TypeInfo(HeapType(HeapType::I31Kind), false), Type::i31ref},
};
} // anonymous namespace
@@ -341,7 +342,7 @@ bool Type::isTuple() const {
bool Type::isRef() const {
if (isBasic()) {
- return id >= funcref && id <= anyref;
+ return id >= funcref && id <= i31ref;
} else {
return getTypeInfo(*this)->isRef();
}
@@ -367,7 +368,7 @@ bool Type::isException() const {
bool Type::isNullable() const {
if (isBasic()) {
- return id >= funcref && id <= anyref;
+ return id >= funcref && id <= eqref; // except i31ref
} else {
return getTypeInfo(*this)->isNullable();
}
@@ -409,6 +410,8 @@ unsigned Type::getByteSize() const {
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
case Type::unreachable:
break;
@@ -454,6 +457,8 @@ FeatureSet Type::getFeatures() const {
case Type::exnref:
return FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling;
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
return FeatureSet::ReferenceTypes | FeatureSet::GC;
default:
return FeatureSet::MVP;
@@ -484,6 +489,10 @@ HeapType Type::getHeapType() const {
return HeapType::ExnKind;
case anyref:
return HeapType::AnyKind;
+ case eqref:
+ return HeapType::EqKind;
+ case i31ref:
+ return HeapType::I31Kind;
default:
break;
}
@@ -512,7 +521,8 @@ bool Type::isSubType(Type left, Type right) {
return true;
}
if (left.isRef() && right.isRef()) {
- return right == Type::anyref;
+ return right == Type::anyref ||
+ (left == Type::i31ref && right == Type::eqref);
}
if (left.isTuple() && right.isTuple()) {
if (left.size() != right.size()) {
@@ -543,6 +553,10 @@ Type Type::getLeastUpperBound(Type a, Type b) {
}
if (a.isRef()) {
if (b.isRef()) {
+ if ((a == Type::i31ref && b == Type::eqref) ||
+ (a == Type::eqref && b == Type::i31ref)) {
+ return Type::eqref;
+ }
// The LUB of two different reference types is anyref, which may or may
// not be a valid type depending on whether the anyref feature is enabled.
// When anyref is disabled, it is possible for the finalization of invalid
@@ -754,6 +768,12 @@ std::ostream& operator<<(std::ostream& os, Type type) {
case Type::anyref:
os << "anyref";
break;
+ case Type::eqref:
+ os << "eqref";
+ break;
+ case Type::i31ref:
+ os << "i31ref";
+ break;
}
} else {
os << *getTypeInfo(type);
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 505753c88..16ba60d72 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1396,6 +1396,8 @@ void FunctionValidator::validateMemBytes(uint8_t bytes,
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
WASM_UNREACHABLE("unexpected type");
}
@@ -2204,6 +2206,8 @@ void FunctionValidator::validateAlignment(
case Type::externref:
case Type::exnref:
case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
case Type::none:
WASM_UNREACHABLE("invalid type");
}