summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild-js.sh1
-rw-r--r--scripts/test/shared.py4
-rw-r--r--src/asmjs/asm_v_wasm.cpp8
-rw-r--r--src/binaryen-c.cpp4
-rw-r--r--src/binaryen-c.h1
-rw-r--r--src/ir/abstract.h2
-rw-r--r--src/js/binaryen.js-post.js1
-rw-r--r--src/literal.h2
-rw-r--r--src/parsing.h1
-rw-r--r--src/passes/ConstHoisting.cpp9
-rw-r--r--src/passes/FuncCastEmulation.cpp8
-rw-r--r--src/passes/InstrumentLocals.cpp6
-rw-r--r--src/shell-interface.h2
-rw-r--r--src/tools/fuzzing.h34
-rw-r--r--src/tools/spec-wrapper.h1
-rw-r--r--src/tools/tool-options.h1
-rw-r--r--src/tools/wasm-reduce.cpp5
-rw-r--r--src/wasm-binary.h8
-rw-r--r--src/wasm-builder.h3
-rw-r--r--src/wasm-features.h10
-rw-r--r--src/wasm-interpreter.h2
-rw-r--r--src/wasm-type.h1
-rw-r--r--src/wasm/literal.cpp10
-rw-r--r--src/wasm/wasm-binary.cpp6
-rw-r--r--src/wasm/wasm-s-parser.cpp3
-rw-r--r--src/wasm/wasm-stack.cpp12
-rw-r--r--src/wasm/wasm-type.cpp28
-rw-r--r--src/wasm/wasm-validator.cpp2
-rw-r--r--src/wasm/wasm.cpp1
-rw-r--r--test/anyref.wast18
-rw-r--r--test/anyref.wast.from-wast19
-rw-r--r--test/anyref.wast.fromBinary20
-rw-r--r--test/anyref.wast.fromBinary.noDebugInfo20
-rw-r--r--test/binaryen.js/exception-handling.js.txt6
-rw-r--r--test/binaryen.js/kitchen-sink.js1
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt17
-rw-r--r--test/binaryen.js/push-pop.js.txt2
-rw-r--r--test/example/c-api-kitchen-sink.c1
-rw-r--r--test/example/c-api-kitchen-sink.txt15
-rw-r--r--test/unit/input/reference_types_target_feature.wasmbin0 -> 150 bytes
-rw-r--r--test/unit/test_features.py32
41 files changed, 279 insertions, 48 deletions
diff --git a/build-js.sh b/build-js.sh
index 35ec946e3..861aceefd 100755
--- a/build-js.sh
+++ b/build-js.sh
@@ -186,6 +186,7 @@ export_function "_BinaryenTypeInt64"
export_function "_BinaryenTypeFloat32"
export_function "_BinaryenTypeFloat64"
export_function "_BinaryenTypeVec128"
+export_function "_BinaryenTypeAnyref"
export_function "_BinaryenTypeExnref"
export_function "_BinaryenTypeUnreachable"
export_function "_BinaryenTypeAuto"
diff --git a/scripts/test/shared.py b/scripts/test/shared.py
index 2440077a8..ad2f44c14 100644
--- a/scripts/test/shared.py
+++ b/scripts/test/shared.py
@@ -313,14 +313,14 @@ class Py2CalledProcessError(subprocess.CalledProcessError):
self.stderr = stderr
-def run_process(cmd, check=True, input=None, capture_output=False, *args, **kw):
+def run_process(cmd, check=True, input=None, capture_output=False, decode_output=True, *args, **kw):
if input and type(input) == str:
input = bytes(input, 'utf-8')
if capture_output:
kw['stdout'] = subprocess.PIPE
kw['stderr'] = subprocess.PIPE
ret = subprocess.run(cmd, check=check, input=input, *args, **kw)
- if ret.stdout is not None:
+ if decode_output and ret.stdout is not None:
ret.stdout = ret.stdout.decode('utf-8')
if ret.stderr is not None:
ret.stderr = ret.stderr.decode('utf-8')
diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp
index 32653fdba..143d6667e 100644
--- a/src/asmjs/asm_v_wasm.cpp
+++ b/src/asmjs/asm_v_wasm.cpp
@@ -53,8 +53,10 @@ AsmType wasmToAsmType(Type type) {
return ASM_INT64;
case v128:
assert(false && "v128 not implemented yet");
+ case anyref:
+ assert(false && "anyref is not supported by asm2wasm");
case exnref:
- assert(false && "exnref is not in asm2wasm");
+ assert(false && "exnref is not supported by asm2wasm");
case none:
return ASM_NONE;
case unreachable:
@@ -75,6 +77,8 @@ char getSig(Type type) {
return 'd';
case v128:
return 'V';
+ case anyref:
+ return 'a';
case exnref:
return 'e';
case none:
@@ -105,6 +109,8 @@ Type sigToType(char sig) {
return f64;
case 'V':
return v128;
+ case 'a':
+ return anyref;
case 'e':
return exnref;
case 'v':
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 5d7566e4a..41fb245d4 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -70,6 +70,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
break;
}
+ case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case Type::none:
case Type::unreachable:
@@ -90,6 +91,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
return Literal(x.i64).castToF64();
case Type::v128:
return Literal(x.v128);
+ case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case Type::none:
case Type::unreachable:
@@ -210,6 +212,7 @@ void printArg(std::ostream& setup, std::ostream& out, BinaryenLiteral arg) {
out << "BinaryenLiteralVec128(" << array << ")";
break;
}
+ case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case Type::none:
case Type::unreachable:
@@ -265,6 +268,7 @@ BinaryenType BinaryenTypeInt64(void) { return i64; }
BinaryenType BinaryenTypeFloat32(void) { return f32; }
BinaryenType BinaryenTypeFloat64(void) { return f64; }
BinaryenType BinaryenTypeVec128(void) { return v128; }
+BinaryenType BinaryenTypeAnyref(void) { return anyref; }
BinaryenType BinaryenTypeExnref(void) { return exnref; }
BinaryenType BinaryenTypeUnreachable(void) { return unreachable; }
BinaryenType BinaryenTypeAuto(void) { return uint32_t(-1); }
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 37e8c3204..b7c99ed1a 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -74,6 +74,7 @@ BinaryenType BinaryenTypeInt64(void);
BinaryenType BinaryenTypeFloat32(void);
BinaryenType BinaryenTypeFloat64(void);
BinaryenType BinaryenTypeVec128(void);
+BinaryenType BinaryenTypeAnyref(void);
BinaryenType BinaryenTypeExnref(void);
BinaryenType BinaryenTypeUnreachable(void);
// Not a real type. Used as the last parameter to BinaryenBlock to let
diff --git a/src/ir/abstract.h b/src/ir/abstract.h
index e1c3b979a..2653218b0 100644
--- a/src/ir/abstract.h
+++ b/src/ir/abstract.h
@@ -81,6 +81,7 @@ inline UnaryOp getUnary(Type type, Op op) {
assert(false && "v128 not implemented yet");
WASM_UNREACHABLE();
}
+ case anyref: // there's no unary instructions for anyref
case exnref: // there's no unary instructions for exnref
case none:
case unreachable: {
@@ -212,6 +213,7 @@ inline BinaryOp getBinary(Type type, Op op) {
assert(false && "v128 not implemented yet");
WASM_UNREACHABLE();
}
+ case anyref: // there's no binary instructions for anyref
case exnref: // there's no binary instructions for exnref
case none:
case unreachable: {
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index a09ad76ab..635a10577 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -37,6 +37,7 @@ Module['i64'] = Module['_BinaryenTypeInt64']();
Module['f32'] = Module['_BinaryenTypeFloat32']();
Module['f64'] = Module['_BinaryenTypeFloat64']();
Module['v128'] = Module['_BinaryenTypeVec128']();
+Module['anyref'] = Module['_BinaryenTypeAnyref']();
Module['exnref'] = Module['_BinaryenTypeExnref']();
Module['unreachable'] = Module['_BinaryenTypeUnreachable']();
Module['auto'] = /* deprecated */ Module['undefined'] = Module['_BinaryenTypeAuto']();
diff --git a/src/literal.h b/src/literal.h
index 4b9dfae7c..9865b8707 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -80,6 +80,7 @@ public:
Literal(int32_t(0)),
Literal(int32_t(0)),
Literal(int32_t(0))}});
+ case Type::anyref: // there's no anyref literals
case Type::exnref: // there's no exnref literals
case none:
case unreachable:
@@ -430,6 +431,7 @@ template<> struct less<wasm::Literal> {
return a.reinterpreti64() < b.reinterpreti64();
case wasm::Type::v128:
return memcmp(a.getv128Ptr(), b.getv128Ptr(), 16) < 0;
+ case wasm::Type::anyref: // anyref is an opaque value
case wasm::Type::exnref: // exnref is an opaque value
case wasm::Type::none:
case wasm::Type::unreachable:
diff --git a/src/parsing.h b/src/parsing.h
index 0ee4e67ac..49051800f 100644
--- a/src/parsing.h
+++ b/src/parsing.h
@@ -263,6 +263,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) {
break;
}
case v128:
+ case anyref: // there's no anyref.const
case exnref: // there's no exnref.const
WASM_UNREACHABLE();
case none:
diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp
index 17761e765..08fede1df 100644
--- a/src/passes/ConstHoisting.cpp
+++ b/src/passes/ConstHoisting.cpp
@@ -91,12 +91,9 @@ private:
size = getTypeSize(value.type);
break;
}
- case v128: {
- // v128 not implemented yet
- return false;
- }
- case exnref: {
- // exnref cannot have literals
+ case v128: // v128 not implemented yet
+ case anyref: // anyref cannot have literals
+ case exnref: { // exnref cannot have literals
return false;
}
case none:
diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp
index 9d6923703..f938da3b7 100644
--- a/src/passes/FuncCastEmulation.cpp
+++ b/src/passes/FuncCastEmulation.cpp
@@ -66,6 +66,10 @@ static Expression* toABI(Expression* value, Module* module) {
assert(false && "v128 not implemented yet");
WASM_UNREACHABLE();
}
+ case anyref: {
+ assert(false && "anyref cannot be converted to i64");
+ WASM_UNREACHABLE();
+ }
case exnref: {
assert(false && "exnref cannot be converted to i64");
WASM_UNREACHABLE();
@@ -108,6 +112,10 @@ static Expression* fromABI(Expression* value, Type type, Module* module) {
assert(false && "v128 not implemented yet");
WASM_UNREACHABLE();
}
+ case anyref: {
+ assert(false && "anyref cannot be converted from i64");
+ WASM_UNREACHABLE();
+ }
case exnref: {
assert(false && "exnref cannot be converted from i64");
WASM_UNREACHABLE();
diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp
index a6a361fd2..ae1c30836 100644
--- a/src/passes/InstrumentLocals.cpp
+++ b/src/passes/InstrumentLocals.cpp
@@ -81,8 +81,10 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
break;
case v128:
assert(false && "v128 not implemented yet");
+ case anyref:
+ assert(false && "anyref not implemented yet");
case exnref:
- assert(false && "not implemented yet");
+ assert(false && "exnref not implemented yet");
case none:
WASM_UNREACHABLE();
case unreachable:
@@ -113,6 +115,8 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
break;
case v128:
assert(false && "v128 not implemented yet");
+ case anyref:
+ assert(false && "anyref not implemented yet");
case exnref:
assert(false && "exnref not implemented yet");
case unreachable:
diff --git a/src/shell-interface.h b/src/shell-interface.h
index 2d9f88846..72c7dc67b 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -114,6 +114,8 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
break;
case v128:
assert(false && "v128 not implemented yet");
+ case anyref:
+ assert(false && "anyref not implemented yet");
case exnref:
assert(false && "exnref not implemented yet");
case none:
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 68c4d992a..baf42336d 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -851,6 +851,7 @@ private:
case f32:
case f64:
case v128:
+ case anyref:
case exnref:
ret = _makeConcrete(type);
break;
@@ -1370,6 +1371,7 @@ private:
return builder.makeLoad(
16, false, offset, pick(1, 2, 4, 8, 16), ptr, type);
}
+ case anyref: // anyref cannot be loaded from memory
case exnref: // exnref cannot be loaded from memory
case none:
case unreachable:
@@ -1471,6 +1473,7 @@ private:
return builder.makeStore(
16, offset, pick(1, 2, 4, 8, 16), ptr, value, type);
}
+ case anyref: // anyref cannot be stored in memory
case exnref: // exnref cannot be stored in memory
case none:
case unreachable:
@@ -1481,7 +1484,7 @@ private:
Expression* makeStore(Type type) {
// exnref type cannot be stored in memory
- if (!allowMemory || type == exnref) {
+ if (!allowMemory || isReferenceType(type)) {
return makeTrivial(type);
}
auto* ret = makeNonAtomicStore(type);
@@ -1566,6 +1569,7 @@ private:
case f64:
return Literal(getDouble());
case v128:
+ case anyref: // anyref cannot have literals
case exnref: // exnref cannot have literals
case none:
case unreachable:
@@ -1608,6 +1612,7 @@ private:
case f64:
return Literal(double(small));
case v128:
+ case anyref: // anyref cannot have literals
case exnref: // exnref cannot have literals
case none:
case unreachable:
@@ -1673,6 +1678,7 @@ private:
std::numeric_limits<uint64_t>::max()));
break;
case v128:
+ case anyref: // anyref cannot have literals
case exnref: // exnref cannot have literals
case none:
case unreachable:
@@ -1704,6 +1710,7 @@ private:
value = Literal(double(int64_t(1) << upTo(64)));
break;
case v128:
+ case anyref: // anyref cannot have literals
case exnref: // exnref cannot have literals
case none:
case unreachable:
@@ -1728,12 +1735,21 @@ private:
}
Expression* makeConst(Type type) {
- if (type == exnref) {
- // There's no exnref.const.
- // TODO We should return a nullref once we implement instructions for
- // reference types proposal.
- assert(false && "exnref const is not implemented yet");
+ switch (type) {
+ case anyref:
+ // There's no anyref.const.
+ // TODO We should return a nullref once we implement instructions for
+ // reference types proposal.
+ assert(false && "anyref const is not implemented yet");
+ case exnref:
+ // There's no exnref.const.
+ // TODO We should return a nullref once we implement instructions for
+ // reference types proposal.
+ assert(false && "exnref const is not implemented yet");
+ default:
+ break;
}
+
auto* ret = wasm.allocator.alloc<Const>();
ret->value = makeLiteral(type);
ret->type = type;
@@ -1802,6 +1818,7 @@ private:
AllTrueVecI64x2),
make(v128)});
}
+ case anyref: // there's no unary ops for anyref
case exnref: // there's no unary ops for exnref
case none:
case unreachable:
@@ -1933,6 +1950,7 @@ private:
}
WASM_UNREACHABLE();
}
+ case anyref: // there's no unary ops for anyref
case exnref: // there's no unary ops for exnref
case none:
case unreachable:
@@ -1955,7 +1973,7 @@ private:
return makeTrivial(type);
}
// There's no binary ops for exnref
- if (type == exnref) {
+ if (isReferenceType(type)) {
makeTrivial(type);
}
@@ -2146,6 +2164,7 @@ private:
make(v128),
make(v128)});
}
+ case anyref: // there's no binary ops for anyref
case exnref: // there's no binary ops for exnref
case none:
case unreachable:
@@ -2340,6 +2359,7 @@ private:
op = ExtractLaneVecF64x2;
break;
case v128:
+ case anyref:
case exnref:
case none:
case unreachable:
diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h
index fcd2e6335..8dcb5fde4 100644
--- a/src/tools/spec-wrapper.h
+++ b/src/tools/spec-wrapper.h
@@ -48,6 +48,7 @@ static std::string generateSpecWrapper(Module& wasm) {
case v128:
ret += "(v128.const i32x4 0 0 0 0)";
break;
+ case anyref: // there's no anyref.const
case exnref: // there's no exnref.const
case none:
case unreachable:
diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h
index 7c1151c7f..0de42ad13 100644
--- a/src/tools/tool-options.h
+++ b/src/tools/tool-options.h
@@ -71,6 +71,7 @@ struct ToolOptions : public Options {
.addFeature(FeatureSet::ExceptionHandling,
"exception handling operations")
.addFeature(FeatureSet::TailCall, "tail call operations")
+ .addFeature(FeatureSet::ReferenceTypes, "reference types")
.add("--no-validation",
"-n",
"Disables validation, assumes inputs are correct",
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index f1f5a5b90..54c662211 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -592,6 +592,7 @@ struct Reducer
fixed = builder->makeUnary(TruncSFloat64ToInt32, child);
break;
case v128:
+ case anyref:
case exnref:
continue; // not implemented yet
case none:
@@ -614,6 +615,7 @@ struct Reducer
fixed = builder->makeUnary(TruncSFloat64ToInt64, child);
break;
case v128:
+ case anyref:
case exnref:
continue; // not implemented yet
case none:
@@ -636,6 +638,7 @@ struct Reducer
fixed = builder->makeUnary(DemoteFloat64, child);
break;
case v128:
+ case anyref:
case exnref:
continue; // not implemented yet
case none:
@@ -658,6 +661,7 @@ struct Reducer
case f64:
WASM_UNREACHABLE();
case v128:
+ case anyref:
case exnref:
continue; // not implemented yet
case none:
@@ -667,6 +671,7 @@ struct Reducer
break;
}
case v128:
+ case anyref:
case exnref:
continue; // not implemented yet
case none:
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 1efa24b48..d01502e9b 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -381,7 +381,9 @@ enum EncodedType {
v128 = -0x5, // 0x7b
// elem_type
AnyFunc = -0x10, // 0x70
- // reference type
+ // opaque reference type
+ anyref = -0x11, // 0x6f
+ // exception reference type
exnref = -0x18, // 0x68
// func_type form
Func = -0x20, // 0x60
@@ -406,6 +408,7 @@ extern const char* SignExtFeature;
extern const char* SIMD128Feature;
extern const char* ExceptionHandlingFeature;
extern const char* TailCallFeature;
+extern const char* ReferenceTypesFeature;
enum Subsection {
NameFunction = 1,
@@ -903,6 +906,9 @@ inline S32LEB binaryType(Type type) {
case v128:
ret = BinaryConsts::EncodedType::v128;
break;
+ case anyref:
+ ret = BinaryConsts::EncodedType::anyref;
+ break;
case exnref:
ret = BinaryConsts::EncodedType::exnref;
break;
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index a0a43bc07..4258b9336 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -723,6 +723,9 @@ public:
value = Literal(bytes.data());
break;
}
+ case anyref:
+ // TODO Implement and return nullref
+ assert(false && "anyref not implemented yet");
case exnref:
// TODO Implement and return nullref
assert(false && "exnref not implemented yet");
diff --git a/src/wasm-features.h b/src/wasm-features.h
index d1789a67a..a645c93a8 100644
--- a/src/wasm-features.h
+++ b/src/wasm-features.h
@@ -33,7 +33,8 @@ struct FeatureSet {
SignExt = 1 << 5,
ExceptionHandling = 1 << 6,
TailCall = 1 << 7,
- All = (1 << 8) - 1
+ ReferenceTypes = 1 << 8,
+ All = (1 << 9) - 1
};
static std::string toString(Feature f) {
@@ -54,6 +55,8 @@ struct FeatureSet {
return "exception-handling";
case TailCall:
return "tail-call";
+ case ReferenceTypes:
+ return "reference-types";
default:
WASM_UNREACHABLE();
}
@@ -72,6 +75,7 @@ struct FeatureSet {
bool hasSignExt() const { return features & SignExt; }
bool hasExceptionHandling() const { return features & ExceptionHandling; }
bool hasTailCall() const { return features & TailCall; }
+ bool hasReferenceTypes() const { return features & ReferenceTypes; }
bool hasAll() const { return features & All; }
void makeMVP() { features = MVP; }
@@ -86,6 +90,7 @@ struct FeatureSet {
void setSignExt(bool v = true) { set(SignExt, v); }
void setExceptionHandling(bool v = true) { set(ExceptionHandling, v); }
void setTailCall(bool v = true) { set(TailCall, v); }
+ void setReferenceTypes(bool v = true) { set(ReferenceTypes, v); }
void setAll(bool v = true) { features = v ? All : MVP; }
void enable(const FeatureSet& other) { features |= other.features; }
@@ -118,6 +123,9 @@ struct FeatureSet {
if (hasTailCall()) {
f(TailCall);
}
+ if (hasReferenceTypes()) {
+ f(ReferenceTypes);
+ }
}
bool operator<=(const FeatureSet& other) const {
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 53345f0ab..05d00ed10 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1142,6 +1142,7 @@ public:
return Literal(load64u(addr)).castToF64();
case v128:
return Literal(load128(addr).data());
+ case anyref: // anyref cannot be loaded from memory
case exnref: // exnref cannot be loaded from memory
case none:
case unreachable:
@@ -1196,6 +1197,7 @@ public:
case v128:
store128(addr, value.getv128());
break;
+ case anyref: // anyref cannot be stored from memory
case exnref: // exnref cannot be stored in memory
case none:
case unreachable:
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 61179ec1a..42426c2c1 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -28,6 +28,7 @@ enum Type {
f32,
f64,
v128,
+ anyref,
exnref,
// none means no type, e.g. a block can have no return type. but unreachable
// is different, as it can be "ignored" when doing type checking across
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 68268d366..43adec6f6 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -137,6 +137,7 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
case Type::v128:
memcpy(buf, &v128, sizeof(v128));
break;
+ case Type::anyref: // anyref type is opaque
case Type::exnref: // exnref type is opaque
case Type::none:
case Type::unreachable:
@@ -272,6 +273,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
o << "i32x4 ";
literal.printVec128(o, literal.getv128());
break;
+ case Type::anyref: // anyref type is opaque
case Type::exnref: // exnref type is opaque
case Type::unreachable:
WASM_UNREACHABLE();
@@ -475,6 +477,7 @@ Literal Literal::eqz() const {
case Type::f64:
return eq(Literal(double(0)));
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -494,6 +497,7 @@ Literal Literal::neg() const {
case Type::f64:
return Literal(int64_t(i64 ^ 0x8000000000000000ULL)).castToF64();
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -513,6 +517,7 @@ Literal Literal::abs() const {
case Type::f64:
return Literal(int64_t(i64 & 0x7fffffffffffffffULL)).castToF64();
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -615,6 +620,7 @@ Literal Literal::add(const Literal& other) const {
case Type::f64:
return Literal(getf64() + other.getf64());
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -634,6 +640,7 @@ Literal Literal::sub(const Literal& other) const {
case Type::f64:
return Literal(getf64() - other.getf64());
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -724,6 +731,7 @@ Literal Literal::mul(const Literal& other) const {
case Type::f64:
return Literal(getf64() * other.getf64());
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -942,6 +950,7 @@ Literal Literal::eq(const Literal& other) const {
case Type::f64:
return Literal(getf64() == other.getf64());
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
@@ -961,6 +970,7 @@ Literal Literal::ne(const Literal& other) const {
case Type::f64:
return Literal(getf64() != other.getf64());
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 7047b674e..d75973ab0 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -681,6 +681,8 @@ void WasmBinaryWriter::writeFeaturesSection() {
return BinaryConsts::UserSections::ExceptionHandlingFeature;
case FeatureSet::TailCall:
return BinaryConsts::UserSections::TailCallFeature;
+ case FeatureSet::ReferenceTypes:
+ return BinaryConsts::UserSections::ReferenceTypesFeature;
default:
WASM_UNREACHABLE();
}
@@ -1085,6 +1087,8 @@ Type WasmBinaryBuilder::getType() {
return f64;
case BinaryConsts::EncodedType::v128:
return v128;
+ case BinaryConsts::EncodedType::anyref:
+ return anyref;
case BinaryConsts::EncodedType::exnref:
return exnref;
default: { throwError("invalid wasm type: " + std::to_string(type)); }
@@ -2167,6 +2171,8 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) {
wasm.features.setSIMD();
} else if (name == BinaryConsts::UserSections::TailCallFeature) {
wasm.features.setTailCall();
+ } else if (name == BinaryConsts::UserSections::ReferenceTypesFeature) {
+ wasm.features.setReferenceTypes();
}
}
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index e1413d5fd..39f6b0a9f 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -893,6 +893,9 @@ Type SExpressionWasmBuilder::stringToType(const char* str,
return v128;
}
}
+ if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) {
+ return anyref;
+ }
if (strncmp(str, "exnref", 6) == 0 && (prefix || str[6] == 0)) {
return exnref;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index d3aba3b8c..cb60c50f9 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -147,6 +147,7 @@ void BinaryInstWriter::visitLoad(Load* curr) {
// the pointer is unreachable, so we are never reached; just don't emit
// a load
return;
+ case anyref: // anyref cannot be loaded from memory
case exnref: // exnref cannot be loaded from memory
case none:
WASM_UNREACHABLE();
@@ -246,6 +247,7 @@ void BinaryInstWriter::visitStore(Store* curr) {
o << int8_t(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::V128Store);
break;
+ case anyref: // anyref cannot be stored from memory
case exnref: // exnref cannot be stored in memory
case none:
case unreachable:
@@ -580,6 +582,7 @@ void BinaryInstWriter::visitConst(Const* curr) {
}
break;
}
+ case anyref: // there's no anyref.const
case exnref: // there's no exnref.const
case none:
case unreachable:
@@ -1493,6 +1496,11 @@ void BinaryInstWriter::mapLocalsAndEmitHeader() {
continue;
}
index += numLocalsByType[v128];
+ if (type == anyref) {
+ mappedLocals[i] = index + currLocalsByType[anyref] - 1;
+ continue;
+ }
+ index += numLocalsByType[anyref];
if (type == exnref) {
mappedLocals[i] = index + currLocalsByType[exnref] - 1;
continue;
@@ -1503,6 +1511,7 @@ void BinaryInstWriter::mapLocalsAndEmitHeader() {
o << U32LEB((numLocalsByType[i32] ? 1 : 0) + (numLocalsByType[i64] ? 1 : 0) +
(numLocalsByType[f32] ? 1 : 0) + (numLocalsByType[f64] ? 1 : 0) +
(numLocalsByType[v128] ? 1 : 0) +
+ (numLocalsByType[anyref] ? 1 : 0) +
(numLocalsByType[exnref] ? 1 : 0));
if (numLocalsByType[i32]) {
o << U32LEB(numLocalsByType[i32]) << binaryType(i32);
@@ -1519,6 +1528,9 @@ void BinaryInstWriter::mapLocalsAndEmitHeader() {
if (numLocalsByType[v128]) {
o << U32LEB(numLocalsByType[v128]) << binaryType(v128);
}
+ if (numLocalsByType[anyref]) {
+ o << U32LEB(numLocalsByType[anyref]) << binaryType(anyref);
+ }
if (numLocalsByType[exnref]) {
o << U32LEB(numLocalsByType[exnref]) << binaryType(exnref);
}
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 2a836ab42..39383a478 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -36,6 +36,8 @@ const char* printType(Type type) {
return "f64";
case Type::v128:
return "v128";
+ case Type::anyref:
+ return "anyref";
case Type::exnref:
return "exnref";
case Type::unreachable:
@@ -56,6 +58,7 @@ unsigned getTypeSize(Type type) {
return 8;
case Type::v128:
return 16;
+ case Type::anyref: // anyref type is opaque
case Type::exnref: // exnref type is opaque
case Type::none:
case Type::unreachable:
@@ -65,13 +68,16 @@ unsigned getTypeSize(Type type) {
}
FeatureSet getFeatures(Type type) {
- if (type == v128) {
- return FeatureSet::SIMD;
- }
- if (type == exnref) {
- return FeatureSet::ExceptionHandling;
+ switch (type) {
+ case v128:
+ return FeatureSet::SIMD;
+ case anyref:
+ return FeatureSet::ReferenceTypes;
+ case exnref:
+ return FeatureSet::ExceptionHandling;
+ default:
+ return FeatureSet();
}
- return FeatureSet();
}
Type getType(unsigned size, bool float_) {
@@ -117,8 +123,13 @@ bool isFloatType(Type type) {
bool isVectorType(Type type) { return type == v128; }
bool isReferenceType(Type type) {
- // TODO Add other reference types later
- return type == exnref;
+ switch (type) {
+ case anyref:
+ case exnref:
+ return true;
+ default:
+ return false;
+ }
}
Type reinterpretType(Type type) {
@@ -132,6 +143,7 @@ Type reinterpretType(Type type) {
case Type::f64:
return i64;
case Type::v128:
+ case Type::anyref:
case Type::exnref:
case Type::none:
case Type::unreachable:
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 8eb3341de..339ad6f68 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1134,6 +1134,7 @@ void FunctionValidator::validateMemBytes(uint8_t bytes,
shouldBeEqual(
bytes, uint8_t(16), curr, "expected v128 operation to touch 16 bytes");
break;
+ case anyref: // anyref cannot be stored in memory
case exnref: // exnref cannot be stored in memory
case none:
WASM_UNREACHABLE();
@@ -1788,6 +1789,7 @@ void FunctionValidator::validateAlignment(
case v128:
case unreachable:
break;
+ case anyref: // anyref cannot be stored in memory
case exnref: // exnref cannot be stored in memory
case none:
WASM_UNREACHABLE();
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 97b60bfb5..f8791286c 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -41,6 +41,7 @@ const char* TruncSatFeature = "nontrapping-fptoint";
const char* SignExtFeature = "sign-ext";
const char* SIMD128Feature = "simd128";
const char* TailCallFeature = "tail-call";
+const char* ReferenceTypesFeature = "reference-types";
} // namespace UserSections
} // namespace BinaryConsts
diff --git a/test/anyref.wast b/test/anyref.wast
new file mode 100644
index 000000000..d617d3f42
--- /dev/null
+++ b/test/anyref.wast
@@ -0,0 +1,18 @@
+(module
+ (memory 1 1)
+ (import "env" "test1" (func $test1 (param anyref) (result anyref)))
+ (import "env" "test2" (global $test2 anyref))
+ (export "test1" (func $test1 (param anyref) (result anyref)))
+ (export "test2" (global $test2))
+ (func $anyref_test (param $0 anyref) (result anyref)
+ (local $1 anyref)
+ (local.set $1
+ (call $test1
+ (local.get $0)
+ )
+ )
+ (return
+ (local.get $1)
+ )
+ )
+)
diff --git a/test/anyref.wast.from-wast b/test/anyref.wast.from-wast
new file mode 100644
index 000000000..117695077
--- /dev/null
+++ b/test/anyref.wast.from-wast
@@ -0,0 +1,19 @@
+(module
+ (type $FUNCSIG$aa (func (param anyref) (result anyref)))
+ (import "env" "test2" (global $test2 anyref))
+ (import "env" "test1" (func $test1 (param anyref) (result anyref)))
+ (memory $0 1 1)
+ (export "test1" (func $test1))
+ (export "test2" (global $test2))
+ (func $anyref_test (; 1 ;) (type $FUNCSIG$aa) (param $0 anyref) (result anyref)
+ (local $1 anyref)
+ (local.set $1
+ (call $test1
+ (local.get $0)
+ )
+ )
+ (return
+ (local.get $1)
+ )
+ )
+)
diff --git a/test/anyref.wast.fromBinary b/test/anyref.wast.fromBinary
new file mode 100644
index 000000000..3d9b223b6
--- /dev/null
+++ b/test/anyref.wast.fromBinary
@@ -0,0 +1,20 @@
+(module
+ (type $0 (func (param anyref) (result anyref)))
+ (import "env" "test2" (global $gimport$1 anyref))
+ (import "env" "test1" (func $test1 (param anyref) (result anyref)))
+ (memory $0 1 1)
+ (export "test1" (func $test1))
+ (export "test2" (global $gimport$1))
+ (func $anyref_test (; 1 ;) (type $0) (param $0 anyref) (result anyref)
+ (local $1 anyref)
+ (local.set $1
+ (call $test1
+ (local.get $0)
+ )
+ )
+ (return
+ (local.get $1)
+ )
+ )
+)
+
diff --git a/test/anyref.wast.fromBinary.noDebugInfo b/test/anyref.wast.fromBinary.noDebugInfo
new file mode 100644
index 000000000..d397cd3f9
--- /dev/null
+++ b/test/anyref.wast.fromBinary.noDebugInfo
@@ -0,0 +1,20 @@
+(module
+ (type $0 (func (param anyref) (result anyref)))
+ (import "env" "test2" (global $gimport$1 anyref))
+ (import "env" "test1" (func $fimport$0 (param anyref) (result anyref)))
+ (memory $0 1 1)
+ (export "test1" (func $fimport$0))
+ (export "test2" (global $gimport$1))
+ (func $0 (; 1 ;) (type $0) (param $0 anyref) (result anyref)
+ (local $1 anyref)
+ (local.set $1
+ (call $fimport$0
+ (local.get $0)
+ )
+ )
+ (return
+ (local.get $1)
+ )
+ )
+)
+
diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt
index 902ac55e6..cdf45aeaa 100644
--- a/test/binaryen.js/exception-handling.js.txt
+++ b/test/binaryen.js/exception-handling.js.txt
@@ -26,7 +26,7 @@
)
)
-getExpressionInfo(throw) = {"id":39,"type":7,"event":"e"}
-getExpressionInfo(br_on_exn) = {"id":41,"type":6,"name":"l","event":"e"}
-getExpressionInfo(rethrow) = {"id":40,"type":7}
+getExpressionInfo(throw) = {"id":39,"type":8,"event":"e"}
+getExpressionInfo(br_on_exn) = {"id":41,"type":7,"name":"l","event":"e"}
+getExpressionInfo(rethrow) = {"id":40,"type":8}
getExpressionInfo(try) = {"id":38,"type":0}
diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js
index 163fe8839..f2a78ab34 100644
--- a/test/binaryen.js/kitchen-sink.js
+++ b/test/binaryen.js/kitchen-sink.js
@@ -57,6 +57,7 @@ function test_types() {
console.log("BinaryenTypeFloat32: " + Binaryen.f32);
console.log("BinaryenTypeFloat64: " + Binaryen.f64);
console.log("BinaryenTypeVec128: " + Binaryen.v128);
+ console.log("BinaryenTypeAnyref: " + Binaryen.anyref);
console.log("BinaryenTypeExnref: " + Binaryen.exnref);
console.log("BinaryenTypeUnreachable: " + Binaryen.unreachable);
console.log("BinaryenTypeAuto: " + Binaryen.auto);
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index a1baa5951..07a06b98b 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -4,8 +4,9 @@ BinaryenTypeInt64: 2
BinaryenTypeFloat32: 3
BinaryenTypeFloat64: 4
BinaryenTypeVec128: 5
-BinaryenTypeExnref: 6
-BinaryenTypeUnreachable: 7
+BinaryenTypeAnyref: 6
+BinaryenTypeExnref: 7
+BinaryenTypeUnreachable: 8
BinaryenTypeAuto: -1
Binaryen.Features.MVP: 0
Binaryen.Features.Atomics: 1
@@ -15,7 +16,7 @@ Binaryen.Features.NontrappingFPToInt: 4
Binaryen.Features.SignExt: 32
Binaryen.Features.SIMD128: 8
Binaryen.Features.ExceptionHandling: 64
-Binaryen.Features.All: 255
+Binaryen.Features.All: 511
BinaryenInvalidId: 0
BinaryenBlockId: 1
BinaryenIfId: 2
@@ -4759,9 +4760,9 @@ int main() {
BinaryenExpressionRef operands[] = { expressions[656] };
expressions[657] = BinaryenThrow(the_module, "a-event", operands, 1);
}
- expressions[658] = BinaryenPop(the_module, 6);
+ expressions[658] = BinaryenPop(the_module, 7);
expressions[659] = BinaryenLocalSet(the_module, 5, expressions[658]);
- expressions[660] = BinaryenLocalGet(the_module, 5, 6);
+ expressions[660] = BinaryenLocalGet(the_module, 5, 7);
expressions[661] = BinaryenBrOnExn(the_module, "try-block", "a-event", expressions[660]);
expressions[662] = BinaryenRethrow(the_module, expressions[661]);
{
@@ -4784,7 +4785,7 @@ int main() {
expressions[674] = BinaryenPush(the_module, expressions[673]);
expressions[675] = BinaryenPop(the_module, 5);
expressions[676] = BinaryenPush(the_module, expressions[675]);
- expressions[677] = BinaryenPop(the_module, 6);
+ expressions[677] = BinaryenPop(the_module, 7);
expressions[678] = BinaryenPush(the_module, expressions[677]);
expressions[679] = BinaryenNop(the_module);
expressions[680] = BinaryenUnreachable(the_module);
@@ -4876,7 +4877,7 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
expressions[689] = BinaryenBlock(the_module, "the-body", children, 2, 0);
}
{
- BinaryenType varTypes[] = { 1, 6 };
+ BinaryenType varTypes[] = { 1, 7 };
functions[0] = BinaryenAddFunction(the_module, "kitchen()sinker", functionTypes[1], varTypes, 2, expressions[689]);
}
expressions[690] = BinaryenConst(the_module, BinaryenLiteralInt32(1));
@@ -4934,7 +4935,7 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
functionTypes[4] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
}
BinaryenModuleAutoDrop(the_module);
- BinaryenModuleSetFeatures(the_module, 255);
+ BinaryenModuleSetFeatures(the_module, 511);
BinaryenModuleGetFeatures(the_module);
BinaryenModulePrint(the_module);
(module
diff --git a/test/binaryen.js/push-pop.js.txt b/test/binaryen.js/push-pop.js.txt
index 0597780d9..c9689831f 100644
--- a/test/binaryen.js/push-pop.js.txt
+++ b/test/binaryen.js/push-pop.js.txt
@@ -27,5 +27,5 @@ getExpressionInfo(i64.pop) = {"id":37,"type":2}
getExpressionInfo(f32.pop) = {"id":37,"type":3}
getExpressionInfo(f64.pop) = {"id":37,"type":4}
getExpressionInfo(v128.pop) = {"id":37,"type":5}
-getExpressionInfo(exnref.pop) = {"id":37,"type":6}
+getExpressionInfo(exnref.pop) = {"id":37,"type":7}
getExpressionInfo(push) = {"id":36}
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index 661d04ce2..3d9d42fa1 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -155,6 +155,7 @@ void test_types() {
printf("BinaryenTypeFloat32: %d\n", BinaryenTypeFloat32());
printf("BinaryenTypeFloat64: %d\n", BinaryenTypeFloat64());
printf("BinaryenTypeVec128: %d\n", BinaryenTypeVec128());
+ printf("BinaryenTypeAnyref: %d\n", BinaryenTypeAnyref());
printf("BinaryenTypeExnref: %d\n", BinaryenTypeExnref());
printf("BinaryenTypeUnreachable: %d\n", BinaryenTypeUnreachable());
printf("BinaryenTypeAuto: %d\n", BinaryenTypeAuto());
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index e135bd98d..d0582bd79 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -4,8 +4,9 @@ BinaryenTypeInt64: 2
BinaryenTypeFloat32: 3
BinaryenTypeFloat64: 4
BinaryenTypeVec128: 5
-BinaryenTypeExnref: 6
-BinaryenTypeUnreachable: 7
+BinaryenTypeAnyref: 6
+BinaryenTypeExnref: 7
+BinaryenTypeUnreachable: 8
BinaryenTypeAuto: -1
BinaryenFeatureMVP: 0
BinaryenFeatureAtomics: 1
@@ -15,7 +16,7 @@ BinaryenFeatureNontrappingFPToInt: 4
BinaryenFeatureSignExt: 32
BinaryenFeatureSIMD128: 8
BinaryenFeatureExceptionHandling: 64
-BinaryenFeatureAll: 255
+BinaryenFeatureAll: 511
(f32.neg
(f32.const -33.61199951171875)
)
@@ -2022,9 +2023,9 @@ int main() {
BinaryenExpressionRef operands[] = { expressions[34] };
expressions[35] = BinaryenThrow(the_module, "a-event", operands, 1);
}
- expressions[36] = BinaryenPop(the_module, 6);
+ expressions[36] = BinaryenPop(the_module, 7);
expressions[37] = BinaryenLocalSet(the_module, 5, expressions[36]);
- expressions[38] = BinaryenLocalGet(the_module, 5, 6);
+ expressions[38] = BinaryenLocalGet(the_module, 5, 7);
expressions[39] = BinaryenBrOnExn(the_module, "try-block", "a-event", expressions[38]);
expressions[40] = BinaryenRethrow(the_module, expressions[39]);
{
@@ -3371,7 +3372,7 @@ int main() {
expressions[666] = BinaryenBlock(the_module, "the-body", children, 2, BinaryenTypeAuto());
}
{
- BinaryenType varTypes[] = { 1, 6 };
+ BinaryenType varTypes[] = { 1, 7 };
functions[0] = BinaryenAddFunction(the_module, "kitchen()sinker", functionTypes[0], varTypes, 2, expressions[666]);
}
expressions[667] = BinaryenConst(the_module, BinaryenLiteralInt32(7));
@@ -3414,7 +3415,7 @@ int main() {
functionTypes[4] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
}
BinaryenModuleAutoDrop(the_module);
- BinaryenModuleSetFeatures(the_module, 255);
+ BinaryenModuleSetFeatures(the_module, 511);
BinaryenModuleGetFeatures(the_module);
BinaryenModuleValidate(the_module);
BinaryenModulePrint(the_module);
diff --git a/test/unit/input/reference_types_target_feature.wasm b/test/unit/input/reference_types_target_feature.wasm
new file mode 100644
index 000000000..7ea8847e9
--- /dev/null
+++ b/test/unit/input/reference_types_target_feature.wasm
Binary files differ
diff --git a/test/unit/test_features.py b/test/unit/test_features.py
index 53037307d..c031c07fa 100644
--- a/test/unit/test_features.py
+++ b/test/unit/test_features.py
@@ -29,6 +29,9 @@ class FeatureValidationTest(BinaryenTestCase):
def check_tail_call(self, module, error):
self.check_feature(module, error, '--enable-tail-call')
+ def check_reference_types(self, module, error):
+ self.check_feature(module, error, '--enable-reference-types')
+
def test_v128_signature(self):
module = '''
(module
@@ -144,6 +147,24 @@ class FeatureValidationTest(BinaryenTestCase):
'''
self.check_tail_call(module, 'return_call_indirect requires tail calls to be enabled')
+ def test_reference_types_anyref(self):
+ module = '''
+ (module
+ (import "env" "test1" (func $test1 (param anyref) (result anyref)))
+ (import "env" "test2" (global $test2 anyref))
+ (export "test1" (func $test1 (param anyref) (result anyref)))
+ (export "test2" (global $test2))
+ (func $anyref_test (param $0 anyref) (result anyref)
+ (return
+ (call $test1
+ (local.get $0)
+ )
+ )
+ )
+ )
+ '''
+ self.check_reference_types(module, 'all used types should be allowed')
+
def test_exnref_local(self):
module = '''
(module
@@ -210,6 +231,12 @@ class TargetFeaturesSectionTest(BinaryenTestCase):
self.check_features(filename, ['tail-call'])
self.assertIn('return_call', self.disassemble(filename))
+ def test_reference_types(self):
+ filename = 'reference_types_target_feature.wasm'
+ self.roundtrip(filename)
+ self.check_features(filename, ['reference-types'])
+ self.assertIn('anyref', self.disassemble(filename))
+
def test_exception_handling(self):
filename = 'exception_handling_target_feature.wasm'
self.roundtrip(filename)
@@ -243,7 +270,7 @@ class TargetFeaturesSectionTest(BinaryenTestCase):
def test_emit_all_features(self):
p = run_process(WASM_OPT + ['--emit-target-features', '-all', '-o', '-'],
- input="(module)", check=False, capture_output=True)
+ input="(module)", check=False, capture_output=True, decode_output=False)
self.assertEqual(p.returncode, 0)
p2 = run_process(WASM_OPT + ['--print-features', '-o', os.devnull],
input=p.stdout, check=False, capture_output=True)
@@ -256,5 +283,6 @@ class TargetFeaturesSectionTest(BinaryenTestCase):
'--enable-nontrapping-float-to-int',
'--enable-sign-ext',
'--enable-simd',
- '--enable-tail-call'
+ '--enable-tail-call',
+ '--enable-reference-types'
], p2.stdout.split())