summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp15
-rw-r--r--src/binaryen-c.h15
-rw-r--r--src/ir/module-utils.cpp2
-rw-r--r--src/passes/GUFA.cpp6
-rw-r--r--src/passes/OptimizeInstructions.cpp19
-rw-r--r--src/passes/Print.cpp5
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-builder.h4
-rw-r--r--src/wasm-delegations-fields.def2
-rw-r--r--src/wasm.h5
-rw-r--r--src/wasm/wasm-binary.cpp9
-rw-r--r--src/wasm/wasm-s-parser.cpp12
-rw-r--r--src/wasm/wasm-stack.cpp8
-rw-r--r--src/wasm/wasm-validator.cpp2
14 files changed, 64 insertions, 44 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 3a42b6f25..b26ec3389 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -1742,10 +1742,9 @@ BinaryenExpressionRef BinaryenCallRef(BinaryenModuleRef module,
}
BinaryenExpressionRef BinaryenRefTest(BinaryenModuleRef module,
BinaryenExpressionRef ref,
- BinaryenHeapType intendedType) {
+ BinaryenType castType) {
return static_cast<Expression*>(
- Builder(*(Module*)module)
- .makeRefTest((Expression*)ref, HeapType(intendedType)));
+ Builder(*(Module*)module).makeRefTest((Expression*)ref, Type(castType)));
}
BinaryenExpressionRef BinaryenRefCast(BinaryenModuleRef module,
BinaryenExpressionRef ref,
@@ -4062,16 +4061,16 @@ void BinaryenRefTestSetRef(BinaryenExpressionRef expr,
assert(refExpr);
static_cast<RefTest*>(expression)->ref = (Expression*)refExpr;
}
-BinaryenHeapType BinaryenRefTestGetIntendedType(BinaryenExpressionRef expr) {
+BinaryenType BinaryenRefTestGetCastType(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<RefTest>());
- return static_cast<RefTest*>(expression)->intendedType.getID();
+ return static_cast<RefTest*>(expression)->castType.getID();
}
-void BinaryenRefTestSetIntendedType(BinaryenExpressionRef expr,
- BinaryenHeapType intendedType) {
+void BinaryenRefTestSetCastType(BinaryenExpressionRef expr,
+ BinaryenType castType) {
auto* expression = (Expression*)expr;
assert(expression->is<RefTest>());
- static_cast<RefTest*>(expression)->intendedType = HeapType(intendedType);
+ static_cast<RefTest*>(expression)->castType = Type(castType);
}
// RefCast
BinaryenExpressionRef BinaryenRefCastGetRef(BinaryenExpressionRef expr) {
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 9fc0d8b04..7894c1c24 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -1038,10 +1038,9 @@ BinaryenCallRef(BinaryenModuleRef module,
BinaryenIndex numOperands,
BinaryenType type,
bool isReturn);
-BINARYEN_API BinaryenExpressionRef
-BinaryenRefTest(BinaryenModuleRef module,
- BinaryenExpressionRef ref,
- BinaryenHeapType intendedType);
+BINARYEN_API BinaryenExpressionRef BinaryenRefTest(BinaryenModuleRef module,
+ BinaryenExpressionRef ref,
+ BinaryenType castType);
BINARYEN_API BinaryenExpressionRef BinaryenRefCast(BinaryenModuleRef module,
BinaryenExpressionRef ref,
BinaryenType type);
@@ -2362,10 +2361,10 @@ BINARYEN_API BinaryenExpressionRef
BinaryenRefTestGetRef(BinaryenExpressionRef expr);
BINARYEN_API void BinaryenRefTestSetRef(BinaryenExpressionRef expr,
BinaryenExpressionRef refExpr);
-BINARYEN_API BinaryenHeapType
-BinaryenRefTestGetIntendedType(BinaryenExpressionRef expr);
-BINARYEN_API void BinaryenRefTestSetIntendedType(BinaryenExpressionRef expr,
- BinaryenHeapType intendedType);
+BINARYEN_API BinaryenType
+BinaryenRefTestGetCastType(BinaryenExpressionRef expr);
+BINARYEN_API void BinaryenRefTestSetCastType(BinaryenExpressionRef expr,
+ BinaryenType intendedType);
// RefCast
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp
index f7ba7d776..482753b87 100644
--- a/src/ir/module-utils.cpp
+++ b/src/ir/module-utils.cpp
@@ -73,7 +73,7 @@ struct CodeScanner
} else if (auto* cast = curr->dynCast<RefCast>()) {
counts.note(cast->type);
} else if (auto* cast = curr->dynCast<RefTest>()) {
- counts.note(cast->intendedType);
+ counts.note(cast->castType);
} else if (auto* cast = curr->dynCast<BrOn>()) {
if (cast->op == BrOnCast || cast->op == BrOnCastFail) {
counts.note(cast->intendedType);
diff --git a/src/passes/GUFA.cpp b/src/passes/GUFA.cpp
index 4250c76e9..137ffda17 100644
--- a/src/passes/GUFA.cpp
+++ b/src/passes/GUFA.cpp
@@ -237,10 +237,8 @@ struct GUFAOptimizer
if (refType.isRef()) {
// We have some knowledge of the type here. Use that to optimize: RefTest
// returns 1 if the input is of a subtype of the intended type, that is,
- // we are looking for a type in that cone of types. (Note that we use a
- // non-nullable cone since only a non-null can pass the test.)
- auto intendedContents =
- PossibleContents::fullConeType(Type(curr->intendedType, NonNullable));
+ // we are looking for a type in that cone of types.
+ auto intendedContents = PossibleContents::fullConeType(curr->castType);
auto optimize = [&](int32_t result) {
auto* last = Builder(*getModule()).makeConst(Literal(int32_t(result)));
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index ec714c1e1..097e0299a 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -2037,20 +2037,29 @@ struct OptimizeInstructions
Builder builder(*getModule());
+ if (curr->ref->type.isNull()) {
+ // The input is null, so we know whether this will succeed or fail.
+ int32_t result = curr->castType.isNullable() ? 1 : 0;
+ replaceCurrent(builder.makeBlock(
+ {builder.makeDrop(curr->ref), builder.makeConst(int32_t(result))}));
+ return;
+ }
+
auto refType = curr->ref->type.getHeapType();
- auto intendedType = curr->intendedType;
+ auto intendedType = curr->castType.getHeapType();
// See above in RefCast.
- if (!canBeCastTo(refType, intendedType)) {
+ if (!canBeCastTo(refType, intendedType) &&
+ (curr->castType.isNonNullable() || curr->ref->type.isNonNullable())) {
// This test cannot succeed, and will definitely return 0.
replaceCurrent(builder.makeSequence(builder.makeDrop(curr->ref),
builder.makeConst(int32_t(0))));
return;
}
- if (curr->ref->type.isNonNullable() &&
- HeapType::isSubType(refType, intendedType)) {
- // This static test will definitely succeed.
+ if (HeapType::isSubType(refType, intendedType) &&
+ (curr->castType.isNullable() || curr->ref->type.isNonNullable())) {
+ // This test will definitely succeed and return 1.
replaceCurrent(builder.makeBlock(
{builder.makeDrop(curr->ref), builder.makeConst(int32_t(1))}));
return;
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 2cd021b6f..d2fbf24d8 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2110,7 +2110,10 @@ struct PrintExpressionContents
}
void visitRefTest(RefTest* curr) {
printMedium(o, "ref.test ");
- printHeapType(o, curr->intendedType, wasm);
+ if (curr->castType.isNullable()) {
+ printMedium(o, "null ");
+ }
+ printHeapType(o, curr->castType.getHeapType(), wasm);
}
void visitRefCast(RefCast* curr) {
if (printUnreachableReplacement(curr)) {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index e4abe4787..996d9ab4c 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1125,11 +1125,11 @@ enum ASTNodes {
RefCastStatic = 0x45,
BrOnCastStatic = 0x46,
BrOnCastStaticFail = 0x47,
- RefCastNop = 0x48,
- // TODO: RefTestNull
+ RefTestNull = 0x48,
RefCastNull = 0x49,
// TODO: BrOnCastNull
// TODO: BrOnCastFailNull
+ RefCastNop = 0x4c,
RefIsFunc = 0x50,
RefIsData = 0x51,
RefIsI31 = 0x52,
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 173e5976f..58a3a3188 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -868,10 +868,10 @@ public:
ret->finalize();
return ret;
}
- RefTest* makeRefTest(Expression* ref, HeapType intendedType) {
+ RefTest* makeRefTest(Expression* ref, Type castType) {
auto* ret = wasm.allocator.alloc<RefTest>();
ret->ref = ref;
- ret->intendedType = intendedType;
+ ret->castType = castType;
ret->finalize();
return ret;
}
diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def
index dc0a13f41..9c966faec 100644
--- a/src/wasm-delegations-fields.def
+++ b/src/wasm-delegations-fields.def
@@ -614,7 +614,7 @@ switch (DELEGATE_ID) {
}
case Expression::Id::RefTestId: {
DELEGATE_START(RefTest);
- DELEGATE_FIELD_HEAPTYPE(RefTest, intendedType);
+ DELEGATE_FIELD_TYPE(RefTest, castType);
DELEGATE_FIELD_CHILD(RefTest, ref);
DELEGATE_END(RefTest);
break;
diff --git a/src/wasm.h b/src/wasm.h
index 3a44556d5..f1dcd7b46 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1522,12 +1522,11 @@ public:
Expression* ref;
- HeapType intendedType;
+ Type castType;
void finalize();
- // TODO: Support ref.test null as well.
- Type getCastType() { return Type(intendedType, NonNullable); }
+ Type getCastType() { return castType; }
};
class RefCast : public SpecificExpression<Expression::RefCastId> {
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 0160ffaf6..386f89060 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -6893,11 +6893,14 @@ bool WasmBinaryBuilder::maybeVisitI31Get(Expression*& out, uint32_t code) {
}
bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) {
- if (code == BinaryConsts::RefTestStatic || code == BinaryConsts::RefTest) {
+ if (code == BinaryConsts::RefTestStatic || code == BinaryConsts::RefTest ||
+ code == BinaryConsts::RefTestNull) {
bool legacy = code == BinaryConsts::RefTestStatic;
- auto intendedType = legacy ? getIndexedHeapType() : getHeapType();
+ auto castType = legacy ? getIndexedHeapType() : getHeapType();
+ auto nullability =
+ (code == BinaryConsts::RefTestNull) ? Nullable : NonNullable;
auto* ref = popNonVoidExpression();
- out = Builder(wasm).makeRefTest(ref, intendedType);
+ out = Builder(wasm).makeRefTest(ref, Type(castType, nullability));
return true;
}
return false;
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index cf287d8a1..4fdc29a66 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2776,9 +2776,15 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) {
}
Expression* SExpressionWasmBuilder::makeRefTest(Element& s) {
- auto heapType = parseHeapType(*s[1]);
- auto* ref = parseExpression(*s[2]);
- return Builder(wasm).makeRefTest(ref, heapType);
+ int i = 1;
+ auto nullability = NonNullable;
+ if (s[0]->str().str != "ref.test_static" && s[1]->str().str == "null") {
+ nullability = Nullable;
+ ++i;
+ }
+ auto heapType = parseHeapType(*s[i++]);
+ auto* ref = parseExpression(*s[i++]);
+ return Builder(wasm).makeRefTest(ref, Type(heapType, nullability));
}
Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 911447b48..e24060f2a 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2025,8 +2025,12 @@ void BinaryInstWriter::visitCallRef(CallRef* curr) {
void BinaryInstWriter::visitRefTest(RefTest* curr) {
o << int8_t(BinaryConsts::GCPrefix);
- o << U32LEB(BinaryConsts::RefTest);
- parent.writeHeapType(curr->intendedType);
+ if (curr->castType.isNullable()) {
+ o << U32LEB(BinaryConsts::RefTestNull);
+ } else {
+ o << U32LEB(BinaryConsts::RefTest);
+ }
+ parent.writeHeapType(curr->castType.getHeapType());
}
void BinaryInstWriter::visitRefCast(RefCast* curr) {
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index b102ecb1c..68fb58ec4 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2513,7 +2513,7 @@ void FunctionValidator::visitRefTest(RefTest* curr) {
return;
}
shouldBeEqual(
- curr->intendedType.getBottom(),
+ curr->castType.getHeapType().getBottom(),
curr->ref->type.getHeapType().getBottom(),
curr,
"ref.test target type and ref type must have a common supertype");