summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binaryen-c.cpp3
-rw-r--r--src/binaryen-c.h3
-rw-r--r--src/gen-s-parser.inc12
-rw-r--r--src/ir/gc-type-utils.h22
-rw-r--r--src/js/binaryen.js-post.js12
-rw-r--r--src/passes/OptimizeInstructions.cpp28
-rw-r--r--src/passes/Print.cpp26
-rw-r--r--src/wasm-binary.h1
-rw-r--r--src/wasm-interpreter.h21
-rw-r--r--src/wasm-s-parser.h4
-rw-r--r--src/wasm.h3
-rw-r--r--src/wasm/wasm-binary.cpp37
-rw-r--r--src/wasm/wasm-s-parser.cpp22
-rw-r--r--src/wasm/wasm-stack.cpp26
-rw-r--r--src/wasm/wasm.cpp9
-rw-r--r--src/wasm/wat-parser.cpp7
16 files changed, 91 insertions, 145 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 416c8d45b..e37270f61 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -1009,9 +1009,6 @@ BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void) {
}
BinaryenOp BinaryenSwizzleVecI8x16(void) { return SwizzleVecI8x16; }
BinaryenOp BinaryenRefAsNonNull(void) { return RefAsNonNull; }
-BinaryenOp BinaryenRefAsFunc(void) { return RefAsFunc; }
-BinaryenOp BinaryenRefAsData(void) { return RefAsData; }
-BinaryenOp BinaryenRefAsI31(void) { return RefAsI31; }
BinaryenOp BinaryenRefAsExternInternalize(void) { return ExternInternalize; }
BinaryenOp BinaryenRefAsExternExternalize(void) { return ExternExternalize; }
BinaryenOp BinaryenBrOnNull(void) { return BrOnNull; }
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 2c861a141..b9f78e2a7 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -671,9 +671,6 @@ BINARYEN_API BinaryenOp BinaryenDemoteZeroVecF64x2ToVecF32x4(void);
BINARYEN_API BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void);
BINARYEN_API BinaryenOp BinaryenSwizzleVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenRefAsNonNull(void);
-BINARYEN_API BinaryenOp BinaryenRefAsFunc(void);
-BINARYEN_API BinaryenOp BinaryenRefAsData(void);
-BINARYEN_API BinaryenOp BinaryenRefAsI31(void);
BINARYEN_API BinaryenOp BinaryenRefAsExternInternalize(void);
BINARYEN_API BinaryenOp BinaryenRefAsExternExternalize(void);
BINARYEN_API BinaryenOp BinaryenBrOnNull(void);
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 70644827c..dbf3b71bf 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -3000,13 +3000,13 @@ switch (buf[0]) {
case 'a': {
switch (buf[7]) {
case 'd':
- if (op == "ref.as_data"sv) { return makeRefAs(s, RefAsData); }
+ if (op == "ref.as_data"sv) { return makeRefCast(s, Type(HeapType::data, NonNullable)); }
goto parse_error;
case 'f':
- if (op == "ref.as_func"sv) { return makeRefAs(s, RefAsFunc); }
+ if (op == "ref.as_func"sv) { return makeRefCast(s, Type(HeapType::func, NonNullable)); }
goto parse_error;
case 'i':
- if (op == "ref.as_i31"sv) { return makeRefAs(s, RefAsI31); }
+ if (op == "ref.as_i31"sv) { return makeRefCast(s, Type(HeapType::i31, NonNullable)); }
goto parse_error;
case 'n':
if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); }
@@ -8599,21 +8599,21 @@ switch (buf[0]) {
switch (buf[7]) {
case 'd':
if (op == "ref.as_data"sv) {
- auto ret = makeRefAs(ctx, pos, RefAsData);
+ auto ret = makeRefCast(ctx, pos, Type(HeapType::data, NonNullable));
CHECK_ERR(ret);
return *ret;
}
goto parse_error;
case 'f':
if (op == "ref.as_func"sv) {
- auto ret = makeRefAs(ctx, pos, RefAsFunc);
+ auto ret = makeRefCast(ctx, pos, Type(HeapType::func, NonNullable));
CHECK_ERR(ret);
return *ret;
}
goto parse_error;
case 'i':
if (op == "ref.as_i31"sv) {
- auto ret = makeRefAs(ctx, pos, RefAsI31);
+ auto ret = makeRefCast(ctx, pos, Type(HeapType::i31, NonNullable));
CHECK_ERR(ret);
return *ret;
}
diff --git a/src/ir/gc-type-utils.h b/src/ir/gc-type-utils.h
index c8f2b26af..318b1b3a3 100644
--- a/src/ir/gc-type-utils.h
+++ b/src/ir/gc-type-utils.h
@@ -119,28 +119,6 @@ inline EvaluationResult evaluateKindCheck(Expression* curr) {
WASM_UNREACHABLE("unhandled BrOn");
}
child = br->ref;
- } else if (auto* as = curr->dynCast<RefAs>()) {
- switch (as->op) {
- // We don't check nullability here.
- case RefAsNonNull:
- return Unknown;
- case RefAsFunc:
- expected = Func;
- break;
- case RefAsData:
- expected = Data;
- break;
- case RefAsI31:
- expected = I31;
- break;
- case ExternInternalize:
- case ExternExternalize:
- // These instructions can never be removed.
- return Unknown;
- default:
- WASM_UNREACHABLE("unhandled RefAs");
- }
- child = as->value;
} else {
WASM_UNREACHABLE("invalid input to evaluateKindCheck");
}
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 2a08c5e5a..da121e23a 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -550,9 +550,6 @@ function initializeConstants() {
'PromoteLowVecF32x4ToVecF64x2',
'SwizzleVecI8x16',
'RefAsNonNull',
- 'RefAsFunc',
- 'RefAsData',
- 'RefAsI31',
'RefAsExternInternalize',
'RefAsExternExternalize',
'BrOnNull',
@@ -2345,15 +2342,6 @@ function wrapModule(module, self = {}) {
'as_non_null'(value) {
return Module['_BinaryenRefAs'](module, Module['RefAsNonNull'], value);
},
- 'as_func'(value) {
- return Module['_BinaryenRefAs'](module, Module['RefAsFunc'], value);
- },
- 'as_data'(value) {
- return Module['_BinaryenRefAs'](module, Module['RefAsData'], value);
- },
- 'as_i31'(value) {
- return Module['_BinaryenRefAs'](module, Module['RefAsI31'], value);
- },
'func'(func, type) {
return preserveStack(() => Module['_BinaryenRefFunc'](module, strToStack(func), type));
},
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 884afcdd4..e8c6dc1fe 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -2118,35 +2118,13 @@ struct OptimizeInstructions
if (curr->op == ExternExternalize || curr->op == ExternInternalize) {
// We can't optimize these. Even removing a non-null cast is not valid as
- // they allow nulls to filter through, unlike other RefAs*
+ // they allow nulls to filter through, unlike other RefAs*.
return;
}
+ assert(curr->op == RefAsNonNull);
skipNonNullCast(curr->value);
-
- // Check if the type is the kind we are checking for.
- auto result = GCTypeUtils::evaluateKindCheck(curr);
-
- if (result == GCTypeUtils::Success) {
- // We know the kind is correct, so all that is left is a check for
- // non-nullability, which we do lower down.
- curr->op = RefAsNonNull;
- } else if (result == GCTypeUtils::Failure) {
- // This is the wrong kind, so it will trap. The binaryen optimizer does
- // not differentiate traps, so we can perform a replacement here. We
- // replace 2 bytes of ref.as_* with one byte of unreachable and one of a
- // drop, which is no worse, and the value and the drop can be optimized
- // out later if the value has no side effects.
- Builder builder(*getModule());
- // Make sure to emit a block with the same type as us; leave updating
- // types for other passes.
- replaceCurrent(builder.makeBlock(
- {builder.makeDrop(curr->value), builder.makeUnreachable()},
- curr->type));
- return;
- }
-
- if (curr->op == RefAsNonNull && !curr->value->type.isNullable()) {
+ if (!curr->value->type.isNullable()) {
replaceCurrent(curr->value);
return;
}
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 12c185e69..e0d9a46a3 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2122,6 +2122,23 @@ struct PrintExpressionContents
if (curr->safety == RefCast::Unsafe) {
printMedium(o, "ref.cast_nop ");
} else {
+ // TODO: These instructions are deprecated. Remove them.
+ if (auto type = curr->type.getHeapType();
+ type.isBasic() && curr->type.isNonNullable()) {
+ switch (type.getBasic()) {
+ case HeapType::func:
+ printMedium(o, "ref.as_func");
+ return;
+ case HeapType::data:
+ printMedium(o, "ref.as_data");
+ return;
+ case HeapType::i31:
+ printMedium(o, "ref.as_i31");
+ return;
+ default:
+ break;
+ }
+ }
if (curr->type.isNullable()) {
printMedium(o, "ref.cast null ");
} else {
@@ -2329,15 +2346,6 @@ struct PrintExpressionContents
case RefAsNonNull:
printMedium(o, "ref.as_non_null");
break;
- case RefAsFunc:
- printMedium(o, "ref.as_func");
- break;
- case RefAsData:
- printMedium(o, "ref.as_data");
- break;
- case RefAsI31:
- printMedium(o, "ref.as_i31");
- break;
case ExternInternalize:
printMedium(o, "extern.internalize");
break;
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 1a3e5c82b..b2e1ef0c6 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1748,6 +1748,7 @@ public:
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
void visitCallRef(CallRef* curr);
+ void visitRefAsCast(RefCast* curr, uint32_t code);
void visitRefAs(RefAs* curr, uint8_t code);
[[noreturn]] void throwError(std::string text);
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 104f06585..43b001f35 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1787,29 +1787,12 @@ public:
switch (curr->op) {
case RefAsNonNull:
// We've already checked for a null.
- break;
- case RefAsFunc:
- if (!value.type.isFunction()) {
- trap("not a func");
- }
- break;
- case RefAsData:
- if (!value.isData()) {
- trap("not a data");
- }
- break;
- case RefAsI31:
- if (value.type.getHeapType() != HeapType::i31) {
- trap("not an i31");
- }
- break;
+ return value;
case ExternInternalize:
case ExternExternalize:
WASM_UNREACHABLE("unimplemented extern conversion");
- default:
- WASM_UNREACHABLE("unimplemented ref.as_*");
}
- return value;
+ WASM_UNREACHABLE("unimplemented ref.as_*");
}
Flow visitStringNew(StringNew* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitStringConst(StringConst* curr) { WASM_UNREACHABLE("unimp"); }
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 6ae3e57be..013730c52 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -285,7 +285,8 @@ private:
Expression* makeI31Get(Element& s, bool signed_);
Expression* makeRefTest(Element& s,
std::optional<Type> castType = std::nullopt);
- Expression* makeRefCast(Element& s);
+ Expression* makeRefCast(Element& s,
+ std::optional<Type> castType = std::nullopt);
Expression* makeRefCastNop(Element& s);
Expression* makeBrOnNull(Element& s, bool onFail = false);
Expression*
@@ -302,6 +303,7 @@ private:
Expression* makeArrayLen(Element& s);
Expression* makeArrayCopy(Element& s);
Expression* makeRefAs(Element& s, RefAsOp op);
+ Expression* makeRefAsNonNull(Element& s);
Expression* makeStringNew(Element& s, StringNewOp op);
Expression* makeStringConst(Element& s);
Expression* makeStringMeasure(Element& s, StringMeasureOp op);
diff --git a/src/wasm.h b/src/wasm.h
index 7b75ec3b8..f7683e6bb 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -559,9 +559,6 @@ enum SIMDTernaryOp {
enum RefAsOp {
RefAsNonNull,
- RefAsFunc,
- RefAsData,
- RefAsI31,
ExternInternalize,
ExternExternalize,
};
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b1f4b8907..767e0c2ab 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -4032,8 +4032,12 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
}
if (opcode == BinaryConsts::RefAsFunc ||
opcode == BinaryConsts::RefAsData ||
- opcode == BinaryConsts::RefAsI31 ||
- opcode == BinaryConsts::ExternInternalize ||
+ opcode == BinaryConsts::RefAsI31) {
+ visitRefAsCast((curr = allocator.alloc<RefCast>())->cast<RefCast>(),
+ opcode);
+ break;
+ }
+ if (opcode == BinaryConsts::ExternInternalize ||
opcode == BinaryConsts::ExternExternalize) {
visitRefAs((curr = allocator.alloc<RefAs>())->cast<RefAs>(), opcode);
break;
@@ -6910,6 +6914,26 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) {
return false;
}
+void WasmBinaryBuilder::visitRefAsCast(RefCast* curr, uint32_t code) {
+ // TODO: These instructions are deprecated. Remove them.
+ switch (code) {
+ case BinaryConsts::RefAsFunc:
+ curr->type = Type(HeapType::func, NonNullable);
+ break;
+ case BinaryConsts::RefAsData:
+ curr->type = Type(HeapType::data, NonNullable);
+ break;
+ case BinaryConsts::RefAsI31:
+ curr->type = Type(HeapType::i31, NonNullable);
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected ref.as*");
+ }
+ curr->ref = popNonVoidExpression();
+ curr->safety = RefCast::Safe;
+ curr->finalize();
+}
+
bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) {
if (code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCast ||
code == BinaryConsts::RefCastNull || code == BinaryConsts::RefCastNop) {
@@ -7439,15 +7463,6 @@ void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
case BinaryConsts::RefAsNonNull:
curr->op = RefAsNonNull;
break;
- case BinaryConsts::RefAsFunc:
- curr->op = RefAsFunc;
- break;
- case BinaryConsts::RefAsData:
- curr->op = RefAsData;
- break;
- case BinaryConsts::RefAsI31:
- curr->op = RefAsI31;
- break;
case BinaryConsts::ExternInternalize:
curr->op = ExternInternalize;
break;
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 4f725d48b..03dba223b 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2790,27 +2790,27 @@ Expression* SExpressionWasmBuilder::makeRefTest(Element& s,
return Builder(wasm).makeRefTest(ref, *castType);
}
-Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
+Expression* SExpressionWasmBuilder::makeRefCast(Element& s,
+ std::optional<Type> castType) {
int i = 1;
- Nullability nullability;
bool legacy = false;
- if (s[0]->str().str == "ref.cast_static") {
- legacy = true;
- } else {
- nullability = NonNullable;
- if (s[i]->str().str == "null") {
+ if (!castType) {
+ Nullability nullability = NonNullable;
+ if (s[0]->str().str == "ref.cast_static") {
+ legacy = true;
+ } else if (s[i]->str().str == "null") {
nullability = Nullable;
++i;
}
+ auto type = parseHeapType(*s[i++]);
+ castType = Type(type, nullability);
}
- auto heapType = parseHeapType(*s[i++]);
auto* ref = parseExpression(*s[i++]);
if (legacy) {
// Legacy polymorphic behavior.
- nullability = ref->type.getNullability();
+ castType = Type(castType->getHeapType(), ref->type.getNullability());
}
- auto type = Type(heapType, nullability);
- return Builder(wasm).makeRefCast(ref, type, RefCast::Safe);
+ return Builder(wasm).makeRefCast(ref, *castType, RefCast::Safe);
}
Expression* SExpressionWasmBuilder::makeRefCastNop(Element& s) {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 82c7c511f..c4e1a863c 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2041,6 +2041,23 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) {
o << U32LEB(BinaryConsts::RefCastNop);
parent.writeIndexedHeapType(curr->type.getHeapType());
} else {
+ // TODO: These instructions are deprecated. Remove them.
+ if (auto type = curr->type.getHeapType();
+ type.isBasic() && curr->type.isNonNullable()) {
+ switch (type.getBasic()) {
+ case HeapType::func:
+ o << U32LEB(BinaryConsts::RefAsFunc);
+ return;
+ case HeapType::data:
+ o << U32LEB(BinaryConsts::RefAsData);
+ return;
+ case HeapType::i31:
+ o << U32LEB(BinaryConsts::RefAsI31);
+ return;
+ default:
+ break;
+ }
+ }
if (curr->type.isNullable()) {
o << U32LEB(BinaryConsts::RefCastNull);
} else {
@@ -2244,15 +2261,6 @@ void BinaryInstWriter::visitRefAs(RefAs* curr) {
case RefAsNonNull:
o << int8_t(BinaryConsts::RefAsNonNull);
break;
- case RefAsFunc:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsFunc);
- break;
- case RefAsData:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsData);
- break;
- case RefAsI31:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsI31);
- break;
case ExternInternalize:
o << int8_t(BinaryConsts::GCPrefix)
<< U32LEB(BinaryConsts::ExternInternalize);
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index c121ba89a..4a72f6ea6 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1115,15 +1115,6 @@ void RefAs::finalize() {
case RefAsNonNull:
type = Type(value->type.getHeapType(), NonNullable);
break;
- case RefAsFunc:
- type = Type(HeapType::func, NonNullable);
- break;
- case RefAsData:
- type = Type(HeapType::data, NonNullable);
- break;
- case RefAsI31:
- type = Type(HeapType::i31, NonNullable);
- break;
case ExternInternalize:
type = Type(HeapType::any, value->type.getNullability());
break;
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 08eec41c6..c2d06ae90 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -2346,7 +2346,9 @@ Result<typename Ctx::InstrT> makeI31Get(Ctx&, Index, bool signed_);
template<typename Ctx>
Result<typename Ctx::InstrT>
makeRefTest(Ctx&, Index, std::optional<Type> castType = std::nullopt);
-template<typename Ctx> Result<typename Ctx::InstrT> makeRefCast(Ctx&, Index);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeRefCast(Ctx&, Index, std::optional<Type> castType = std::nullopt);
template<typename Ctx> Result<typename Ctx::InstrT> makeRefCastNop(Ctx&, Index);
template<typename Ctx>
Result<typename Ctx::InstrT> makeBrOnNull(Ctx&, Index, bool onFail = false);
@@ -3444,7 +3446,8 @@ makeRefTest(Ctx& ctx, Index pos, std::optional<Type> castType) {
}
template<typename Ctx>
-Result<typename Ctx::InstrT> makeRefCast(Ctx& ctx, Index pos) {
+Result<typename Ctx::InstrT>
+makeRefCast(Ctx& ctx, Index pos, std::optional<Type> castType) {
return ctx.in.err("unimplemented instruction");
}