summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asmjs/asm_v_wasm.cpp16
-rw-r--r--src/binaryen-c.cpp90
-rw-r--r--src/ir/abstract.h10
-rw-r--r--src/ir/module-splitting.cpp12
-rw-r--r--src/ir/table-utils.cpp3
-rw-r--r--src/literal.h43
-rw-r--r--src/passes/ConstHoisting.cpp8
-rw-r--r--src/passes/FuncCastEmulation.cpp14
-rw-r--r--src/passes/InstrumentLocals.cpp167
-rw-r--r--src/passes/OptimizeInstructions.cpp8
-rw-r--r--src/passes/Precompute.cpp3
-rw-r--r--src/passes/Print.cpp98
-rw-r--r--src/tools/fuzzing/fuzzing.cpp76
-rw-r--r--src/tools/fuzzing/heap-types.cpp8
-rw-r--r--src/tools/spec-wrapper.h12
-rw-r--r--src/tools/wasm-reduce.cpp40
-rw-r--r--src/tools/wasm-shell.cpp4
-rw-r--r--src/wasm-builder.h33
-rw-r--r--src/wasm-interpreter.h10
-rw-r--r--src/wasm-type.h8
-rw-r--r--src/wasm.h8
-rw-r--r--src/wasm/literal.cpp98
-rw-r--r--src/wasm/wasm-binary.cpp55
-rw-r--r--src/wasm/wasm-s-parser.cpp15
-rw-r--r--src/wasm/wasm-stack.cpp15
-rw-r--r--src/wasm/wasm-type.cpp118
-rw-r--r--src/wasm/wasm-validator.cpp28
-rw-r--r--src/wasm/wasm.cpp12
-rw-r--r--src/wasm/wat-parser.cpp5
-rw-r--r--test/binaryen.js/kitchen-sink.js18
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt12
-rw-r--r--test/example/c-api-kitchen-sink.c18
-rw-r--r--test/example/c-api-kitchen-sink.txt12
-rw-r--r--test/example/stack-utils.cpp38
-rw-r--r--test/example/type-builder-nominal.cpp42
-rw-r--r--test/example/type-builder.cpp100
-rw-r--r--test/example/typeinfo.cpp10
-rw-r--r--test/example/typeinfo.txt8
-rw-r--r--test/gtest/possible-contents.cpp10
-rw-r--r--test/gtest/type-builder.cpp13
-rw-r--r--test/lit/fuzz-types/isorecursive.test34
-rw-r--r--test/lit/fuzz-types/nominal.test26
-rw-r--r--test/lit/fuzz-types/structural.test26
-rw-r--r--test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast18
-rw-r--r--test/lit/strings.wast10
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt50
46 files changed, 591 insertions, 871 deletions
diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp
index 38eb029f4..314c2494f 100644
--- a/src/asmjs/asm_v_wasm.cpp
+++ b/src/asmjs/asm_v_wasm.cpp
@@ -33,12 +33,6 @@ JsType wasmToJsType(Type type) {
return JS_INT64;
case Type::v128:
WASM_UNREACHABLE("v128 not implemented yet");
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- WASM_UNREACHABLE("reference types are not supported by wasm2js");
case Type::none:
return JS_NONE;
case Type::unreachable:
@@ -60,16 +54,6 @@ char getSig(Type type) {
return 'd';
case Type::v128:
return 'V';
- case Type::funcref:
- return 'F';
- case Type::anyref:
- return 'A';
- case Type::eqref:
- return 'Q';
- case Type::i31ref:
- return 'I';
- case Type::dataref:
- return 'D';
case Type::none:
return 'v';
case Type::unreachable:
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index e2afe66dc..d0e99ac0b 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -51,6 +51,29 @@ static_assert(sizeof(BinaryenLiteral) == sizeof(Literal),
BinaryenLiteral toBinaryenLiteral(Literal x) {
BinaryenLiteral ret;
ret.type = x.type.getID();
+ if (x.type.isRef()) {
+ auto heapType = x.type.getHeapType();
+ if (heapType.isBasic()) {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ ret.func = x.isNull() ? nullptr : x.getFunc().c_str();
+ break;
+ case HeapType::any:
+ case HeapType::eq:
+ assert(x.isNull() && "unexpected non-null reference type literal");
+ break;
+ case HeapType::i31:
+ case HeapType::data:
+ case HeapType::string:
+ case HeapType::stringview_wtf8:
+ case HeapType::stringview_wtf16:
+ case HeapType::stringview_iter:
+ WASM_UNREACHABLE("TODO: reftypes");
+ }
+ return ret;
+ }
+ WASM_UNREACHABLE("TODO: reftypes");
+ }
TODO_SINGLE_COMPOUND(x.type);
switch (x.type.getBasic()) {
case Type::i32:
@@ -68,16 +91,6 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
case Type::v128:
memcpy(&ret.v128, x.getv128Ptr(), 16);
break;
- case Type::funcref:
- ret.func = x.isNull() ? nullptr : x.getFunc().c_str();
- break;
- case Type::anyref:
- case Type::eqref:
- assert(x.isNull() && "unexpected non-null reference type literal");
- break;
- case Type::i31ref:
- case Type::dataref:
- WASM_UNREACHABLE("TODO: reftypes");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -86,7 +99,30 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
}
Literal fromBinaryenLiteral(BinaryenLiteral x) {
- switch (x.type) {
+ auto type = Type(x.type);
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ if (type.isNullable()) {
+ return Literal::makeNull(heapType);
+ }
+ if (heapType.isBasic()) {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ return Literal::makeFunc(x.func);
+ case HeapType::any:
+ case HeapType::eq:
+ case HeapType::i31:
+ case HeapType::data:
+ case HeapType::string:
+ case HeapType::stringview_wtf8:
+ case HeapType::stringview_wtf16:
+ case HeapType::stringview_iter:
+ WASM_UNREACHABLE("TODO: reftypes");
+ }
+ }
+ }
+ assert(type.isBasic());
+ switch (type.getBasic()) {
case Type::i32:
return Literal(x.i32);
case Type::i64:
@@ -97,14 +133,6 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
return Literal(x.i64).castToF64();
case Type::v128:
return Literal(x.v128);
- case Type::funcref:
- return Literal::makeFunc(x.func);
- case Type::anyref:
- case Type::eqref:
- return Literal::makeNull(Type(x.type).getHeapType());
- case Type::i31ref:
- case Type::dataref:
- WASM_UNREACHABLE("TODO: reftypes");
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -137,12 +165,24 @@ BinaryenType BinaryenTypeInt64(void) { return Type::i64; }
BinaryenType BinaryenTypeFloat32(void) { return Type::f32; }
BinaryenType BinaryenTypeFloat64(void) { return Type::f64; }
BinaryenType BinaryenTypeVec128(void) { return Type::v128; }
-BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; }
-BinaryenType BinaryenTypeExternref(void) { return Type::anyref; }
-BinaryenType BinaryenTypeAnyref(void) { return Type::anyref; }
-BinaryenType BinaryenTypeEqref(void) { return Type::eqref; }
-BinaryenType BinaryenTypeI31ref(void) { return Type::i31ref; }
-BinaryenType BinaryenTypeDataref(void) { return Type::dataref; }
+BinaryenType BinaryenTypeFuncref(void) {
+ return Type(HeapType::func, Nullable).getID();
+}
+BinaryenType BinaryenTypeExternref(void) {
+ return Type(HeapType::any, Nullable).getID();
+}
+BinaryenType BinaryenTypeAnyref(void) {
+ return Type(HeapType::any, Nullable).getID();
+}
+BinaryenType BinaryenTypeEqref(void) {
+ return Type(HeapType::eq, Nullable).getID();
+}
+BinaryenType BinaryenTypeI31ref(void) {
+ return Type(HeapType::i31, NonNullable).getID();
+}
+BinaryenType BinaryenTypeDataref(void) {
+ return Type(HeapType::data, NonNullable).getID();
+}
BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; }
BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); }
diff --git a/src/ir/abstract.h b/src/ir/abstract.h
index 63057a975..feac9b50d 100644
--- a/src/ir/abstract.h
+++ b/src/ir/abstract.h
@@ -121,11 +121,6 @@ inline UnaryOp getUnary(Type type, Op op) {
break;
}
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable: {
return InvalidUnary;
@@ -293,11 +288,6 @@ inline BinaryOp getBinary(Type type, Op op) {
break;
}
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable: {
return InvalidBinary;
diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp
index dc04cdba2..e24dd6452 100644
--- a/src/ir/module-splitting.cpp
+++ b/src/ir/module-splitting.cpp
@@ -143,11 +143,11 @@ void TableSlotManager::addSlot(Name func, Slot slot) {
TableSlotManager::TableSlotManager(Module& module) : module(module) {
// TODO: Reject or handle passive element segments
- auto it = std::find_if(module.tables.begin(),
- module.tables.end(),
- [&](std::unique_ptr<Table>& table) {
- return table->type == Type::funcref;
- });
+ auto funcref = Type(HeapType::func, Nullable);
+ auto it = std::find_if(
+ module.tables.begin(),
+ module.tables.end(),
+ [&](std::unique_ptr<Table>& table) { return table->type == funcref; });
if (it == module.tables.end()) {
return;
}
@@ -163,7 +163,7 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) {
// append new items at constant offsets after all existing items at constant
// offsets.
if (activeTableSegments.size() == 1 &&
- activeTableSegments[0]->type == Type::funcref &&
+ activeTableSegments[0]->type == funcref &&
!activeTableSegments[0]->offset->is<Const>()) {
assert(activeTableSegments[0]->offset->is<GlobalGet>() &&
"Unexpected initializer instruction");
diff --git a/src/ir/table-utils.cpp b/src/ir/table-utils.cpp
index 0d47f155b..fb9285319 100644
--- a/src/ir/table-utils.cpp
+++ b/src/ir/table-utils.cpp
@@ -76,7 +76,8 @@ bool usesExpressions(ElementSegment* curr, Module* module) {
// declare a type that is a subtype of that, so it must use the post-MVP form
// of using expressions.
bool hasTableOfSpecializedType =
- curr->table.is() && module->getTable(curr->table)->type != Type::funcref;
+ curr->table.is() &&
+ module->getTable(curr->table)->type != Type(HeapType::func, Nullable);
return !allElementsRefFunc || hasTableOfSpecializedType;
}
diff --git a/src/literal.h b/src/literal.h
index 4caeab9d4..c37f74499 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -251,11 +251,12 @@ public:
static Literal makeNull(HeapType type) {
return Literal(Type(type, Nullable));
}
- static Literal makeFunc(Name func, Type type = Type::funcref) {
+ static Literal makeFunc(Name func,
+ Type type = Type(HeapType::func, Nullable)) {
return Literal(func, type);
}
static Literal makeI31(int32_t value) {
- auto lit = Literal(Type::i31ref);
+ auto lit = Literal(Type(HeapType::i31, NonNullable));
lit.i32 = value & 0x7fffffff;
return lit;
}
@@ -753,20 +754,7 @@ struct RttSupers : std::vector<RttSuper> {};
namespace std {
template<> struct hash<wasm::Literal> {
size_t operator()(const wasm::Literal& a) const {
- auto digest = wasm::hash(a.type.getID());
- auto hashRef = [&]() {
- assert(a.type.isRef());
- if (a.isNull()) {
- return digest;
- }
- if (a.type.isFunction()) {
- wasm::rehash(digest, a.getFunc());
- return digest;
- }
- // other non-null reference type literals cannot represent concrete
- // values, i.e. there is no concrete anyref or eqref other than null.
- WASM_UNREACHABLE("unexpected type");
- };
+ auto digest = wasm::hash(a.type);
if (a.type.isBasic()) {
switch (a.type.getBasic()) {
case wasm::Type::i32:
@@ -787,20 +775,25 @@ template<> struct hash<wasm::Literal> {
wasm::rehash(digest, chunks[0]);
wasm::rehash(digest, chunks[1]);
return digest;
- case wasm::Type::funcref:
- case wasm::Type::anyref:
- case wasm::Type::eqref:
- case wasm::Type::dataref:
- return hashRef();
- case wasm::Type::i31ref:
- wasm::rehash(digest, a.geti31(true));
- return digest;
case wasm::Type::none:
case wasm::Type::unreachable:
break;
}
} else if (a.type.isRef()) {
- return hashRef();
+ if (a.isNull()) {
+ return digest;
+ }
+ if (a.type.isFunction()) {
+ wasm::rehash(digest, a.getFunc());
+ return digest;
+ }
+ if (a.type.getHeapType() == wasm::HeapType::i31) {
+ wasm::rehash(digest, a.geti31(true));
+ return digest;
+ }
+ // other non-null reference type literals cannot represent concrete
+ // values, i.e. there is no concrete anyref or eqref other than null.
+ WASM_UNREACHABLE("unexpected type");
} else if (a.type.isRtt()) {
const auto& supers = a.getRttSupers();
wasm::rehash(digest, supers.size());
diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp
index 3320c129b..3d9ac5e90 100644
--- a/src/passes/ConstHoisting.cpp
+++ b/src/passes/ConstHoisting.cpp
@@ -89,15 +89,9 @@ private:
size = value.type.getByteSize();
break;
}
- // not implemented yet
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref: {
return false;
- }
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp
index 704f44e03..5e62ec9fc 100644
--- a/src/passes/FuncCastEmulation.cpp
+++ b/src/passes/FuncCastEmulation.cpp
@@ -62,13 +62,6 @@ static Expression* toABI(Expression* value, Module* module) {
case Type::v128: {
WASM_UNREACHABLE("v128 not implemented yet");
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref: {
- WASM_UNREACHABLE("reference types cannot be converted to i64");
- }
case Type::none: {
// the value is none, but we need a value here
value =
@@ -107,13 +100,6 @@ static Expression* fromABI(Expression* value, Type type, Module* module) {
case Type::v128: {
WASM_UNREACHABLE("v128 not implemented yet");
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref: {
- WASM_UNREACHABLE("reference types cannot be converted from i64");
- }
case Type::none: {
value = builder.makeDrop(value);
break;
diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp
index 3bf23b61c..761aac2a9 100644
--- a/src/passes/InstrumentLocals.cpp
+++ b/src/passes/InstrumentLocals.cpp
@@ -58,9 +58,6 @@ Name get_f64("get_f64");
Name get_v128("get_v128");
Name get_funcref("get_funcref");
Name get_anyref("get_anyref");
-Name get_eqref("get_eqref");
-Name get_i31ref("get_i31ref");
-Name get_dataref("get_dataref");
Name set_i32("set_i32");
Name set_i64("set_i64");
@@ -69,48 +66,41 @@ Name set_f64("set_f64");
Name set_v128("set_v128");
Name set_funcref("set_funcref");
Name set_anyref("set_anyref");
-Name set_eqref("set_eqref");
-Name set_i31ref("set_i31ref");
-Name set_dataref("set_dataref");
struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
void visitLocalGet(LocalGet* curr) {
Builder builder(*getModule());
Name import;
- TODO_SINGLE_COMPOUND(curr->type);
- switch (curr->type.getBasic()) {
- case Type::i32:
- import = get_i32;
- break;
- case Type::i64:
- return; // TODO
- case Type::f32:
- import = get_f32;
- break;
- case Type::f64:
- import = get_f64;
- break;
- case Type::v128:
- import = get_v128;
- break;
- case Type::funcref:
+ if (curr->type.isRef()) {
+ auto heapType = curr->type.getHeapType();
+ if (heapType == HeapType::func && curr->type.isNullable()) {
import = get_funcref;
- break;
- case Type::anyref:
+ } else if (heapType == HeapType::any && curr->type.isNullable()) {
import = get_anyref;
- break;
- case Type::eqref:
- import = get_eqref;
- break;
- case Type::i31ref:
- import = get_i31ref;
- break;
- case Type::dataref:
- import = get_dataref;
- break;
- case Type::none:
- case Type::unreachable:
- WASM_UNREACHABLE("unexpected type");
+ } else {
+ WASM_UNREACHABLE("TODO: general reference types");
+ }
+ } else {
+ TODO_SINGLE_COMPOUND(curr->type);
+ switch (curr->type.getBasic()) {
+ case Type::i32:
+ import = get_i32;
+ break;
+ case Type::i64:
+ return; // TODO
+ case Type::f32:
+ import = get_f32;
+ break;
+ case Type::f64:
+ import = get_f64;
+ break;
+ case Type::v128:
+ import = get_v128;
+ break;
+ case Type::none:
+ case Type::unreachable:
+ WASM_UNREACHABLE("unexpected type");
+ }
}
replaceCurrent(builder.makeCall(import,
{builder.makeConst(int32_t(id++)),
@@ -130,45 +120,41 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
Builder builder(*getModule());
Name import;
auto type = curr->value->type;
- if (type.isFunction() && type != Type::funcref) {
+ if (type.isFunction() && type.getHeapType() != HeapType::func) {
// FIXME: support typed function references
return;
}
- TODO_SINGLE_COMPOUND(curr->value->type);
- switch (type.getBasic()) {
- case Type::i32:
- import = set_i32;
- break;
- case Type::i64:
- return; // TODO
- case Type::f32:
- import = set_f32;
- break;
- case Type::f64:
- import = set_f64;
- break;
- case Type::v128:
- import = set_v128;
- break;
- case Type::funcref:
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ if (heapType == HeapType::func && type.isNullable()) {
import = set_funcref;
- break;
- case Type::anyref:
+ } else if (heapType == HeapType::any && type.isNullable()) {
import = set_anyref;
- break;
- case Type::eqref:
- import = set_eqref;
- break;
- case Type::i31ref:
- import = set_i31ref;
- break;
- case Type::dataref:
- import = set_dataref;
- break;
- case Type::unreachable:
- return; // nothing to do here
- default:
- WASM_UNREACHABLE("unexpected type");
+ } else {
+ WASM_UNREACHABLE("TODO: general reference types");
+ }
+ } else {
+ TODO_SINGLE_COMPOUND(curr->value->type);
+ switch (type.getBasic()) {
+ case Type::i32:
+ import = set_i32;
+ break;
+ case Type::i64:
+ return; // TODO
+ case Type::f32:
+ import = set_f32;
+ break;
+ case Type::f64:
+ import = set_f64;
+ break;
+ case Type::v128:
+ import = set_v128;
+ break;
+ case Type::unreachable:
+ return; // nothing to do here
+ case Type::none:
+ WASM_UNREACHABLE("unexpected type");
+ }
}
curr->value = builder.makeCall(import,
{builder.makeConst(int32_t(id++)),
@@ -188,36 +174,13 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
addImport(curr, set_f64, {Type::i32, Type::i32, Type::f64}, Type::f64);
if (curr->features.hasReferenceTypes()) {
- addImport(curr,
- get_funcref,
- {Type::i32, Type::i32, Type::funcref},
- Type::funcref);
- addImport(curr,
- set_funcref,
- {Type::i32, Type::i32, Type::funcref},
- Type::funcref);
- addImport(
- curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref);
- addImport(
- curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref);
- if (curr->features.hasGC()) {
- 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);
- addImport(curr,
- get_dataref,
- {Type::i32, Type::i32, Type::dataref},
- Type::dataref);
- addImport(curr,
- set_dataref,
- {Type::i32, Type::i32, Type::dataref},
- Type::dataref);
- }
+ Type func = Type(HeapType::func, Nullable);
+ Type any = Type(HeapType::any, Nullable);
+
+ addImport(curr, get_funcref, {Type::i32, Type::i32, func}, func);
+ addImport(curr, set_funcref, {Type::i32, Type::i32, func}, func);
+ addImport(curr, get_anyref, {Type::i32, Type::i32, any}, any);
+ addImport(curr, set_anyref, {Type::i32, Type::i32, any}, any);
}
if (curr->features.hasSIMD()) {
addImport(curr, get_v128, {Type::i32, Type::i32, Type::v128}, Type::v128);
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 9d50275b9..9ab8e20d9 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1472,7 +1472,8 @@ struct OptimizeInstructions
// there.
//
// See "notes on removing casts", above, for when this is safe to do.
- void skipCast(Expression*& input, Type requiredType = Type::anyref) {
+ void skipCast(Expression*& input,
+ Type requiredType = Type(HeapType::any, Nullable)) {
// Traps-never-happen mode is a requirement for us to optimize here.
if (!getPassOptions().trapsNeverHappen) {
return;
@@ -1523,8 +1524,9 @@ struct OptimizeInstructions
// This is safe to do first because nothing farther down cares about the
// type, and we consume the two input references, so removing a cast could
// not help our parents (see "notes on removing casts").
- skipCast(curr->left, Type::eqref);
- skipCast(curr->right, Type::eqref);
+ Type nullableEq = Type(HeapType::eq, Nullable);
+ skipCast(curr->left, nullableEq);
+ skipCast(curr->right, nullableEq);
// Identical references compare equal.
// (Technically we do not need to check if the inputs are also foldable into
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index f599990a0..156c33c3f 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -249,7 +249,8 @@ struct Precompute
curr->finalize();
return;
}
- } else if (singleValue.type == Type::funcref) {
+ } else if (singleValue.type.isRef() &&
+ singleValue.type.getHeapType() == HeapType::func) {
if (auto* r = curr->value->template dynCast<RefFunc>()) {
r->func = singleValue.getFunc();
r->finalize();
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index ca2985240..440ff114f 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -72,6 +72,62 @@ static std::ostream& printLocal(Index index, Function* func, std::ostream& o) {
namespace {
+static bool maybePrintRefShorthand(std::ostream& o, Type type) {
+ if (!type.isRef()) {
+ return false;
+ }
+ auto heapType = type.getHeapType();
+ if (heapType.isBasic()) {
+ if (type.isNullable()) {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ o << "funcref";
+ return true;
+ case HeapType::any:
+ o << "anyref";
+ return true;
+ case HeapType::eq:
+ o << "eqref";
+ return true;
+ case HeapType::i31:
+ case HeapType::data:
+ break;
+ case HeapType::string:
+ o << "stringref";
+ return true;
+ case HeapType::stringview_wtf8:
+ o << "stringview_wtf8";
+ return true;
+ case HeapType::stringview_wtf16:
+ o << "stringview_wtf16";
+ return true;
+ case HeapType::stringview_iter:
+ o << "stringview_iter";
+ return true;
+ }
+ } else {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ case HeapType::any:
+ case HeapType::eq:
+ break;
+ case HeapType::i31:
+ o << "i31ref";
+ return true;
+ case HeapType::data:
+ o << "dataref";
+ return true;
+ case HeapType::string:
+ case HeapType::stringview_wtf8:
+ case HeapType::stringview_wtf16:
+ case HeapType::stringview_iter:
+ break;
+ }
+ }
+ }
+ return false;
+}
+
// Helper for printing the name of a type. This output is guaranteed to not
// contain spaces.
struct TypeNamePrinter {
@@ -126,13 +182,15 @@ void TypeNamePrinter::print(Type type) {
} else if (type.isRtt()) {
print(type.getRtt());
} else if (type.isRef()) {
- os << "ref";
- if (type.isNullable()) {
- os << "?";
+ if (!maybePrintRefShorthand(os, type)) {
+ os << "ref";
+ if (type.isNullable()) {
+ os << "?";
+ }
+ os << '|';
+ print(type.getHeapType());
+ os << '|';
}
- os << '|';
- print(type.getHeapType());
- os << '|';
} else {
WASM_UNREACHABLE("unexpected type");
}
@@ -273,29 +331,15 @@ static std::ostream& printType(std::ostream& o, Type type, Module* wasm) {
}
TypeNamePrinter(o, wasm).print(rtt.heapType);
o << ')';
- } else if (type.isRef() && !type.isBasic()) {
- auto heapType = type.getHeapType();
- if (type.isNullable() && heapType.isBasic()) {
- // Print shorthands for certain nullable basic heap types.
- switch (heapType.getBasic()) {
- case HeapType::string:
- return o << "stringref";
- case HeapType::stringview_wtf8:
- return o << "stringview_wtf8";
- case HeapType::stringview_wtf16:
- return o << "stringview_wtf16";
- case HeapType::stringview_iter:
- return o << "stringview_iter";
- default:
- break;
+ } else if (type.isRef()) {
+ if (!maybePrintRefShorthand(o, type)) {
+ o << "(ref ";
+ if (type.isNullable()) {
+ o << "null ";
}
+ TypeNamePrinter(o, wasm).print(type.getHeapType());
+ o << ')';
}
- o << "(ref ";
- if (type.isNullable()) {
- o << "null ";
- }
- TypeNamePrinter(o, wasm).print(type.getHeapType());
- o << ')';
} else {
WASM_UNREACHABLE("unexpected type");
}
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 5489e7638..59c9dca45 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -260,15 +260,15 @@ void TranslateToFuzzReader::setupTables() {
// Ensure a funcref element segment and table exist. Segments with more
// specific function types may have a smaller chance of getting functions.
Table* table = nullptr;
- auto iter =
- std::find_if(wasm.tables.begin(), wasm.tables.end(), [&](auto& table) {
- return table->type == Type::funcref;
- });
+ Type funcref = Type(HeapType::func, Nullable);
+ auto iter = std::find_if(wasm.tables.begin(),
+ wasm.tables.end(),
+ [&](auto& table) { return table->type == funcref; });
if (iter != wasm.tables.end()) {
table = iter->get();
} else {
auto tablePtr = builder.makeTable(
- Names::getValidTableName(wasm, "fuzzing_table"), Type::funcref, 0, 0);
+ Names::getValidTableName(wasm, "fuzzing_table"), funcref, 0, 0);
tablePtr->hasExplicitName = true;
table = wasm.addTable(std::move(tablePtr));
}
@@ -277,7 +277,7 @@ void TranslateToFuzzReader::setupTables() {
std::any_of(wasm.elementSegments.begin(),
wasm.elementSegments.end(),
[&](auto& segment) {
- return segment->table.is() && segment->type == Type::funcref;
+ return segment->table.is() && segment->type == funcref;
});
if (!hasFuncrefElemSegment) {
// TODO: use a random table
@@ -934,7 +934,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
if (type.isTuple()) {
options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
}
- if (type == Type::i31ref) {
+ if (type.isRef() && type.getHeapType() == HeapType::i31) {
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeI31New);
}
// TODO: struct.get and other GC things
@@ -1463,11 +1463,6 @@ Expression* TranslateToFuzzReader::makeNonAtomicLoad(Type type) {
return builder.makeLoad(
16, false, offset, pick(1, 2, 4, 8, 16), ptr, type);
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -1566,11 +1561,6 @@ Expression* TranslateToFuzzReader::makeNonAtomicStore(Type type) {
return builder.makeStore(
16, offset, pick(1, 2, 4, 8, 16), ptr, value, type);
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -1701,11 +1691,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) {
case Type::f64:
return Literal(getDouble());
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
@@ -1747,11 +1732,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) {
case Type::f64:
return Literal(double(small));
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1816,11 +1796,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) {
std::numeric_limits<uint64_t>::max()));
break;
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1844,11 +1819,6 @@ Literal TranslateToFuzzReader::makeLiteral(Type type) {
value = Literal(double(int64_t(1) << upTo(64)));
break;
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2115,11 +2085,6 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) {
AllTrueVecI32x4),
make(Type::v128)});
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2255,11 +2220,6 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) {
}
WASM_UNREACHABLE("invalid value");
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2493,11 +2453,6 @@ Expression* TranslateToFuzzReader::makeBinary(Type type) {
make(Type::v128),
make(Type::v128)});
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2700,11 +2655,6 @@ Expression* TranslateToFuzzReader::makeSIMDExtract(Type type) {
op = ExtractLaneVecF64x2;
break;
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2892,7 +2842,7 @@ Expression* TranslateToFuzzReader::makeRefEq(Type type) {
}
Expression* TranslateToFuzzReader::makeI31New(Type type) {
- assert(type == Type::i31ref);
+ assert(type.isRef() && type.getHeapType() == HeapType::i31);
assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
auto* value = make(Type::i32);
return builder.makeI31New(value);
@@ -2901,7 +2851,9 @@ Expression* TranslateToFuzzReader::makeI31New(Type type) {
Expression* TranslateToFuzzReader::makeI31Get(Type type) {
assert(type == Type::i32);
assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
- auto* i31 = make(Type::i31ref);
+ // TODO: Maybe this should be nullable?
+ // https://github.com/WebAssembly/gc/issues/312
+ auto* i31 = make(Type(HeapType::i31, NonNullable));
return builder.makeI31Get(i31, bool(oneIn(2)));
}
@@ -2958,7 +2910,9 @@ Type TranslateToFuzzReader::getSingleConcreteType() {
WeightedOption{Type::f32, VeryImportant},
WeightedOption{Type::f64, VeryImportant})
.add(FeatureSet::SIMD, WeightedOption{Type::v128, Important})
- .add(FeatureSet::ReferenceTypes, Type::funcref, Type::anyref)
+ .add(FeatureSet::ReferenceTypes,
+ Type(HeapType::func, Nullable),
+ Type(HeapType::any, Nullable))
.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
// Type(HeapType::func, NonNullable),
// Type(HeapType::any, NonNullable),
@@ -2974,7 +2928,7 @@ Type TranslateToFuzzReader::getReferenceType() {
return pick(FeatureOptions<Type>()
// Avoid Type::anyref without GC enabled, see
// TranslateToFuzzReader::getSingleConcreteType.
- .add(FeatureSet::ReferenceTypes, Type::funcref)
+ .add(FeatureSet::ReferenceTypes, Type(HeapType::func, Nullable))
.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
Type(HeapType::func, NonNullable),
Type(HeapType::any, NonNullable),
diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp
index 77891ce53..edb96977d 100644
--- a/src/tools/fuzzing/heap-types.cpp
+++ b/src/tools/fuzzing/heap-types.cpp
@@ -163,13 +163,7 @@ struct HeapTypeGeneratorImpl {
return rand.pick(
Random::FeatureOptions<Type::BasicType>{}
.add(FeatureSet::MVP, Type::i32, Type::i64, Type::f32, Type::f64)
- .add(FeatureSet::SIMD, Type::v128)
- .add(FeatureSet::ReferenceTypes | FeatureSet::GC,
- Type::funcref,
- Type::anyref,
- Type::eqref,
- Type::i31ref,
- Type::dataref));
+ .add(FeatureSet::SIMD, Type::v128));
}
HeapType generateHeapType() {
diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h
index c2a49c598..366e8d4fc 100644
--- a/src/tools/spec-wrapper.h
+++ b/src/tools/spec-wrapper.h
@@ -52,18 +52,6 @@ inline std::string generateSpecWrapper(Module& wasm) {
case Type::v128:
ret += "(v128.const i32x4 0 0 0 0)";
break;
- case Type::funcref:
- ret += "(ref.null func)";
- break;
- case Type::anyref:
- ret += "(ref.null any)";
- break;
- case Type::eqref:
- ret += "(ref.null eq)";
- break;
- case Type::i31ref:
- case Type::dataref:
- WASM_UNREACHABLE("TODO: reftypes");
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 a4d326426..28cc77e95 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -626,13 +626,9 @@ struct Reducer
case Type::f64:
fixed = builder->makeUnary(TruncSFloat64ToInt32, child);
break;
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- continue; // not implemented yet
+ continue;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -653,13 +649,9 @@ struct Reducer
case Type::f64:
fixed = builder->makeUnary(TruncSFloat64ToInt64, child);
break;
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- continue; // not implemented yet
+ continue;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -680,13 +672,9 @@ struct Reducer
case Type::f64:
fixed = builder->makeUnary(DemoteFloat64, child);
break;
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- continue; // not implemented yet
+ continue;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -707,26 +695,18 @@ struct Reducer
break;
case Type::f64:
WASM_UNREACHABLE("unexpected type");
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- continue; // not implemented yet
+ continue;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
}
break;
}
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- continue; // not implemented yet
+ continue;
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index 617d56313..51eafb652 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -347,8 +347,8 @@ protected:
spectest->addExport(
builder.makeExport("global_f64", Name::fromInt(3), ExternalKind::Global));
- spectest->addTable(
- builder.makeTable(Name::fromInt(0), Type::funcref, 10, 20));
+ spectest->addTable(builder.makeTable(
+ Name::fromInt(0), Type(HeapType::func, Nullable), 10, 20));
spectest->addExport(
builder.makeExport("table", Name::fromInt(0), ExternalKind::Table));
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index eec86bc50..d76d24b21 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -82,7 +82,8 @@ public:
}
static std::unique_ptr<Table> makeTable(Name name,
- Type type = Type::funcref,
+ Type type = Type(HeapType::func,
+ Nullable),
Address initial = 0,
Address max = Table::kMaxSize) {
auto table = std::make_unique<Table>();
@@ -97,7 +98,7 @@ public:
makeElementSegment(Name name,
Name table,
Expression* offset = nullptr,
- Type type = Type::funcref) {
+ Type type = Type(HeapType::func, Nullable)) {
auto seg = std::make_unique<ElementSegment>();
seg->name = name;
seg->table = table;
@@ -1114,20 +1115,14 @@ public:
if (type.isFunction()) {
return makeRefFunc(value.getFunc(), type.getHeapType());
}
+ if (type.isRef() && type.getHeapType() == HeapType::i31) {
+ return makeI31New(makeConst(value.geti31()));
+ }
if (type.isRtt()) {
return makeRtt(value.type);
}
TODO_SINGLE_COMPOUND(type);
- switch (type.getBasic()) {
- case Type::anyref:
- case Type::eqref:
- assert(value.isNull() && "unexpected non-null reference type literal");
- return makeRefNull(type);
- case Type::i31ref:
- return makeI31New(makeConst(value.geti31()));
- default:
- WASM_UNREACHABLE("invalid constant expression");
- }
+ WASM_UNREACHABLE("unsupported constant expression");
}
Expression* makeConstantExpression(Literals values) {
@@ -1273,7 +1268,10 @@ public:
if (curr->type.isNullable()) {
return ExpressionManipulator::refNull(curr, curr->type);
}
- if (curr->type.isFunction() || !curr->type.isBasic()) {
+ if (curr->type.isRef() && curr->type.getHeapType() == HeapType::i31) {
+ return makeI31New(makeConst(0));
+ }
+ if (!curr->type.isBasic()) {
// We can't do any better, keep the original.
return curr;
}
@@ -1298,15 +1296,6 @@ public:
value = Literal(bytes.data());
break;
}
- case Type::funcref:
- WASM_UNREACHABLE("handled above");
- case Type::anyref:
- case Type::eqref:
- return ExpressionManipulator::refNull(curr, curr->type);
- case Type::i31ref:
- return makeI31New(makeConst(0));
- case Type::dataref:
- return curr;
case Type::none:
return ExpressionManipulator::nop(curr);
case Type::unreachable:
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 478b33bc4..eb5dcd5a7 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -2396,11 +2396,6 @@ public:
return Literal(load64u(addr)).castToF64();
case Type::v128:
return Literal(load128(addr).data());
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -2454,11 +2449,6 @@ public:
case Type::v128:
store128(addr, value.getv128());
break;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 23e559aad..4d87ac68d 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -106,14 +106,8 @@ public:
f32,
f64,
v128,
- funcref,
- anyref,
- eqref,
- // From here types are non-nullable.
- i31ref,
- dataref,
};
- static constexpr BasicType _last_basic_type = dataref;
+ static constexpr BasicType _last_basic_type = v128;
Type() : id(none) {}
diff --git a/src/wasm.h b/src/wasm.h
index b5d51b84b..99a2d9f94 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -2036,11 +2036,13 @@ class ElementSegment : public Named {
public:
Name table;
Expression* offset;
- Type type = Type::funcref;
+ Type type = Type(HeapType::func, Nullable);
std::vector<Expression*> data;
ElementSegment() = default;
- ElementSegment(Name table, Expression* offset, Type type = Type::funcref)
+ ElementSegment(Name table,
+ Expression* offset,
+ Type type = Type(HeapType::func, Nullable))
: table(table), offset(offset), type(type) {}
ElementSegment(Name table,
Expression* offset,
@@ -2060,7 +2062,7 @@ public:
Address initial = 0;
Address max = kMaxSize;
- Type type = Type::funcref;
+ Type type = Type(HeapType::func, Nullable);
bool hasMax() { return max != kUnlimitedSize; }
void clear() {
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 6c7689990..85e93f912 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -46,11 +46,6 @@ Literal::Literal(Type type) : type(type) {
case Type::none:
return;
case Type::unreachable:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
break;
}
}
@@ -100,11 +95,6 @@ Literal::Literal(const Literal& other) : type(other.type) {
case Type::none:
return;
case Type::unreachable:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
break;
}
}
@@ -239,7 +229,7 @@ Literals Literal::makeNegOnes(Type type) {
Literal Literal::makeZero(Type type) {
assert(type.isSingle());
if (type.isRef()) {
- if (type == Type::i31ref) {
+ if (type.getHeapType() == HeapType::i31) {
return makeI31(0);
} else {
return makeNull(type.getHeapType());
@@ -355,11 +345,6 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
break;
case Type::none:
case Type::unreachable:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
WASM_UNREACHABLE("invalid type");
}
}
@@ -373,43 +358,37 @@ bool Literal::operator==(const Literal& other) const {
if (type != other.type) {
return false;
}
- auto compareRef = [&]() {
- assert(type.isRef());
- // Note that we've already handled nulls earlier.
- if (type.isFunction()) {
- assert(func.is() && other.func.is());
- return func == other.func;
- }
- if (type.isData()) {
- return gcData == other.gcData;
- }
- // other non-null reference type literals cannot represent concrete values,
- // i.e. there is no concrete anyref or eqref other than null.
- WASM_UNREACHABLE("unexpected type");
- };
if (type.isBasic()) {
switch (type.getBasic()) {
case Type::none:
return true; // special voided literal
case Type::i32:
case Type::f32:
- case Type::i31ref:
return i32 == other.i32;
case Type::i64:
case Type::f64:
return i64 == other.i64;
case Type::v128:
return memcmp(v128, other.v128, 16) == 0;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::dataref:
- return compareRef();
case Type::unreachable:
break;
}
} else if (type.isRef()) {
- return compareRef();
+ assert(type.isRef());
+ // Note that we've already handled nulls earlier.
+ if (type.isFunction()) {
+ assert(func.is() && other.func.is());
+ return func == other.func;
+ }
+ if (type.isData()) {
+ return gcData == other.gcData;
+ }
+ if (type.getHeapType() == HeapType::i31) {
+ return i32 == other.i32;
+ }
+ // other non-null reference type literals cannot represent concrete values,
+ // i.e. there is no concrete anyref or eqref other than null.
+ WASM_UNREACHABLE("unexpected type");
} else if (type.isRtt()) {
return *rttSupers == *other.rttSupers;
}
@@ -578,11 +557,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
o << "i32x4 ";
literal.printVec128(o, literal.getv128());
break;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
}
@@ -801,11 +775,6 @@ Literal Literal::eqz() const {
case Type::f64:
return eq(Literal(double(0)));
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -824,11 +793,6 @@ Literal Literal::neg() const {
case Type::f64:
return Literal(int64_t(i64 ^ 0x8000000000000000ULL)).castToF64();
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -847,11 +811,6 @@ Literal Literal::abs() const {
case Type::f64:
return Literal(int64_t(i64 & 0x7fffffffffffffffULL)).castToF64();
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -987,11 +946,6 @@ Literal Literal::add(const Literal& other) const {
case Type::f64:
return standardizeNaN(getf64() + other.getf64());
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1010,11 +964,6 @@ Literal Literal::sub(const Literal& other) const {
case Type::f64:
return standardizeNaN(getf64() - other.getf64());
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1112,11 +1061,6 @@ Literal Literal::mul(const Literal& other) const {
case Type::f64:
return standardizeNaN(getf64() * other.getf64());
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1347,11 +1291,6 @@ Literal Literal::eq(const Literal& other) const {
case Type::f64:
return Literal(getf64() == other.getf64());
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -1370,11 +1309,6 @@ Literal Literal::ne(const Literal& other) const {
case Type::f64:
return Literal(getf64() != other.getf64());
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
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 e2588422c..5427deea1 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -693,6 +693,7 @@ void WasmBinaryWriter::writeElementSegments() {
auto start = startSection(BinaryConsts::Section::Element);
o << U32LEB(elemCount);
+ Type funcref = Type(HeapType::func, Nullable);
for (auto& segment : wasm->elementSegments) {
Index tableIdx = 0;
@@ -708,7 +709,7 @@ void WasmBinaryWriter::writeElementSegments() {
if (!isPassive) {
tableIdx = getTableIndex(segment->table);
hasTableIndex =
- tableIdx > 0 || wasm->getTable(segment->table)->type != Type::funcref;
+ tableIdx > 0 || wasm->getTable(segment->table)->type != funcref;
}
uint32_t flags = 0;
@@ -1339,7 +1340,36 @@ void WasmBinaryWriter::writeInlineBuffer(const char* data, size_t size) {
}
void WasmBinaryWriter::writeType(Type type) {
- if (type.isRef() && !type.isBasic()) {
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ if (heapType.isBasic()) {
+ if (type.isNullable()) {
+ switch (heapType.getBasic()) {
+ case HeapType::any:
+ o << S32LEB(BinaryConsts::EncodedType::anyref);
+ return;
+ case HeapType::func:
+ o << S32LEB(BinaryConsts::EncodedType::funcref);
+ return;
+ case HeapType::eq:
+ o << S32LEB(BinaryConsts::EncodedType::eqref);
+ return;
+ default:
+ break;
+ }
+ } else {
+ switch (heapType.getBasic()) {
+ case HeapType::i31:
+ o << S32LEB(BinaryConsts::EncodedType::i31ref);
+ return;
+ case HeapType::data:
+ o << S32LEB(BinaryConsts::EncodedType::dataref);
+ return;
+ default:
+ break;
+ }
+ }
+ }
if (type.isNullable()) {
o << S32LEB(BinaryConsts::EncodedType::nullable);
} else {
@@ -1381,21 +1411,6 @@ void WasmBinaryWriter::writeType(Type type) {
case Type::v128:
ret = BinaryConsts::EncodedType::v128;
break;
- case Type::funcref:
- ret = BinaryConsts::EncodedType::funcref;
- break;
- 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::dataref:
- ret = BinaryConsts::EncodedType::dataref;
- break;
default:
WASM_UNREACHABLE("unexpected type");
}
@@ -1774,13 +1789,13 @@ bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) {
out = Type::v128;
return true;
case BinaryConsts::EncodedType::funcref:
- out = Type::funcref;
+ out = Type(HeapType::func, Nullable);
return true;
case BinaryConsts::EncodedType::anyref:
- out = Type::anyref;
+ out = Type(HeapType::any, Nullable);
return true;
case BinaryConsts::EncodedType::eqref:
- out = Type::eqref;
+ out = Type(HeapType::eq, Nullable);
return true;
case BinaryConsts::EncodedType::i31ref:
out = Type(HeapType::i31, NonNullable);
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index bfe09280d..97a25d2c4 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1169,20 +1169,20 @@ Type SExpressionWasmBuilder::stringToType(const char* str,
}
}
if (strncmp(str, "funcref", 7) == 0 && (prefix || str[7] == 0)) {
- return Type::funcref;
+ return Type(HeapType::func, Nullable);
}
if ((strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) ||
(strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0))) {
- return Type::anyref;
+ return Type(HeapType::any, Nullable);
}
if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) {
- return Type::eqref;
+ return Type(HeapType::eq, Nullable);
}
if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) {
- return Type::i31ref;
+ return Type(HeapType::i31, NonNullable);
}
if (strncmp(str, "dataref", 7) == 0 && (prefix || str[7] == 0)) {
- return Type::dataref;
+ return Type(HeapType::data, NonNullable);
}
if (strncmp(str, "stringref", 9) == 0 && (prefix || str[9] == 0)) {
return Type(HeapType::string, Nullable);
@@ -1763,11 +1763,6 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) {
break;
}
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
WASM_UNREACHABLE("unexpected const type");
case Type::none:
case Type::unreachable: {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 28472aebd..c980d896b 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -187,11 +187,6 @@ void BinaryInstWriter::visitLoad(Load* curr) {
// the pointer is unreachable, so we are never reached; just don't emit
// a load
return;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
WASM_UNREACHABLE("unexpected type");
}
@@ -290,11 +285,6 @@ void BinaryInstWriter::visitStore(Store* curr) {
o << int8_t(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::V128Store);
break;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
@@ -742,11 +732,6 @@ void BinaryInstWriter::visitConst(Const* curr) {
}
break;
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
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 b13b1ecd7..84b11000f 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -567,19 +567,6 @@ Type asCanonical(Type type) {
}
}
-// Given a HeapType that may or may not be backed by the simplest possible
-// representation, return the equivalent type that is definitely backed by the
-// simplest possible representation.
-HeapType asCanonical(HeapType type) {
- if (type.isBasic()) {
- return type;
- } else if (auto canon = getHeapTypeInfo(type)->getCanonical()) {
- return *canon;
- } else {
- return type;
- }
-}
-
HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) {
if (type.isBasic()) {
return type.getBasic();
@@ -670,35 +657,6 @@ std::optional<Type> TypeInfo::getCanonical() const {
return tuple.types[0];
}
}
- if (isRef()) {
- HeapType basic = asCanonical(ref.heapType);
- if (basic.isBasic()) {
- if (ref.nullable) {
- switch (basic.getBasic()) {
- case HeapType::func:
- return Type::funcref;
- case HeapType::any:
- return Type::anyref;
- case HeapType::eq:
- return Type::eqref;
- case HeapType::i31:
- case HeapType::data:
- case HeapType::string:
- case HeapType::stringview_wtf8:
- case HeapType::stringview_wtf16:
- case HeapType::stringview_iter:
- break;
- }
- } else {
- if (basic == HeapType::i31) {
- return Type::i31ref;
- }
- if (basic == HeapType::data) {
- return Type::dataref;
- }
- }
- }
- }
return {};
}
@@ -1004,7 +962,7 @@ bool Type::isTuple() const {
bool Type::isRef() const {
if (isBasic()) {
- return id >= funcref && id <= _last_basic_type;
+ return false;
} else {
return getTypeInfo(*this)->isRef();
}
@@ -1012,7 +970,7 @@ bool Type::isRef() const {
bool Type::isFunction() const {
if (isBasic()) {
- return id == funcref;
+ return false;
} else {
auto* info = getTypeInfo(*this);
return info->isRef() && info->ref.heapType.isFunction();
@@ -1021,7 +979,7 @@ bool Type::isFunction() const {
bool Type::isData() const {
if (isBasic()) {
- return id == dataref;
+ return false;
} else {
auto* info = getTypeInfo(*this);
return info->isRef() && info->ref.heapType.isData();
@@ -1030,7 +988,7 @@ bool Type::isData() const {
bool Type::isNullable() const {
if (isBasic()) {
- return id >= funcref && id <= eqref; // except i31ref and dataref
+ return false;
} else {
return getTypeInfo(*this)->isNullable();
}
@@ -1099,11 +1057,6 @@ unsigned Type::getByteSize() const {
return 8;
case Type::v128:
return 16;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
case Type::unreachable:
break;
@@ -1217,16 +1170,6 @@ HeapType Type::getHeapType() const {
case Type::f64:
case Type::v128:
break;
- case Type::funcref:
- return HeapType::func;
- case Type::anyref:
- return HeapType::any;
- case Type::eqref:
- return HeapType::eq;
- case Type::i31ref:
- return HeapType::i31;
- case Type::dataref:
- return HeapType::data;
}
WASM_UNREACHABLE("Unexpected type");
} else {
@@ -2086,16 +2029,6 @@ std::ostream& TypePrinter::print(Type type) {
return os << "f64";
case Type::v128:
return os << "v128";
- case Type::funcref:
- return os << "funcref";
- case Type::anyref:
- return os << "anyref";
- case Type::eqref:
- return os << "eqref";
- case Type::i31ref:
- return os << "i31ref";
- case Type::dataref:
- return os << "dataref";
}
}
@@ -2109,19 +2042,36 @@ std::ostream& TypePrinter::print(Type type) {
print(type.getTuple());
} else if (type.isRef()) {
auto heapType = type.getHeapType();
- if (type.isNullable() && heapType.isBasic()) {
- // Print shorthands for certain nullable basic heap types.
- switch (heapType.getBasic()) {
- case HeapType::string:
- return os << "stringref";
- case HeapType::stringview_wtf8:
- return os << "stringview_wtf8";
- case HeapType::stringview_wtf16:
- return os << "stringview_wtf16";
- case HeapType::stringview_iter:
- return os << "stringview_iter";
- default:
- break;
+ if (heapType.isBasic()) {
+ // Print shorthands for certain basic heap types.
+ if (type.isNullable()) {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ return os << "funcref";
+ case HeapType::any:
+ return os << "anyref";
+ case HeapType::eq:
+ return os << "eqref";
+ case HeapType::string:
+ return os << "stringref";
+ case HeapType::stringview_wtf8:
+ return os << "stringview_wtf8";
+ case HeapType::stringview_wtf16:
+ return os << "stringview_wtf16";
+ case HeapType::stringview_iter:
+ return os << "stringview_iter";
+ default:
+ break;
+ }
+ } else {
+ switch (heapType.getBasic()) {
+ case HeapType::i31:
+ return os << "i31ref";
+ case HeapType::data:
+ return os << "dataref";
+ default:
+ break;
+ }
}
}
os << "(ref ";
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 4c6e8e929..65a910747 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1399,11 +1399,6 @@ void FunctionValidator::validateMemBytes(uint8_t bytes,
break;
case Type::unreachable:
break;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
WASM_UNREACHABLE("unexpected type");
}
@@ -2044,14 +2039,15 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) {
}
void FunctionValidator::visitRefEq(RefEq* curr) {
+ Type eqref = Type(HeapType::eq, Nullable);
shouldBeTrue(
getModule()->features.hasGC(), curr, "ref.eq requires gc to be enabled");
shouldBeSubType(curr->left->type,
- Type::eqref,
+ eqref,
curr->left,
"ref.eq's left argument should be a subtype of eqref");
shouldBeSubType(curr->right->type,
- Type::eqref,
+ eqref,
curr->right,
"ref.eq's right argument should be a subtype of eqref");
}
@@ -2330,7 +2326,7 @@ void FunctionValidator::visitI31Get(I31Get* curr) {
curr,
"i31.get_s/u requires gc to be enabled");
shouldBeSubType(curr->i31->type,
- Type::i31ref,
+ Type(HeapType::i31, Nullable),
curr->i31,
"i31.get_s/u's argument should be i31ref");
}
@@ -2853,11 +2849,6 @@ void FunctionValidator::validateAlignment(
case Type::v128:
case Type::unreachable:
break;
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
case Type::none:
WASM_UNREACHABLE("invalid type");
}
@@ -3130,7 +3121,7 @@ static void validateTables(Module& module, ValidationInfo& info) {
"--enable-reference-types)");
if (!module.tables.empty()) {
auto& table = module.tables.front();
- info.shouldBeTrue(table->type == Type::funcref,
+ info.shouldBeTrue(table->type == Type(HeapType::func, Nullable),
"table",
"Only funcref is valid for table type (when reference "
"types are disabled)");
@@ -3150,6 +3141,8 @@ static void validateTables(Module& module, ValidationInfo& info) {
}
}
+ Type anyref = Type(HeapType::any, Nullable);
+ Type funcref = Type(HeapType::func, Nullable);
for (auto& table : module.tables) {
info.shouldBeTrue(table->initial <= table->max,
"table",
@@ -3159,14 +3152,13 @@ static void validateTables(Module& module, ValidationInfo& info) {
"table",
"Non-nullable reference types are not yet supported for tables");
if (!module.features.hasGC()) {
- info.shouldBeTrue(table->type.isFunction() || table->type == Type::anyref,
+ info.shouldBeTrue(table->type.isFunction() || table->type == anyref,
"table",
- "Only function reference types or anyref are valid "
+ "Only function reference types or externref are valid "
"for table type (when GC is disabled)");
}
if (!module.features.hasTypedFunctionReferences()) {
- info.shouldBeTrue(table->type == Type::funcref ||
- table->type == Type::anyref,
+ info.shouldBeTrue(table->type == funcref || table->type == anyref,
"table",
"Only funcref and anyref are valid for table type "
"(when typed-function references are disabled)");
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index eceb4585b..bd83d62ed 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -903,7 +903,7 @@ void I31New::finalize() {
if (value->type == Type::unreachable) {
type = Type::unreachable;
} else {
- type = Type::i31ref;
+ type = Type(HeapType::i31, NonNullable);
}
}
@@ -1024,11 +1024,11 @@ Type BrOn::getSentType() {
}
return Type(getIntendedType(), NonNullable);
case BrOnFunc:
- return Type::funcref;
+ return Type(HeapType::func, NonNullable);
case BrOnData:
- return Type::dataref;
+ return Type(HeapType::data, NonNullable);
case BrOnI31:
- return Type::i31ref;
+ return Type(HeapType::i31, NonNullable);
case BrOnCastFail:
case BrOnNonFunc:
case BrOnNonData:
@@ -1164,10 +1164,10 @@ void RefAs::finalize() {
type = Type(HeapType::func, NonNullable);
break;
case RefAsData:
- type = Type::dataref;
+ type = Type(HeapType::data, NonNullable);
break;
case RefAsI31:
- type = Type::i31ref;
+ type = Type(HeapType::i31, NonNullable);
break;
default:
WASM_UNREACHABLE("invalid ref.as_*");
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index e3a2ab588..8b86017ff 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -1488,11 +1488,6 @@ Result<typename Ctx::InstrT> makeConst(Ctx& ctx, ParseInput& in, Type type) {
return in.err("unimplemented instruction");
case Type::none:
case Type::unreachable:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
break;
}
WASM_UNREACHABLE("unexpected type");
diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js
index ecfc73bff..6e5e19b2c 100644
--- a/test/binaryen.js/kitchen-sink.js
+++ b/test/binaryen.js/kitchen-sink.js
@@ -68,24 +68,6 @@ function test_types() {
console.log(" // BinaryenTypeVec128: " + binaryen.v128);
console.log(" //", binaryen.expandType(binaryen.v128).join(","));
- console.log(" // BinaryenTypeFuncref: " + binaryen.funcref);
- console.log(" //", binaryen.expandType(binaryen.funcref).join(","));
-
- console.log(" // BinaryenTypeExternref: " + binaryen.externref);
- console.log(" //", binaryen.expandType(binaryen.externref).join(","));
-
- console.log(" // BinaryenTypeAnyref: " + binaryen.anyref);
- console.log(" //", binaryen.expandType(binaryen.anyref).join(","));
-
- console.log(" // BinaryenTypeEqref: " + binaryen.eqref);
- console.log(" //", binaryen.expandType(binaryen.eqref).join(","));
-
- console.log(" // BinaryenTypeI31ref: " + binaryen.i31ref);
- console.log(" //", binaryen.expandType(binaryen.i31ref).join(","));
-
- console.log(" // BinaryenTypeDataref: " + binaryen.dataref);
- console.log(" //", binaryen.expandType(binaryen.dataref).join(","));
-
console.log(" // BinaryenTypeAuto: " + binaryen.auto);
var i32_pair = binaryen.createType([binaryen.i32, binaryen.i32]);
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 36b5c6749..f5b77234d 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -12,18 +12,6 @@
// 5
// BinaryenTypeVec128: 6
// 6
- // BinaryenTypeFuncref: 7
- // 7
- // BinaryenTypeExternref: 8
- // 8
- // BinaryenTypeAnyref: 8
- // 8
- // BinaryenTypeEqref: 9
- // 9
- // BinaryenTypeI31ref: 10
- // 10
- // BinaryenTypeDataref: 11
- // 11
// BinaryenTypeAuto: -1
// 2,2
// 2,2
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index 28e784a05..90ea43e8a 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -229,37 +229,43 @@ void test_types() {
assert(valueType == v128);
BinaryenType funcref = BinaryenTypeFuncref();
- printf("BinaryenTypeFuncref: %d\n", funcref);
+ printf("BinaryenTypeFuncref: (ptr)\n", funcref);
+ assert(funcref == BinaryenTypeFuncref());
assert(BinaryenTypeArity(funcref) == 1);
BinaryenTypeExpand(funcref, &valueType);
assert(valueType == funcref);
BinaryenType externref = BinaryenTypeExternref();
- printf("BinaryenTypeExternref: %d\n", externref);
+ printf("BinaryenTypeExternref: (ptr)\n", externref);
+ assert(externref == BinaryenTypeExternref());
assert(BinaryenTypeArity(externref) == 1);
BinaryenTypeExpand(externref, &valueType);
assert(valueType == externref);
BinaryenType anyref = BinaryenTypeAnyref();
- printf("BinaryenTypeAnyref: %d\n", anyref);
+ printf("BinaryenTypeAnyref: (ptr)\n", anyref);
+ assert(anyref == BinaryenTypeAnyref());
assert(BinaryenTypeArity(anyref) == 1);
BinaryenTypeExpand(anyref, &valueType);
assert(valueType == anyref);
BinaryenType eqref = BinaryenTypeEqref();
- printf("BinaryenTypeEqref: %d\n", eqref);
+ printf("BinaryenTypeEqref: (ptr)\n", eqref);
+ assert(eqref == BinaryenTypeEqref());
assert(BinaryenTypeArity(eqref) == 1);
BinaryenTypeExpand(eqref, &valueType);
assert(valueType == eqref);
BinaryenType i31ref = BinaryenTypeI31ref();
- printf("BinaryenTypeI31ref: %d\n", i31ref);
+ printf("BinaryenTypeI31ref: (ptr)\n", i31ref);
+ assert(i31ref == BinaryenTypeI31ref());
assert(BinaryenTypeArity(i31ref) == 1);
BinaryenTypeExpand(i31ref, &valueType);
assert(valueType == i31ref);
BinaryenType dataref = BinaryenTypeDataref();
- printf("BinaryenTypeDataref: %d\n", dataref);
+ printf("BinaryenTypeDataref: (ptr)\n", dataref);
+ assert(dataref == BinaryenTypeDataref());
assert(BinaryenTypeArity(dataref) == 1);
BinaryenTypeExpand(dataref, &valueType);
assert(valueType == dataref);
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index 9f8324d48..e3a8e5676 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -5,12 +5,12 @@ BinaryenTypeInt64: 3
BinaryenTypeFloat32: 4
BinaryenTypeFloat64: 5
BinaryenTypeVec128: 6
-BinaryenTypeFuncref: 7
-BinaryenTypeExternref: 8
-BinaryenTypeAnyref: 8
-BinaryenTypeEqref: 9
-BinaryenTypeI31ref: 10
-BinaryenTypeDataref: 11
+BinaryenTypeFuncref: (ptr)
+BinaryenTypeExternref: (ptr)
+BinaryenTypeAnyref: (ptr)
+BinaryenTypeEqref: (ptr)
+BinaryenTypeI31ref: (ptr)
+BinaryenTypeDataref: (ptr)
BinaryenTypeAuto: -1
BinaryenPackedTypeNotPacked: 0
BinaryenPackedTypeInt8: 1
diff --git a/test/example/stack-utils.cpp b/test/example/stack-utils.cpp
index 8709396f9..c54040251 100644
--- a/test/example/stack-utils.cpp
+++ b/test/example/stack-utils.cpp
@@ -250,6 +250,9 @@ void test_signature_composition() {
}
void test_signature_subtype() {
+ Type funcref = Type(HeapType::func, Nullable);
+ Type anyref = Type(HeapType::any, Nullable);
+
std::cout << ";; Test stack signature subtyping\n";
// Differences in unreachability only
{
@@ -260,15 +263,15 @@ void test_signature_subtype() {
}
// Covariance of results
{
- StackSignature a(Type::none, Type::funcref, StackSignature::Fixed);
- StackSignature b(Type::none, Type::anyref, StackSignature::Fixed);
+ StackSignature a(Type::none, funcref, StackSignature::Fixed);
+ StackSignature b(Type::none, anyref, StackSignature::Fixed);
assert(StackSignature::isSubType(a, b));
assert(!StackSignature::isSubType(b, a));
}
// Contravariance of params
{
- StackSignature a(Type::anyref, Type::none, StackSignature::Fixed);
- StackSignature b(Type::funcref, Type::none, StackSignature::Fixed);
+ StackSignature a(anyref, Type::none, StackSignature::Fixed);
+ StackSignature b(funcref, Type::none, StackSignature::Fixed);
assert(StackSignature::isSubType(a, b));
assert(!StackSignature::isSubType(b, a));
}
@@ -355,6 +358,9 @@ void test_signature_subtype() {
}
void test_signature_lub() {
+ Type funcref = Type(HeapType::func, Nullable);
+ Type anyref = Type(HeapType::any, Nullable);
+
std::cout << ";; Test stack signature lub\n";
{
StackSignature a{Type::none, Type::none, StackSignature::Fixed};
@@ -392,30 +398,28 @@ void test_signature_lub() {
(StackSignature{Type::i32, Type::i32, StackSignature::Polymorphic}));
}
{
- StackSignature a{Type::none, Type::anyref, StackSignature::Polymorphic};
- StackSignature b{Type::none, Type::funcref, StackSignature::Polymorphic};
+ StackSignature a{Type::none, anyref, StackSignature::Polymorphic};
+ StackSignature b{Type::none, funcref, StackSignature::Polymorphic};
assert(StackSignature::haveLeastUpperBound(a, b));
- assert(
- StackSignature::getLeastUpperBound(a, b) ==
- (StackSignature{Type::none, Type::anyref, StackSignature::Polymorphic}));
+ assert(StackSignature::getLeastUpperBound(a, b) ==
+ (StackSignature{Type::none, anyref, StackSignature::Polymorphic}));
}
{
- StackSignature a{Type::anyref, Type::none, StackSignature::Polymorphic};
- StackSignature b{Type::funcref, Type::none, StackSignature::Polymorphic};
+ StackSignature a{anyref, Type::none, StackSignature::Polymorphic};
+ StackSignature b{funcref, Type::none, StackSignature::Polymorphic};
// assert(StackSignature::haveLeastUpperBound(a, b));
// assert(StackSignature::getLeastUpperBound(a, b) ==
- // (StackSignature{Type::funcref, Type::none,
+ // (StackSignature{funcref, Type::none,
// StackSignature::Polymorphic}));
}
{
StackSignature a{
- {Type::i32, Type::funcref}, Type::funcref, StackSignature::Polymorphic};
- StackSignature b{
- Type::funcref, {Type::f32, Type::anyref}, StackSignature::Polymorphic};
+ {Type::i32, funcref}, funcref, StackSignature::Polymorphic};
+ StackSignature b{funcref, {Type::f32, anyref}, StackSignature::Polymorphic};
assert(StackSignature::haveLeastUpperBound(a, b));
assert(StackSignature::getLeastUpperBound(a, b) ==
- (StackSignature{{Type::i32, Type::funcref},
- {Type::f32, Type::anyref},
+ (StackSignature{{Type::i32, funcref},
+ {Type::f32, anyref},
StackSignature::Polymorphic}));
}
// No LUB
diff --git a/test/example/type-builder-nominal.cpp b/test/example/type-builder-nominal.cpp
index 8dbbfcf30..cbda43f1f 100644
--- a/test/example/type-builder-nominal.cpp
+++ b/test/example/type-builder-nominal.cpp
@@ -123,21 +123,24 @@ void test_canonicalization() {
void test_basic() {
std::cout << ";; Test basic\n";
+ Type canonAnyref = Type(HeapType::any, Nullable);
+ Type canonI31ref = Type(HeapType::i31, NonNullable);
+
TypeBuilder builder(6);
Type anyref = builder.getTempRefType(builder[4], Nullable);
Type i31ref = builder.getTempRefType(builder[5], NonNullable);
- builder[0] = Signature(Type::anyref, Type::i31ref);
- builder[1] = Signature(anyref, Type::i31ref);
- builder[2] = Signature(Type::anyref, i31ref);
+ builder[0] = Signature(canonAnyref, canonI31ref);
+ builder[1] = Signature(anyref, canonI31ref);
+ builder[2] = Signature(canonAnyref, i31ref);
builder[3] = Signature(anyref, i31ref);
builder[4] = HeapType::any;
builder[5] = HeapType::i31;
std::vector<HeapType> built = *builder.build();
- assert(built[0].getSignature() == Signature(Type::anyref, Type::i31ref));
+ assert(built[0].getSignature() == Signature(canonAnyref, canonI31ref));
assert(built[1].getSignature() == built[0].getSignature());
assert(built[2].getSignature() == built[1].getSignature());
assert(built[3].getSignature() == built[2].getSignature());
@@ -150,16 +153,18 @@ void test_basic() {
void test_signatures(bool warm) {
std::cout << ";; Test canonical signatures\n";
+ Type canonAnyref = Type(HeapType::any, Nullable);
+ Type canonI31ref = Type(HeapType::i31, NonNullable);
+
TypeBuilder builder(2);
Type tempRef = builder.getTempRefType(builder[0], Nullable);
- builder[0] = Signature(Type::i31ref, Type::anyref);
+ builder[0] = Signature(canonI31ref, canonAnyref);
builder[1] = Signature(tempRef, tempRef);
std::vector<HeapType> built = *builder.build();
- HeapType small = Signature(Type::i31ref, Type::anyref);
- HeapType big =
- Signature(Type(Signature(Type::i31ref, Type::anyref), Nullable),
- Type(Signature(Type::i31ref, Type::anyref), Nullable));
+ HeapType small = Signature(canonI31ref, canonAnyref);
+ HeapType big = Signature(Type(Signature(canonI31ref, canonAnyref), Nullable),
+ Type(Signature(canonI31ref, canonAnyref), Nullable));
if (warm) {
assert(built[0] != small);
assert(built[1] != big);
@@ -306,6 +311,9 @@ void test_recursive() {
void test_subtypes() {
std::cout << ";; Test subtyping\n";
+ Type anyref = Type(HeapType::any, Nullable);
+ Type funcref = Type(HeapType::func, Nullable);
+
auto LUB = [&](HeapType a, HeapType b) {
Type refA = Type(a, Nullable);
Type refB = Type(b, Nullable);
@@ -362,7 +370,7 @@ void test_subtypes() {
Type structRef1 = builder.getTempRefType(builder[1], Nullable);
builder[0] = Struct{};
builder[1] = Struct{};
- builder[2] = Signature(Type::none, Type::anyref);
+ builder[2] = Signature(Type::none, anyref);
builder[3] = Signature(Type::none, structRef0);
builder[4] = Signature(Type::none, structRef1);
built = *builder.build();
@@ -394,12 +402,10 @@ void test_subtypes() {
builder[0].subTypeOf(builder[1]);
builder[2].subTypeOf(builder[3]);
builder[4].subTypeOf(builder[5]);
- builder[0] =
- Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)});
- builder[1] =
- Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)});
- builder[2] = Signature(Type::i32, Type::anyref);
- builder[3] = Signature(Type::i32, Type::anyref);
+ builder[0] = Struct({Field(Type::i32, Mutable), Field(anyref, Mutable)});
+ builder[1] = Struct({Field(Type::i32, Mutable), Field(anyref, Mutable)});
+ builder[2] = Signature(Type::i32, anyref);
+ builder[3] = Signature(Type::i32, anyref);
builder[4] = Array(Field(Type::i32, Mutable));
builder[5] = Array(Field(Type::i32, Mutable));
built = *builder.build();
@@ -428,8 +434,8 @@ void test_subtypes() {
std::vector<HeapType> built;
{
TypeBuilder builder(2);
- builder[0] = Struct({Field(Type::anyref, Immutable)});
- builder[1] = Struct({Field(Type::funcref, Immutable)});
+ builder[0] = Struct({Field(anyref, Immutable)});
+ builder[1] = Struct({Field(funcref, Immutable)});
builder[1].subTypeOf(builder[0]);
built = *builder.build();
}
diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp
index ce7b74841..219282ea8 100644
--- a/test/example/type-builder.cpp
+++ b/test/example/type-builder.cpp
@@ -44,21 +44,24 @@ void test_canonicalization() {
void test_basic() {
std::cout << ";; Test basic\n";
+ Type canonAnyref = Type(HeapType::any, Nullable);
+ Type canonI31ref = Type(HeapType::i31, NonNullable);
+
TypeBuilder builder(6);
Type anyref = builder.getTempRefType(builder[4], Nullable);
Type i31ref = builder.getTempRefType(builder[5], NonNullable);
- builder[0] = Signature(Type::anyref, Type::i31ref);
- builder[1] = Signature(anyref, Type::i31ref);
- builder[2] = Signature(Type::anyref, i31ref);
+ builder[0] = Signature(canonAnyref, canonI31ref);
+ builder[1] = Signature(anyref, canonI31ref);
+ builder[2] = Signature(canonAnyref, i31ref);
builder[3] = Signature(anyref, i31ref);
builder[4] = HeapType::any;
builder[5] = HeapType::i31;
std::vector<HeapType> built = *builder.build();
- assert(built[0] == Signature(Type::anyref, Type::i31ref));
+ assert(built[0] == Signature(canonAnyref, canonI31ref));
assert(built[1] == built[0]);
assert(built[2] == built[1]);
assert(built[3] == built[2]);
@@ -210,8 +213,8 @@ void test_recursive() {
std::cout << print(built[1]) << "\n\n";
assert(built[0].getSignature().results.getHeapType() == built[0]);
assert(built[1].getSignature().results.getHeapType() == built[0]);
- assert(built[0].getSignature().params == Type::anyref);
- assert(built[1].getSignature().params == Type::anyref);
+ assert(built[0].getSignature().params == Type(HeapType::any, Nullable));
+ assert(built[1].getSignature().params == Type(HeapType::any, Nullable));
assert(built[0] == built[1]);
assert(built[2] == HeapType::any);
}
@@ -220,6 +223,12 @@ void test_recursive() {
void test_lub() {
std::cout << ";; Test LUBs\n";
+ Type func = Type(HeapType::func, Nullable);
+ Type any = Type(HeapType::any, Nullable);
+ Type eq = Type(HeapType::eq, Nullable);
+ Type i31 = Type(HeapType::i31, Nullable);
+ Type data = Type(HeapType::data, Nullable);
+
auto LUB = [&](Type a, Type b) {
Type lubAB = Type::getLeastUpperBound(a, b);
Type lubBA = Type::getLeastUpperBound(b, a);
@@ -238,15 +247,11 @@ void test_lub() {
{
// Basic Types
- for (auto other : {Type::funcref,
- Type::anyref,
- Type::eqref,
- Type::i31ref,
- Type::dataref}) {
- assert(LUB(Type::anyref, other) == Type::anyref);
+ for (auto other : {func, any, eq, i31, data}) {
+ assert(LUB(any, other) == any);
}
- assert(LUB(Type::eqref, Type::funcref) == Type::anyref);
- assert(LUB(Type::i31ref, Type::dataref) == Type(HeapType::eq, NonNullable));
+ assert(LUB(eq, func) == any);
+ assert(LUB(i31, data) == eq);
}
{
@@ -260,22 +265,21 @@ void test_lub() {
{
// Funcref with specific signature
- assert(LUB(Type::funcref, Type(Signature(), Nullable)) == Type::funcref);
+ assert(LUB(func, Type(Signature(), Nullable)) == func);
}
{
// Incompatible signatures
- Type a(Signature(Type::none, Type::anyref), Nullable);
- Type b(Signature(Type::anyref, Type::none), Nullable);
- assert(LUB(a, b) == Type::funcref);
+ Type a(Signature(Type::none, any), Nullable);
+ Type b(Signature(any, Type::none), Nullable);
+ assert(LUB(a, b) == Type(HeapType::func, Nullable));
}
{
// Signatures incompatible in tuple size
- Type a(Signature(Type::none, {Type::anyref, Type::anyref}), Nullable);
- Type b(Signature(Type::none, {Type::anyref, Type::anyref, Type::anyref}),
- Nullable);
- assert(LUB(a, b) == Type::funcref);
+ Type a(Signature(Type::none, {any, any}), Nullable);
+ Type b(Signature(Type::none, {any, any, any}), Nullable);
+ assert(LUB(a, b) == Type(HeapType::func, Nullable));
}
// {
@@ -303,24 +307,24 @@ void test_lub() {
{
// Mutable fields are invariant
- Type a(Array(Field(Type::eqref, Mutable)), Nullable);
- Type b(Array(Field(Type::funcref, Mutable)), Nullable);
- assert(LUB(a, b) == Type(HeapType::data, Nullable));
+ Type a(Array(Field(eq, Mutable)), Nullable);
+ Type b(Array(Field(func, Mutable)), Nullable);
+ assert(LUB(a, b) == data);
}
{
// Immutable fields are covariant
- Type a(Array(Field(Type::eqref, Immutable)), Nullable);
- Type b(Array(Field(Type::funcref, Immutable)), Nullable);
- Type lub(Array(Field(Type::anyref, Immutable)), Nullable);
+ Type a(Array(Field(eq, Immutable)), Nullable);
+ Type b(Array(Field(func, Immutable)), Nullable);
+ Type lub(Array(Field(any, Immutable)), Nullable);
assert(LUB(a, b) == lub);
}
{
// Depth subtyping
- Type a(Struct({Field(Type::eqref, Immutable)}), Nullable);
- Type b(Struct({Field(Type::funcref, Immutable)}), Nullable);
- Type lub(Struct({Field(Type::anyref, Immutable)}), Nullable);
+ Type a(Struct({Field(eq, Immutable)}), Nullable);
+ Type b(Struct({Field(func, Immutable)}), Nullable);
+ Type lub(Struct({Field(any, Immutable)}), Nullable);
assert(LUB(a, b) == lub);
}
@@ -344,32 +348,29 @@ void test_lub() {
{
// Width and depth subtyping with different suffixes
- Type a(Struct({Field(Type::eqref, Immutable), Field(Type::i64, Immutable)}),
+ Type a(Struct({Field(eq, Immutable), Field(Type::i64, Immutable)}),
Nullable);
- Type b(
- Struct({Field(Type::funcref, Immutable), Field(Type::f32, Immutable)}),
- Nullable);
- Type lub(Struct({Field(Type::anyref, Immutable)}), Nullable);
+ Type b(Struct({Field(func, Immutable), Field(Type::f32, Immutable)}),
+ Nullable);
+ Type lub(Struct({Field(any, Immutable)}), Nullable);
assert(LUB(a, b) == lub);
}
{
// No common prefix
- Type a(
- Struct({Field(Type::i32, Immutable), Field(Type::anyref, Immutable)}),
- Nullable);
- Type b(
- Struct({Field(Type::f32, Immutable), Field(Type::anyref, Immutable)}),
- Nullable);
+ Type a(Struct({Field(Type::i32, Immutable), Field(any, Immutable)}),
+ Nullable);
+ Type b(Struct({Field(Type::f32, Immutable), Field(any, Immutable)}),
+ Nullable);
Type lub(Struct(), Nullable);
assert(LUB(a, b) == lub);
}
{
// Nested structs
- Type innerA(Struct({Field(Type::eqref, Immutable)}), Nullable);
- Type innerB(Struct({Field(Type::funcref, Immutable)}), Nullable);
- Type innerLub(Struct({Field(Type::anyref, Immutable)}), Nullable);
+ Type innerA(Struct({Field(eq, Immutable)}), Nullable);
+ Type innerB(Struct({Field(func, Immutable)}), Nullable);
+ Type innerLub(Struct({Field(any, Immutable)}), Nullable);
Type a(Struct({Field(innerA, Immutable)}), Nullable);
Type b(Struct({Field(innerB, Immutable)}), Nullable);
Type lub(Struct({Field(innerLub, Immutable)}), Nullable);
@@ -381,18 +382,15 @@ void test_lub() {
TypeBuilder builder(2);
Type tempA = builder.getTempRefType(builder[0], Nullable);
Type tempB = builder.getTempRefType(builder[1], Nullable);
- builder[0] =
- Struct({Field(tempB, Immutable), Field(Type::eqref, Immutable)});
- builder[1] =
- Struct({Field(tempA, Immutable), Field(Type::funcref, Immutable)});
+ builder[0] = Struct({Field(tempB, Immutable), Field(eq, Immutable)});
+ builder[1] = Struct({Field(tempA, Immutable), Field(func, Immutable)});
auto built = *builder.build();
Type a(built[0], Nullable);
Type b(built[1], Nullable);
TypeBuilder lubBuilder(1);
Type tempLub = builder.getTempRefType(lubBuilder[0], Nullable);
- lubBuilder[0] =
- Struct({Field(tempLub, Immutable), Field(Type::anyref, Immutable)});
+ lubBuilder[0] = Struct({Field(tempLub, Immutable), Field(any, Immutable)});
built = *lubBuilder.build();
Type lub(built[0], Nullable);
diff --git a/test/example/typeinfo.cpp b/test/example/typeinfo.cpp
index ed5637bd9..55e7b9082 100644
--- a/test/example/typeinfo.cpp
+++ b/test/example/typeinfo.cpp
@@ -8,7 +8,6 @@ using namespace wasm;
void test_compound() {
{
HeapType func(HeapType::func);
- assert(Type(func, Nullable).getID() == Type::funcref);
assert(Type(func, NonNullable).getID() == Type(func, NonNullable).getID());
assert(Type(func, NonNullable).getID() != Type(func, Nullable).getID());
HeapType sameFunc(HeapType::func);
@@ -16,7 +15,6 @@ void test_compound() {
Type(sameFunc, NonNullable).getID());
HeapType any(HeapType::any);
- assert(Type(any, Nullable).getID() == Type::anyref);
assert(Type(any, NonNullable).getID() == Type(any, NonNullable).getID());
assert(Type(any, NonNullable).getID() != Type(any, Nullable).getID());
HeapType sameAny(HeapType::any);
@@ -24,14 +22,12 @@ void test_compound() {
Type(sameAny, NonNullable).getID());
HeapType eq(HeapType::eq);
- // assert(Type(eq, Nullable).getID() == Type::eqref);
assert(Type(eq, NonNullable).getID() == Type(eq, NonNullable).getID());
assert(Type(eq, NonNullable).getID() != Type(eq, Nullable).getID());
HeapType sameEq(HeapType::eq);
assert(Type(eq, NonNullable).getID() == Type(sameEq, NonNullable).getID());
HeapType i31(HeapType::i31);
- // assert(Type(i31, NonNullable).getID() == Type::i31ref);
assert(Type(i31, NonNullable).getID() == Type(i31, NonNullable).getID());
assert(Type(i31, NonNullable).getID() != Type(i31, Nullable).getID());
HeapType sameI31(HeapType::i31);
@@ -92,7 +88,7 @@ void test_compound() {
Tuple sameTuple({Type::i32, Type::f64});
assert(Type(tuple).getID() == Type(sameTuple).getID());
- Tuple otherTuple({Type::f64, Type::anyref});
+ Tuple otherTuple({Type::f64, Type::i64});
assert(Type(tuple).getID() != Type(otherTuple).getID());
}
{
@@ -165,7 +161,6 @@ void test_printing() {
{Type::i64, Immutable},
{Type::f32, Mutable},
{Type::f64, Mutable},
- {Type::anyref, Immutable},
});
std::cout << struct_ << "\n";
std::cout << Type(struct_, NonNullable) << "\n";
@@ -177,7 +172,7 @@ void test_printing() {
std::cout << array << "\n";
std::cout << Type(array, NonNullable) << "\n";
std::cout << Type(array, Nullable) << "\n";
- Array arrayMut({Type::anyref, Mutable});
+ Array arrayMut({Type::i64, Mutable});
std::cout << arrayMut << "\n";
std::cout << Type(arrayMut, NonNullable) << "\n";
std::cout << Type(arrayMut, Nullable) << "\n";
@@ -190,7 +185,6 @@ void test_printing() {
Tuple tuple({
Type::i32,
Type::f64,
- Type::anyref,
});
std::cout << tuple << "\n";
std::cout << Type(tuple) << "\n";
diff --git a/test/example/typeinfo.txt b/test/example/typeinfo.txt
index 924fcb3ec..838fd34a3 100644
--- a/test/example/typeinfo.txt
+++ b/test/example/typeinfo.txt
@@ -27,7 +27,7 @@ i31ref
(struct)
(ref $struct.0)
(ref null $struct.0)
-(struct (field i32 i64 (mut f32) (mut f64) anyref))
+(struct (field i32 i64 (mut f32) (mut f64)))
(ref $struct.0)
(ref null $struct.0)
@@ -35,15 +35,15 @@ i31ref
(array i32)
(ref $array.0)
(ref null $array.0)
-(array (mut anyref))
+(array (mut i64))
(ref $array.0)
(ref null $array.0)
;; Tuple
()
none
-(i32 f64 anyref)
-(i32 f64 anyref)
+(i32 f64)
+(i32 f64)
;; Rtt
(rtt 0 func)
diff --git a/test/gtest/possible-contents.cpp b/test/gtest/possible-contents.cpp
index 2994a6221..2bed9a882 100644
--- a/test/gtest/possible-contents.cpp
+++ b/test/gtest/possible-contents.cpp
@@ -59,6 +59,9 @@ protected:
wasm::setTypeSystem(TypeSystem::Nominal);
}
+ Type anyref = Type(HeapType::any, Nullable);
+ Type funcref = Type(HeapType::func, Nullable);
+
PossibleContents none = PossibleContents::none();
PossibleContents i32Zero = PossibleContents::literal(Literal(int32_t(0)));
@@ -74,15 +77,14 @@ protected:
PossibleContents i32Global2 =
PossibleContents::global("i32Global2", Type::i32);
PossibleContents f64Global = PossibleContents::global("f64Global", Type::f64);
- PossibleContents anyGlobal =
- PossibleContents::global("anyGlobal", Type::anyref);
+ PossibleContents anyGlobal = PossibleContents::global("anyGlobal", anyref);
PossibleContents nonNullFunc = PossibleContents::literal(
Literal("func", Type(Signature(Type::none, Type::none), NonNullable)));
PossibleContents exactI32 = PossibleContents::exactType(Type::i32);
- PossibleContents exactAnyref = PossibleContents::exactType(Type::anyref);
- PossibleContents exactFuncref = PossibleContents::exactType(Type::funcref);
+ PossibleContents exactAnyref = PossibleContents::exactType(anyref);
+ PossibleContents exactFuncref = PossibleContents::exactType(funcref);
PossibleContents exactNonNullAnyref =
PossibleContents::exactType(Type(HeapType::any, NonNullable));
PossibleContents exactNonNullFuncref =
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
index ca9bd865d..d06236130 100644
--- a/test/gtest/type-builder.cpp
+++ b/test/gtest/type-builder.cpp
@@ -481,11 +481,13 @@ static void testCanonicalizeBasicTypes() {
Type anyref = builder.getTempRefType(builder[0], Nullable);
Type anyrefs = builder.getTempTupleType({anyref, anyref});
+ Type anyrefCanon = Type(HeapType::any, Nullable);
+
builder[0] = HeapType::any;
builder[1] = Struct({Field(anyref, Immutable)});
- builder[2] = Struct({Field(Type::anyref, Immutable)});
+ builder[2] = Struct({Field(anyrefCanon, Immutable)});
builder[3] = Signature(anyrefs, Type::none);
- builder[4] = Signature({Type::anyref, Type::anyref}, Type::none);
+ builder[4] = Signature({anyrefCanon, anyrefCanon}, Type::none);
auto result = builder.build();
ASSERT_TRUE(result);
@@ -504,10 +506,13 @@ TEST_F(IsorecursiveTest, CanonicalizeBasicTypes) {
// Test SubTypes utility code.
TEST_F(NominalTest, testSubTypes) {
+ Type anyref = Type(HeapType::any, Nullable);
+ Type funcref = Type(HeapType::func, Nullable);
+
// Build type types, the second of which is a subtype.
TypeBuilder builder(2);
- builder[0] = Struct({Field(Type::anyref, Immutable)});
- builder[1] = Struct({Field(Type::funcref, Immutable)});
+ builder[0] = Struct({Field(anyref, Immutable)});
+ builder[1] = Struct({Field(funcref, Immutable)});
builder[1].subTypeOf(builder[0]);
auto built = *builder.build();
diff --git a/test/lit/fuzz-types/isorecursive.test b/test/lit/fuzz-types/isorecursive.test
index 9165d9265..78315c5b1 100644
--- a/test/lit/fuzz-types/isorecursive.test
+++ b/test/lit/fuzz-types/isorecursive.test
@@ -2,25 +2,25 @@
;; CHECK: (rec
;; CHECK-NEXT: (type $0 (struct_subtype data))
-;; CHECK-NEXT: (type $1 (func_subtype (param i31ref) (result dataref) func))
-;; CHECK-NEXT: (type $2 (array_subtype i32 data))
-;; CHECK-NEXT: (type $3 (array_subtype i32 $2))
-;; CHECK-NEXT: (type $4 (array_subtype i32 $2))
-;; CHECK-NEXT: (type $5 (array_subtype i32 $3))
-;; CHECK-NEXT: (type $6 (array_subtype i32 $3))
+;; CHECK-NEXT: (type $1 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) func))
+;; CHECK-NEXT: (type $2 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) data))
+;; CHECK-NEXT: (type $3 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2))
+;; CHECK-NEXT: (type $4 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2))
+;; CHECK-NEXT: (type $5 (struct_subtype (field f64 v128 (ref null $10) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $3))
+;; CHECK-NEXT: (type $6 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $3))
;; CHECK-NEXT: (type $7 (struct_subtype $0))
-;; CHECK-NEXT: (type $8 (struct_subtype $0))
-;; CHECK-NEXT: (type $9 (array_subtype i32 $6))
-;; CHECK-NEXT: (type $10 (struct_subtype $0))
-;; CHECK-NEXT: (type $11 (array_subtype i32 $2))
+;; CHECK-NEXT: (type $8 (struct_subtype (field f32 (mut i16) (ref eq) (mut (rtt $2))) $0))
+;; CHECK-NEXT: (type $9 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $6))
+;; CHECK-NEXT: (type $10 (struct_subtype (field (ref $2) (mut (ref $13)) (ref null i31) v128 (ref null $6)) $0))
+;; CHECK-NEXT: (type $11 (struct_subtype (field f64 v128 (ref $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2))
;; CHECK-NEXT: (type $12 (struct_subtype $0))
-;; CHECK-NEXT: (type $13 (array_subtype i32 $6))
+;; CHECK-NEXT: (type $13 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $6))
;; CHECK-NEXT: )
;; CHECK-NEXT: (rec
-;; CHECK-NEXT: (type $14 (struct_subtype $10))
-;; CHECK-NEXT: (type $15 (func_subtype (param i31ref) (result dataref) $1))
-;; CHECK-NEXT: (type $16 (array_subtype i32 $2))
-;; CHECK-NEXT: (type $17 (struct_subtype $14))
-;; CHECK-NEXT: (type $18 (struct_subtype (field (mut funcref) (mut (ref null $7)) funcref) $12))
-;; CHECK-NEXT: (type $19 (func_subtype (param i31ref) (result dataref) $15))
+;; CHECK-NEXT: (type $14 (struct_subtype (field (ref $2) (mut (ref $13)) i31ref v128 (ref $9) (mut (ref null $10))) $10))
+;; CHECK-NEXT: (type $15 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) $1))
+;; CHECK-NEXT: (type $16 (struct_subtype (field f64 v128 (ref null $0) (mut i16) (mut (rtt $5)) (mut (ref null $2))) $2))
+;; CHECK-NEXT: (type $17 (struct_subtype (field (ref $2) (mut (ref $13)) i31ref v128 (ref $9) (mut (ref null $10))) $14))
+;; CHECK-NEXT: (type $18 (struct_subtype $12))
+;; CHECK-NEXT: (type $19 (func_subtype (param f64) (result f64 i64 f32 (rtt any) f64 f32) $15))
;; CHECK-NEXT: )
diff --git a/test/lit/fuzz-types/nominal.test b/test/lit/fuzz-types/nominal.test
index 248ce6539..299cf2613 100644
--- a/test/lit/fuzz-types/nominal.test
+++ b/test/lit/fuzz-types/nominal.test
@@ -3,20 +3,20 @@
;; CHECK: (type $0 (struct_subtype (field (ref null $9) (ref $5)) data))
;; CHECK-NEXT: (type $1 (func_subtype (param (rtt 0 $8)) func))
;; CHECK-NEXT: (type $2 (struct_subtype (field (mut (rtt $19)) (ref $4)) data))
-;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $2))
-;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut (ref $13))) $2))
-;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $3))
-;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $3))
-;; CHECK-NEXT: (type $7 (struct_subtype (field (ref null $9) (ref $5) eqref (mut (ref null $3)) (mut (rtt $18)) dataref) $0))
-;; CHECK-NEXT: (type $8 (struct_subtype (field (ref $9) (ref $5) (rtt 2 $1) (mut (rtt $17)) (mut (rtt i31)) (rtt $8)) $0))
-;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64) (rtt 2 $15)) $6))
-;; CHECK-NEXT: (type $10 (struct_subtype (field (ref null $9) (ref $5)) $0))
-;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (rtt $19)) (ref $4)) $2))
+;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $2))
+;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (rtt $19)) (ref $4)) $2))
+;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $3))
+;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $3))
+;; CHECK-NEXT: (type $7 (struct_subtype (field (ref null $9) (ref $5)) $0))
+;; CHECK-NEXT: (type $8 (struct_subtype (field (ref null $9) (ref $5)) $0))
+;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $6))
+;; CHECK-NEXT: (type $10 (struct_subtype (field (ref $9) (ref $5) i32) $0))
+;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut f64) i32 (mut f32)) $2))
;; CHECK-NEXT: (type $12 (struct_subtype (field (ref null $9) (ref $5)) $0))
-;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $6))
-;; CHECK-NEXT: (type $14 (struct_subtype (field (ref null $9) (ref $5)) $10))
+;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 v128 (mut v128)) $6))
+;; CHECK-NEXT: (type $14 (struct_subtype (field (ref $9) (ref $5) i32) $10))
;; CHECK-NEXT: (type $15 (func_subtype (param (rtt 0 $8)) $1))
-;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (rtt $19)) (ref $4) v128) $2))
-;; CHECK-NEXT: (type $17 (struct_subtype (field (ref null $9) (ref $5)) $14))
+;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut i16) i64 (mut (rtt 0 i31))) $2))
+;; CHECK-NEXT: (type $17 (struct_subtype (field (ref $9) (ref $5) i32) $14))
;; CHECK-NEXT: (type $18 (struct_subtype (field (ref null $9) (ref $5)) $12))
;; CHECK-NEXT: (type $19 (func_subtype (param (rtt 0 $8)) $15))
diff --git a/test/lit/fuzz-types/structural.test b/test/lit/fuzz-types/structural.test
index a7b38edb4..e0aa75e9e 100644
--- a/test/lit/fuzz-types/structural.test
+++ b/test/lit/fuzz-types/structural.test
@@ -1,22 +1,22 @@
;; RUN: wasm-fuzz-types --structural -v --seed=0 | filecheck %s
-;; CHECK: (type $0 (struct (field (ref null $9) (ref $3))))
-;; CHECK-NEXT: (type $1 (func (param (rtt 0 $8))))
-;; CHECK-NEXT: (type $2 (struct (field (mut (rtt $1)) (ref $4))))
-;; CHECK-NEXT: (type $3 (struct (field (mut (rtt $1)) (ref $4) i64 (mut (ref null $2)) (mut i64))))
-;; CHECK-NEXT: (type $4 (struct (field (mut (rtt $1)) (ref $4) (mut (ref $3)))))
+;; CHECK: (type $0 (struct (field (ref null $3) (ref $3))))
+;; CHECK-NEXT: (type $1 (func (param (rtt 0 $0))))
+;; CHECK-NEXT: (type $2 (struct (field (mut (rtt $1)) (ref $2))))
+;; CHECK-NEXT: (type $3 (struct (field (mut (rtt $1)) (ref $2) i64 v128 (mut v128))))
+;; CHECK-NEXT: (type $4 identical to $2)
;; CHECK-NEXT: (type $5 identical to $3)
;; CHECK-NEXT: (type $6 identical to $3)
-;; CHECK-NEXT: (type $7 (struct (field (ref null $9) (ref $3) eqref (mut (ref null $3)) (mut (rtt $0)) dataref)))
-;; CHECK-NEXT: (type $8 (struct (field (ref $9) (ref $3) (rtt 2 $1) (mut (rtt $0)) (mut (rtt i31)) (rtt $8))))
-;; CHECK-NEXT: (type $9 (struct (field (mut (rtt $1)) (ref $4) i64 (mut (ref null $2)) (mut i64) (rtt 2 $1))))
-;; CHECK-NEXT: (type $10 identical to $0)
-;; CHECK-NEXT: (type $11 identical to $2)
+;; CHECK-NEXT: (type $7 identical to $0)
+;; CHECK-NEXT: (type $8 identical to $0)
+;; CHECK-NEXT: (type $9 identical to $3)
+;; CHECK-NEXT: (type $10 (struct (field (ref $3) (ref $3) i32)))
+;; CHECK-NEXT: (type $11 (struct (field (mut (rtt $1)) (ref $2) (mut f64) i32 (mut f32))))
;; CHECK-NEXT: (type $12 identical to $0)
;; CHECK-NEXT: (type $13 identical to $3)
-;; CHECK-NEXT: (type $14 identical to $0)
+;; CHECK-NEXT: (type $14 identical to $10)
;; CHECK-NEXT: (type $15 identical to $1)
-;; CHECK-NEXT: (type $16 (struct (field (mut (rtt $1)) (ref $4) v128)))
-;; CHECK-NEXT: (type $17 identical to $0)
+;; CHECK-NEXT: (type $16 (struct (field (mut (rtt $1)) (ref $2) (mut i16) i64 (mut (rtt 0 i31)))))
+;; CHECK-NEXT: (type $17 identical to $10)
;; CHECK-NEXT: (type $18 identical to $0)
;; CHECK-NEXT: (type $19 identical to $1)
diff --git a/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast b/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast
index e736253f6..28c42e1fa 100644
--- a/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast
+++ b/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast
@@ -16,12 +16,6 @@
;; CHECK: (type $i32_i32_anyref_=>_anyref (func (param i32 i32 anyref) (result anyref)))
- ;; CHECK: (type $i32_i32_eqref_=>_eqref (func (param i32 i32 eqref) (result eqref)))
-
- ;; CHECK: (type $i32_i32_i31ref_=>_i31ref (func (param i32 i32 i31ref) (result i31ref)))
-
- ;; CHECK: (type $i32_i32_dataref_=>_dataref (func (param i32 i32 dataref) (result dataref)))
-
;; CHECK: (type $i32_i32_v128_=>_v128 (func (param i32 i32 v128) (result v128)))
;; CHECK: (type $none_=>_none (func))
@@ -50,18 +44,6 @@
;; CHECK: (import "env" "set_anyref" (func $set_anyref (param i32 i32 anyref) (result anyref)))
- ;; CHECK: (import "env" "get_eqref" (func $get_eqref (param i32 i32 eqref) (result eqref)))
-
- ;; CHECK: (import "env" "set_eqref" (func $set_eqref (param i32 i32 eqref) (result eqref)))
-
- ;; CHECK: (import "env" "get_i31ref" (func $get_i31ref (param i32 i32 i31ref) (result i31ref)))
-
- ;; CHECK: (import "env" "set_i31ref" (func $set_i31ref (param i32 i32 i31ref) (result i31ref)))
-
- ;; CHECK: (import "env" "get_dataref" (func $get_dataref (param i32 i32 dataref) (result dataref)))
-
- ;; CHECK: (import "env" "set_dataref" (func $set_dataref (param i32 i32 dataref) (result dataref)))
-
;; CHECK: (import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128)))
;; CHECK: (import "env" "set_v128" (func $set_v128 (param i32 i32 v128) (result v128)))
diff --git a/test/lit/strings.wast b/test/lit/strings.wast
index c807ac000..03e87e562 100644
--- a/test/lit/strings.wast
+++ b/test/lit/strings.wast
@@ -5,17 +5,17 @@
;; RUN: foreach %s %t wasm-opt --enable-strings --enable-reference-types --enable-gc --roundtrip -S -o - | filecheck %s
(module
- ;; CHECK: (type $ref?|string|_=>_none (func (param stringref)))
+ ;; CHECK: (type $stringref_=>_none (func (param stringref)))
- ;; CHECK: (type $ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter)))
+ ;; CHECK: (type $stringref_stringview_wtf8_stringview_wtf16_stringview_iter_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter)))
- ;; CHECK: (type $ref?|string|_ref?|string|_=>_none (func (param stringref stringref)))
+ ;; CHECK: (type $stringref_stringref_=>_none (func (param stringref stringref)))
- ;; CHECK: (type $ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_ref|string|_ref|stringview_wtf8|_ref|stringview_wtf16|_ref|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter stringref stringview_wtf8 stringview_wtf16 stringview_iter (ref string) (ref stringview_wtf8) (ref stringview_wtf16) (ref stringview_iter))))
+ ;; CHECK: (type $stringref_stringview_wtf8_stringview_wtf16_stringview_iter_stringref_stringview_wtf8_stringview_wtf16_stringview_iter_ref|string|_ref|stringview_wtf8|_ref|stringview_wtf16|_ref|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter stringref stringview_wtf8 stringview_wtf16 stringview_iter (ref string) (ref stringview_wtf8) (ref stringview_wtf16) (ref stringview_iter))))
;; CHECK: (type $none_=>_none (func))
- ;; CHECK: (type $ref?|stringview_wtf16|_=>_none (func (param stringview_wtf16)))
+ ;; CHECK: (type $stringview_wtf16_=>_none (func (param stringview_wtf16)))
;; CHECK: (type $ref|$array|_=>_none (func (param (ref $array))))
diff --git a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
index fa88cc5ef..ad0779876 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,42 +1,40 @@
total
- [exports] : 8
- [funcs] : 9
+ [exports] : 10
+ [funcs] : 12
[globals] : 6
[imports] : 5
[memory-data] : 22
[table-data] : 4
[tables] : 1
[tags] : 0
- [total] : 650
- [vars] : 12
+ [total] : 549
+ [vars] : 22
AtomicCmpxchg : 1
AtomicFence : 1
- AtomicNotify : 1
- Binary : 83
- Block : 72
- Break : 5
+ Binary : 71
+ Block : 60
+ Break : 2
Call : 23
- CallRef : 4
- Const : 141
+ CallRef : 2
+ Const : 119
Drop : 3
- GlobalGet : 39
- GlobalSet : 21
- I31New : 10
- If : 31
- Load : 24
- LocalGet : 49
- LocalSet : 25
- Loop : 11
- Nop : 9
- RefEq : 2
- RefFunc : 12
+ GlobalGet : 35
+ GlobalSet : 19
+ I31New : 6
+ If : 25
+ Load : 16
+ LocalGet : 45
+ LocalSet : 23
+ Loop : 6
+ Nop : 7
+ RefFunc : 11
RefIs : 1
RefNull : 2
Return : 27
SIMDExtract : 1
- Select : 2
- Store : 2
- StructNew : 4
- TupleExtract : 2
+ Select : 1
+ Store : 3
+ StructNew : 2
TupleMake : 7
- Unary : 35
+ Unary : 29
+ Unreachable : 1