summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/gen-s-parser.py4
-rw-r--r--src/binaryen-c.cpp31
-rw-r--r--src/binaryen-c.h19
-rw-r--r--src/gen-s-parser.inc3
-rw-r--r--src/ir/ExpressionAnalyzer.cpp5
-rw-r--r--src/ir/ExpressionManipulator.cpp3
-rw-r--r--src/ir/ReFinalize.cpp1
-rw-r--r--src/ir/cost.h5
-rw-r--r--src/ir/effects.h1
-rw-r--r--src/ir/utils.h2
-rw-r--r--src/js/binaryen.js-post.js26
-rw-r--r--src/passes/DeadCodeElimination.cpp10
-rw-r--r--src/passes/Print.cpp9
-rw-r--r--src/tools/fuzzing.h18
-rw-r--r--src/wasm-binary.h5
-rw-r--r--src/wasm-builder.h7
-rw-r--r--src/wasm-interpreter.h15
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm-stack.h1
-rw-r--r--src/wasm-traversal.h18
-rw-r--r--src/wasm.h11
-rw-r--r--src/wasm/wasm-binary.cpp10
-rw-r--r--src/wasm/wasm-s-parser.cpp8
-rw-r--r--src/wasm/wasm-stack.cpp4
-rw-r--r--src/wasm/wasm-validator.cpp16
-rw-r--r--src/wasm/wasm.cpp10
-rw-r--r--src/wasm2js.h4
-rw-r--r--test/binaryen.js/exception-handling.js.txt8
-rw-r--r--test/binaryen.js/expressions.js31
-rw-r--r--test/binaryen.js/expressions.js.txt6
-rw-r--r--test/binaryen.js/kitchen-sink.js9
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt24
-rw-r--r--test/example/c-api-kitchen-sink.c4
-rw-r--r--test/example/c-api-kitchen-sink.txt6
-rw-r--r--test/passes/translate-to-fuzz_all-features.txt859
35 files changed, 430 insertions, 764 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index d66f10852..dd053ecee 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -495,7 +495,9 @@ instructions = [
# Multivalue pseudoinstructions
("tuple.make", "makeTupleMake(s)"),
("tuple.extract", "makeTupleExtract(s)"),
- ("pop", "makePop(s)")
+ ("pop", "makePop(s)"),
+ # GC instructions
+ ("ref.eq", "makeRefEq(s)")
]
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 2f1d3f5ff..6dc6f7821 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -271,6 +271,7 @@ BinaryenExpressionId BinaryenRefIsNullId(void) {
BinaryenExpressionId BinaryenRefFuncId(void) {
return Expression::Id::RefFuncId;
}
+BinaryenExpressionId BinaryenRefEqId(void) { return Expression::Id::RefEqId; }
BinaryenExpressionId BinaryenTryId(void) { return Expression::Id::TryId; }
BinaryenExpressionId BinaryenThrowId(void) { return Expression::Id::ThrowId; }
BinaryenExpressionId BinaryenRethrowId(void) {
@@ -1290,6 +1291,13 @@ BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
return static_cast<Expression*>(Builder(*(Module*)module).makeRefFunc(func));
}
+BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
+ BinaryenExpressionRef left,
+ BinaryenExpressionRef right) {
+ return static_cast<Expression*>(
+ Builder(*(Module*)module).makeRefEq((Expression*)left, (Expression*)right));
+}
+
BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody) {
@@ -2786,6 +2794,29 @@ void BinaryenRefFuncSetFunc(BinaryenExpressionRef expr, const char* funcName) {
assert(expression->is<RefFunc>());
static_cast<RefFunc*>(expression)->func = funcName;
}
+// RefEq
+BinaryenExpressionRef BinaryenRefEqGetLeft(BinaryenExpressionRef expr) {
+ auto* expression = (Expression*)expr;
+ assert(expression->is<RefEq>());
+ return static_cast<RefEq*>(expression)->left;
+}
+void BinaryenRefEqSetLeft(BinaryenExpressionRef expr,
+ BinaryenExpressionRef left) {
+ auto* expression = (Expression*)expr;
+ assert(expression->is<RefEq>());
+ static_cast<RefEq*>(expression)->left = (Expression*)left;
+}
+BinaryenExpressionRef BinaryenRefEqGetRight(BinaryenExpressionRef expr) {
+ auto* expression = (Expression*)expr;
+ assert(expression->is<RefEq>());
+ return static_cast<RefEq*>(expression)->right;
+}
+void BinaryenRefEqSetRight(BinaryenExpressionRef expr,
+ BinaryenExpressionRef right) {
+ auto* expression = (Expression*)expr;
+ assert(expression->is<RefEq>());
+ static_cast<RefEq*>(expression)->right = (Expression*)right;
+}
// Try
BinaryenExpressionRef BinaryenTryGetBody(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 3a3be4608..ff1af8ff4 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -166,6 +166,7 @@ BINARYEN_API BinaryenExpressionId BinaryenMemoryFillId(void);
BINARYEN_API BinaryenExpressionId BinaryenRefNullId(void);
BINARYEN_API BinaryenExpressionId BinaryenRefIsNullId(void);
BINARYEN_API BinaryenExpressionId BinaryenRefFuncId(void);
+BINARYEN_API BinaryenExpressionId BinaryenRefEqId(void);
BINARYEN_API BinaryenExpressionId BinaryenTryId(void);
BINARYEN_API BinaryenExpressionId BinaryenThrowId(void);
BINARYEN_API BinaryenExpressionId BinaryenRethrowId(void);
@@ -832,6 +833,9 @@ BINARYEN_API BinaryenExpressionRef
BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef value);
BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module,
const char* func);
+BINARYEN_API BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module,
+ BinaryenExpressionRef left,
+ BinaryenExpressionRef right);
BINARYEN_API BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module,
BinaryenExpressionRef body,
BinaryenExpressionRef catchBody);
@@ -1710,6 +1714,21 @@ BINARYEN_API const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr);
BINARYEN_API void BinaryenRefFuncSetFunc(BinaryenExpressionRef expr,
const char* funcName);
+// RefEq
+
+// Gets the left expression of a `ref.eq` expression.
+BINARYEN_API BinaryenExpressionRef
+BinaryenRefEqGetLeft(BinaryenExpressionRef expr);
+// Sets the left expression of a `ref.eq` expression.
+BINARYEN_API void BinaryenRefEqSetLeft(BinaryenExpressionRef expr,
+ BinaryenExpressionRef left);
+// Gets the right expression of a `ref.eq` expression.
+BINARYEN_API BinaryenExpressionRef
+BinaryenRefEqGetRight(BinaryenExpressionRef expr);
+// Sets the right expression of a `ref.eq` expression.
+BINARYEN_API void BinaryenRefEqSetRight(BinaryenExpressionRef expr,
+ BinaryenExpressionRef right);
+
// Try
// Gets the body expression of a `try` expression.
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index d14e5bbdc..76616c320 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -2524,6 +2524,9 @@ switch (op[0]) {
switch (op[2]) {
case 'f': {
switch (op[4]) {
+ case 'e':
+ if (strcmp(op, "ref.eq") == 0) { return makeRefEq(s); }
+ goto parse_error;
case 'f':
if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); }
goto parse_error;
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp
index a8d9ce44a..766d4023e 100644
--- a/src/ir/ExpressionAnalyzer.cpp
+++ b/src/ir/ExpressionAnalyzer.cpp
@@ -220,6 +220,7 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) {
void visitRefNull(RefNull* curr) { visitor.visitType(curr->type); }
void visitRefIsNull(RefIsNull* curr) {}
void visitRefFunc(RefFunc* curr) { visitor.visitNonScopeName(curr->func); }
+ void visitRefEq(RefEq* curr) {}
void visitTry(Try* curr) {}
void visitThrow(Throw* curr) { visitor.visitNonScopeName(curr->event); }
void visitRethrow(Rethrow* curr) {}
@@ -479,9 +480,7 @@ size_t ExpressionAnalyzer::hash(Expression* curr) {
"wasm64 will need changes here");
rehash(digest, curr);
}
- void visitAddress(Address curr) {
- rehash(digest, curr.addr);
- }
+ void visitAddress(Address curr) { rehash(digest, curr.addr); }
};
return Hasher(curr).digest;
diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp
index e1264e96e..95fee632f 100644
--- a/src/ir/ExpressionManipulator.cpp
+++ b/src/ir/ExpressionManipulator.cpp
@@ -233,6 +233,9 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
Expression* visitRefFunc(RefFunc* curr) {
return builder.makeRefFunc(curr->func);
}
+ Expression* visitRefEq(RefEq* curr) {
+ return builder.makeRefEq(copy(curr->left), copy(curr->right));
+ }
Expression* visitTry(Try* curr) {
return builder.makeTry(
copy(curr->body), copy(curr->catchBody), curr->type);
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index b6e2a1b59..99387ada1 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -124,6 +124,7 @@ void ReFinalize::visitMemoryGrow(MemoryGrow* curr) { curr->finalize(); }
void ReFinalize::visitRefNull(RefNull* curr) { curr->finalize(); }
void ReFinalize::visitRefIsNull(RefIsNull* curr) { curr->finalize(); }
void ReFinalize::visitRefFunc(RefFunc* curr) { curr->finalize(); }
+void ReFinalize::visitRefEq(RefEq* curr) { curr->finalize(); }
void ReFinalize::visitTry(Try* curr) { curr->finalize(); }
void ReFinalize::visitThrow(Throw* curr) { curr->finalize(); }
void ReFinalize::visitRethrow(Rethrow* curr) { curr->finalize(); }
diff --git a/src/ir/cost.h b/src/ir/cost.h
index 056d51447..5df4917e4 100644
--- a/src/ir/cost.h
+++ b/src/ir/cost.h
@@ -757,8 +757,11 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
Index visitMemorySize(MemorySize* curr) { return 1; }
Index visitMemoryGrow(MemoryGrow* curr) { return 100; }
Index visitRefNull(RefNull* curr) { return 1; }
- Index visitRefIsNull(RefIsNull* curr) { return 1; }
+ Index visitRefIsNull(RefIsNull* curr) { return 1 + visit(curr->value); }
Index visitRefFunc(RefFunc* curr) { return 1; }
+ Index visitRefEq(RefEq* curr) {
+ return 1 + visit(curr->left) + visit(curr->right);
+ }
Index visitTry(Try* curr) {
// We assume no exception will be thrown in most cases
return visit(curr->body);
diff --git a/src/ir/effects.h b/src/ir/effects.h
index b973d7446..a90e902b0 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -475,6 +475,7 @@ struct EffectAnalyzer
void visitRefNull(RefNull* curr) {}
void visitRefIsNull(RefIsNull* curr) {}
void visitRefFunc(RefFunc* curr) {}
+ void visitRefEq(RefEq* curr) {}
void visitTry(Try* curr) {}
void visitThrow(Throw* curr) {
if (tryDepth == 0) {
diff --git a/src/ir/utils.h b/src/ir/utils.h
index 51fe4c9e7..428657e88 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -150,6 +150,7 @@ struct ReFinalize
void visitRefNull(RefNull* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
+ void visitRefEq(RefEq* curr);
void visitTry(Try* curr);
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
@@ -219,6 +220,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitRefNull(RefNull* curr) { curr->finalize(); }
void visitRefIsNull(RefIsNull* curr) { curr->finalize(); }
void visitRefFunc(RefFunc* curr) { curr->finalize(); }
+ void visitRefEq(RefEq* curr) { curr->finalize(); }
void visitTry(Try* curr) { curr->finalize(); }
void visitThrow(Throw* curr) { curr->finalize(); }
void visitRethrow(Rethrow* curr) { curr->finalize(); }
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 4703abc54..e24b50984 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -89,6 +89,7 @@ function initializeConstants() {
'RefNull',
'RefIsNull',
'RefFunc',
+ 'RefEq',
'Try',
'Throw',
'Rethrow',
@@ -2093,6 +2094,9 @@ function wrapModule(module, self = {}) {
},
'func'(func) {
return preserveStack(() => Module['_BinaryenRefFunc'](module, strToStack(func)));
+ },
+ 'eq'(left, right) {
+ return Module['_BinaryenRefEq'](module, left, right);
}
};
@@ -2803,6 +2807,13 @@ Module['getExpressionInfo'] = function(expr) {
'type': type,
'func': UTF8ToString(Module['_BinaryenRefFuncGetFunc'](expr)),
};
+ case Module['RefEqId']:
+ return {
+ 'id': id,
+ 'type': type,
+ 'left': Module['_BinaryenRefEqGetLeft'](expr),
+ 'right': Module['_BinaryenRefEqGetRight'](expr)
+ };
case Module['TryId']:
return {
'id': id,
@@ -4100,6 +4111,21 @@ Module['RefFunc'] = makeExpressionWrapper({
}
});
+Module['RefEq'] = makeExpressionWrapper({
+ 'getLeft'(expr) {
+ return Module['_BinaryenRefEqGetLeft'](expr);
+ },
+ 'setLeft'(expr, leftExpr) {
+ return Module['_BinaryenRefEqSetLeft'](expr, leftExpr);
+ },
+ 'getRight'(expr) {
+ return Module['_BinaryenRefEqGetRight'](expr);
+ },
+ 'setRight'(expr, rightExpr) {
+ return Module['_BinaryenRefEqSetRight'](expr, rightExpr);
+ }
+});
+
Module['Try'] = makeExpressionWrapper({
'getBody'(expr) {
return Module['_BinaryenTryGetBody'](expr);
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 4215de3f8..bf1c0705a 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -361,6 +361,8 @@ struct DeadCodeElimination
DELEGATE(RefIsNull);
case Expression::Id::RefFuncId:
DELEGATE(RefFunc);
+ case Expression::Id::RefEqId:
+ DELEGATE(RefEq);
case Expression::Id::TryId:
DELEGATE(Try);
case Expression::Id::ThrowId:
@@ -527,6 +529,14 @@ struct DeadCodeElimination
blockifyReachableOperands({curr->delta}, curr->type);
}
+ void visitRefIsNull(RefIsNull* curr) {
+ blockifyReachableOperands({curr->value}, curr->type);
+ }
+
+ void visitRefEq(RefEq* curr) {
+ blockifyReachableOperands({curr->left, curr->right}, curr->type);
+ }
+
void visitFunction(Function* curr) { assert(reachableBreaks.size() == 0); }
};
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 6955a7a5e..27c3e327c 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1441,6 +1441,7 @@ struct PrintExpressionContents
printMedium(o, "ref.func ");
printName(curr->func, o);
}
+ void visitRefEq(RefEq* curr) { printMedium(o, "ref.eq"); }
void visitTry(Try* curr) {
printMedium(o, "try");
if (curr->type.isConcrete()) {
@@ -1968,6 +1969,14 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
PrintExpressionContents(currFunction, o).visit(curr);
o << ')';
}
+ void visitRefEq(RefEq* curr) {
+ o << '(';
+ PrintExpressionContents(currFunction, o).visit(curr);
+ incIndent();
+ printFullLine(curr->left);
+ printFullLine(curr->right);
+ decIndent();
+ }
// try-catch-end is written in the folded wat format as
// (try
// (do
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 0783588cd..7ef24bbac 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -892,6 +892,8 @@ private:
}
if (type == Type::i32) {
options.add(FeatureSet::ReferenceTypes, &Self::makeRefIsNull);
+ options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
+ &Self::makeRefEq);
}
if (type.isTuple()) {
options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
@@ -2640,6 +2642,14 @@ private:
return builder.makeRefIsNull(make(getReferenceType()));
}
+ Expression* makeRefEq(Type type) {
+ assert(type == Type::i32);
+ assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
+ auto* left = make(getEqReferenceType());
+ auto* right = make(getEqReferenceType());
+ return builder.makeRefEq(left, right);
+ }
+
Expression* makeMemoryInit() {
if (!allowMemory) {
return makeTrivial(Type::none);
@@ -2723,6 +2733,14 @@ private:
Type getReferenceType() { return pick(getReferenceTypes()); }
+ std::vector<Type> getEqReferenceTypes() {
+ return items(
+ FeatureOptions<Type>().add(FeatureSet::ReferenceTypes | FeatureSet::GC,
+ Type::eqref)); // TODO: i31ref
+ }
+
+ Type getEqReferenceType() { return pick(getEqReferenceTypes()); }
+
Type getTupleType() {
std::vector<Type> elements;
size_t numElements = 2 + upTo(MAX_TUPLE_SIZE - 1);
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 39980ee04..df800d470 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -927,6 +927,10 @@ enum ASTNodes {
RefIsNull = 0xd1,
RefFunc = 0xd2,
+ // GC opcodes
+
+ RefEq = 0xd5,
+
// exception handling opcodes
Try = 0x06,
@@ -1458,6 +1462,7 @@ public:
void visitRefNull(RefNull* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
+ void visitRefEq(RefEq* curr);
void visitTryOrTryInBlock(Expression*& out);
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 737dad16a..8c5d8722e 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -558,6 +558,13 @@ public:
ret->finalize();
return ret;
}
+ RefEq* makeRefEq(Expression* left, Expression* right) {
+ auto* ret = allocator.alloc<RefEq>();
+ ret->left = left;
+ ret->right = right;
+ ret->finalize();
+ return ret;
+ }
Try* makeTry(Expression* body, Expression* catchBody) {
auto* ret = allocator.alloc<Try>();
ret->body = body;
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 69d6ff771..57ec65edd 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1260,6 +1260,21 @@ public:
NOTE_NAME(curr->func);
return Literal::makeFunc(curr->func);
}
+ Flow visitRefEq(RefEq* curr) {
+ NOTE_ENTER("RefEq");
+ Flow flow = visit(curr->left);
+ if (flow.breaking()) {
+ return flow;
+ }
+ auto left = flow.getSingleValue();
+ flow = visit(curr->right);
+ if (flow.breaking()) {
+ return flow;
+ }
+ auto right = flow.getSingleValue();
+ NOTE_EVAL2(left, right);
+ return Literal(int32_t(left == right));
+ }
Flow visitTry(Try* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitThrow(Throw* curr) {
NOTE_ENTER("Throw");
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index f413ab5d4..5719084e4 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -236,6 +236,7 @@ private:
Expression* makeRefNull(Element& s);
Expression* makeRefIsNull(Element& s);
Expression* makeRefFunc(Element& s);
+ Expression* makeRefEq(Element& s);
Expression* makeTry(Element& s);
Expression* makeTryOrCatchBody(Element& s, Type type, bool isTry);
Expression* makeThrow(Element& s);
diff --git a/src/wasm-stack.h b/src/wasm-stack.h
index 13cce6d6f..b7a064168 100644
--- a/src/wasm-stack.h
+++ b/src/wasm-stack.h
@@ -137,6 +137,7 @@ public:
void visitRefNull(RefNull* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
+ void visitRefEq(RefEq* curr);
void visitTry(Try* curr);
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index 94997caf1..8267f4767 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -76,6 +76,7 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
ReturnType visitRefNull(RefNull* curr) { return ReturnType(); }
ReturnType visitRefIsNull(RefIsNull* curr) { return ReturnType(); }
ReturnType visitRefFunc(RefFunc* curr) { return ReturnType(); }
+ ReturnType visitRefEq(RefEq* curr) { return ReturnType(); }
ReturnType visitTry(Try* curr) { return ReturnType(); }
ReturnType visitThrow(Throw* curr) { return ReturnType(); }
ReturnType visitRethrow(Rethrow* curr) { return ReturnType(); }
@@ -180,6 +181,8 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
DELEGATE(RefIsNull);
case Expression::Id::RefFuncId:
DELEGATE(RefFunc);
+ case Expression::Id::RefEqId:
+ DELEGATE(RefEq);
case Expression::Id::TryId:
DELEGATE(Try);
case Expression::Id::ThrowId:
@@ -260,6 +263,7 @@ struct OverriddenVisitor {
UNIMPLEMENTED(RefNull);
UNIMPLEMENTED(RefIsNull);
UNIMPLEMENTED(RefFunc);
+ UNIMPLEMENTED(RefEq);
UNIMPLEMENTED(Try);
UNIMPLEMENTED(Throw);
UNIMPLEMENTED(Rethrow);
@@ -365,6 +369,8 @@ struct OverriddenVisitor {
DELEGATE(RefIsNull);
case Expression::Id::RefFuncId:
DELEGATE(RefFunc);
+ case Expression::Id::RefEqId:
+ DELEGATE(RefEq);
case Expression::Id::TryId:
DELEGATE(Try);
case Expression::Id::ThrowId:
@@ -518,6 +524,9 @@ struct UnifiedExpressionVisitor : public Visitor<SubType, ReturnType> {
ReturnType visitRefFunc(RefFunc* curr) {
return static_cast<SubType*>(this)->visitExpression(curr);
}
+ ReturnType visitRefEq(RefEq* curr) {
+ return static_cast<SubType*>(this)->visitExpression(curr);
+ }
ReturnType visitTry(Try* curr) {
return static_cast<SubType*>(this)->visitExpression(curr);
}
@@ -835,6 +844,9 @@ struct Walker : public VisitorType {
static void doVisitRefFunc(SubType* self, Expression** currp) {
self->visitRefFunc((*currp)->cast<RefFunc>());
}
+ static void doVisitRefEq(SubType* self, Expression** currp) {
+ self->visitRefEq((*currp)->cast<RefEq>());
+ }
static void doVisitTry(SubType* self, Expression** currp) {
self->visitTry((*currp)->cast<Try>());
}
@@ -1108,6 +1120,12 @@ struct PostWalker : public Walker<SubType, VisitorType> {
self->pushTask(SubType::doVisitRefFunc, currp);
break;
}
+ case Expression::Id::RefEqId: {
+ self->pushTask(SubType::doVisitRefEq, currp);
+ self->pushTask(SubType::scan, &curr->cast<RefEq>()->right);
+ self->pushTask(SubType::scan, &curr->cast<RefEq>()->left);
+ break;
+ }
case Expression::Id::TryId: {
self->pushTask(SubType::doVisitTry, currp);
self->pushTask(SubType::scan, &curr->cast<Try>()->catchBody);
diff --git a/src/wasm.h b/src/wasm.h
index 9f61fac37..3f12f435e 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -553,6 +553,7 @@ public:
RefNullId,
RefIsNullId,
RefFuncId,
+ RefEqId,
TryId,
ThrowId,
RethrowId,
@@ -1128,6 +1129,16 @@ public:
void finalize();
};
+class RefEq : public SpecificExpression<Expression::RefEqId> {
+public:
+ RefEq(MixedArena& allocator) {}
+
+ Expression* left;
+ Expression* right;
+
+ void finalize();
+};
+
class Try : public SpecificExpression<Expression::TryId> {
public:
Try(MixedArena& allocator) {}
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index a6299c892..c1f698bb0 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2474,6 +2474,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
case BinaryConsts::RefFunc:
visitRefFunc((curr = allocator.alloc<RefFunc>())->cast<RefFunc>());
break;
+ case BinaryConsts::RefEq:
+ visitRefEq((curr = allocator.alloc<RefEq>())->cast<RefEq>());
+ break;
case BinaryConsts::Try:
visitTryOrTryInBlock(curr);
break;
@@ -4864,6 +4867,13 @@ void WasmBinaryBuilder::visitRefFunc(RefFunc* curr) {
curr->finalize();
}
+void WasmBinaryBuilder::visitRefEq(RefEq* curr) {
+ BYN_TRACE("zz node: RefEq\n");
+ curr->right = popNonVoidExpression();
+ curr->left = popNonVoidExpression();
+ curr->finalize();
+}
+
void WasmBinaryBuilder::visitTryOrTryInBlock(Expression*& out) {
BYN_TRACE("zz node: Try\n");
auto* curr = allocator.alloc<Try>();
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 2aa60979f..1bb83ec94 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1850,6 +1850,14 @@ Expression* SExpressionWasmBuilder::makeRefFunc(Element& s) {
return ret;
}
+Expression* SExpressionWasmBuilder::makeRefEq(Element& s) {
+ auto ret = allocator.alloc<RefEq>();
+ ret->left = parseExpression(s[1]);
+ ret->right = parseExpression(s[2]);
+ ret->finalize();
+ return ret;
+}
+
// try-catch-end is written in the folded wast format as
// (try
// ...
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 66f9e02dd..551275622 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1701,6 +1701,10 @@ void BinaryInstWriter::visitRefFunc(RefFunc* curr) {
<< U32LEB(parent.getFunctionIndex(curr->func));
}
+void BinaryInstWriter::visitRefEq(RefEq* curr) {
+ o << int8_t(BinaryConsts::RefEq);
+}
+
void BinaryInstWriter::visitTry(Try* curr) {
breakStack.emplace_back(IMPOSSIBLE_CONTINUE);
o << int8_t(BinaryConsts::Try);
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 16ba60d72..c1df740df 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -330,6 +330,7 @@ public:
void visitMemoryGrow(MemoryGrow* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
+ void visitRefEq(RefEq* curr);
void visitTry(Try* curr);
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
@@ -1957,6 +1958,21 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) {
shouldBeTrue(!!func, curr, "function argument of ref.func must exist");
}
+void FunctionValidator::visitRefEq(RefEq* curr) {
+ shouldBeTrue(
+ getModule()->features.hasGC(), curr, "ref.eq requires gc to be enabled");
+ shouldBeSubTypeOrFirstIsUnreachable(
+ curr->left->type,
+ Type::eqref,
+ curr->left,
+ "ref.eq's left argument should be a subtype of eqref");
+ shouldBeSubTypeOrFirstIsUnreachable(
+ curr->right->type,
+ Type::eqref,
+ curr->right,
+ "ref.eq's right argument should be a subtype of eqref");
+}
+
void FunctionValidator::visitTry(Try* curr) {
if (curr->type != Type::unreachable) {
shouldBeSubTypeOrFirstIsUnreachable(
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 6cc61a8a1..0b45f494d 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -192,6 +192,8 @@ const char* getExpressionName(Expression* curr) {
return "ref.is_null";
case Expression::Id::RefFuncId:
return "ref.func";
+ case Expression::Id::RefEqId:
+ return "ref.eq";
case Expression::Id::TryId:
return "try";
case Expression::Id::ThrowId:
@@ -915,6 +917,14 @@ void RefIsNull::finalize() {
void RefFunc::finalize() { type = Type::funcref; }
+void RefEq::finalize() {
+ if (left->type == Type::unreachable || right->type == Type::unreachable) {
+ type = Type::unreachable;
+ } else {
+ type = Type::i32;
+ }
+}
+
void Try::finalize() {
type = Type::getLeastUpperBound(body->type, catchBody->type);
}
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 9350b38d6..7377dad31 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -2019,6 +2019,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
unimplemented(curr);
WASM_UNREACHABLE("unimp");
}
+ Ref visitRefEq(RefEq* curr) {
+ unimplemented(curr);
+ WASM_UNREACHABLE("unimp");
+ }
Ref visitTry(Try* curr) {
unimplemented(curr);
WASM_UNREACHABLE("unimp");
diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt
index ab545aac9..a586691d3 100644
--- a/test/binaryen.js/exception-handling.js.txt
+++ b/test/binaryen.js/exception-handling.js.txt
@@ -28,7 +28,7 @@
)
)
-getExpressionInfo(throw) = {"id":44,"type":1,"event":"e"}
-getExpressionInfo(br_on_exn) = {"id":46,"type":9,"name":"l","event":"e"}
-getExpressionInfo(rethrow) = {"id":45,"type":1}
-getExpressionInfo(try) = {"id":43,"type":0}
+getExpressionInfo(throw) = {"id":45,"type":1,"event":"e"}
+getExpressionInfo(br_on_exn) = {"id":47,"type":9,"name":"l","event":"e"}
+getExpressionInfo(rethrow) = {"id":46,"type":1}
+getExpressionInfo(try) = {"id":44,"type":0}
diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js
index b9a9a24fb..a97097afe 100644
--- a/test/binaryen.js/expressions.js
+++ b/test/binaryen.js/expressions.js
@@ -1400,6 +1400,37 @@ console.log("# RefFunc");
module.dispose();
})();
+console.log("# RefEq");
+(function testRefEq() {
+ const module = new binaryen.Module();
+
+ var left = module.local.get(0, binaryen.eqref);
+ var right = module.local.get(1, binaryen.eqref);
+ const theRefEq = binaryen.RefEq(module.ref.eq(left, right));
+ assert(theRefEq instanceof binaryen.RefEq);
+ assert(theRefEq instanceof binaryen.Expression);
+ assert(theRefEq.left === left);
+ assert(theRefEq.right === right);
+ assert(theRefEq.type === binaryen.i32);
+
+ theRefEq.left = left = module.local.get(2, binaryen.eqref);
+ assert(theRefEq.left === left);
+ theRefEq.right = right = module.local.get(3, binaryen.eqref);
+ assert(theRefEq.right === right);
+ theRefEq.type = binaryen.f64;
+ theRefEq.finalize();
+ assert(theRefEq.type === binaryen.i32);
+
+ console.log(theRefEq.toText());
+ assert(
+ theRefEq.toText()
+ ==
+ "(ref.eq\n (local.get $2)\n (local.get $3)\n)\n"
+ );
+
+ module.dispose();
+})();
+
console.log("# Try");
(function testTry() {
const module = new binaryen.Module();
diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt
index a8946875a..22c4f2747 100644
--- a/test/binaryen.js/expressions.js.txt
+++ b/test/binaryen.js/expressions.js.txt
@@ -210,6 +210,12 @@
# RefFunc
(ref.func $b)
+# RefEq
+(ref.eq
+ (local.get $2)
+ (local.get $3)
+)
+
# Try
(try (result i32)
(do
diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js
index 342315682..69c812bf7 100644
--- a/test/binaryen.js/kitchen-sink.js
+++ b/test/binaryen.js/kitchen-sink.js
@@ -155,11 +155,15 @@ function test_ids() {
console.log("DataDropId: " + binaryen.DataDropId);
console.log("MemoryCopyId: " + binaryen.MemoryCopyId);
console.log("MemoryFillId: " + binaryen.MemoryFillId);
+ console.log("PopId: " + binaryen.PopId);
+ console.log("RefNullId: " + binaryen.RefNullId);
+ console.log("RefIsNullId: " + binaryen.RefIsNullId);
+ console.log("RefFuncId: " + binaryen.RefFuncId);
+ console.log("RefEqId: " + binaryen.RefEqId);
console.log("TryId: " + binaryen.TryId);
console.log("ThrowId: " + binaryen.ThrowId);
console.log("RethrowId: " + binaryen.RethrowId);
console.log("BrOnExnId: " + binaryen.BrOnExnId);
- console.log("PopId: " + binaryen.PopId);
}
function test_core() {
@@ -521,6 +525,9 @@ function test_core() {
module.ref.is_null(module.ref.func("kitchen()sinker")),
module.select(temp10, module.ref.null(binaryen.funcref), module.ref.func("kitchen()sinker"), binaryen.funcref),
+ // GC
+ module.ref.eq(module.ref.null(binaryen.eqref), module.ref.null(binaryen.eqref)),
+
// Exception handling
module.try(
module.throw("a-event", [module.i32.const(0)]),
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 413a2236c..b94811be5 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -79,11 +79,15 @@ MemoryInitId: 35
DataDropId: 36
MemoryCopyId: 37
MemoryFillId: 38
-TryId: 43
-ThrowId: 44
-RethrowId: 45
-BrOnExnId: 46
PopId: 39
+RefNullId: 40
+RefIsNullId: 41
+RefFuncId: 42
+RefEqId: 43
+TryId: 44
+ThrowId: 45
+RethrowId: 46
+BrOnExnId: 47
getExpressionInfo={"id":15,"type":4,"op":6}
(f32.neg
(f32.const -33.61199951171875)
@@ -1841,6 +1845,12 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7}
(i32.const 1)
)
)
+ (drop
+ (ref.eq
+ (ref.null eq)
+ (ref.null eq)
+ )
+ )
(try
(do
(throw $a-event
@@ -3698,6 +3708,12 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7}
(i32.const 1)
)
)
+ (drop
+ (ref.eq
+ (ref.null eq)
+ (ref.null eq)
+ )
+ )
(try
(do
(throw $a-event
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index 442394e12..6b4aaec7d 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -740,6 +740,10 @@ void test_core() {
BinaryenRefNull(module, BinaryenTypeFuncref()),
BinaryenRefFunc(module, "kitchen()sinker"),
BinaryenTypeFuncref()),
+ // GC
+ BinaryenRefEq(module,
+ BinaryenRefNull(module, BinaryenTypeEqref()),
+ BinaryenRefNull(module, BinaryenTypeEqref())),
// Exception handling
BinaryenTry(module, tryBody, catchBody),
// Atomics
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index 405848140..e2dd48ad4 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -1776,6 +1776,12 @@ BinaryenFeatureAll: 4095
(i32.const 1)
)
)
+ (drop
+ (ref.eq
+ (ref.null eq)
+ (ref.null eq)
+ )
+ )
(try
(do
(throw $a-event
diff --git a/test/passes/translate-to-fuzz_all-features.txt b/test/passes/translate-to-fuzz_all-features.txt
index b03dbbb20..50cc583ac 100644
--- a/test/passes/translate-to-fuzz_all-features.txt
+++ b/test/passes/translate-to-fuzz_all-features.txt
@@ -1,24 +1,14 @@
(module
- (type $f32_=>_none (func (param f32)))
+ (type $none_=>_funcref_anyref_f32_exnref (func (result funcref anyref f32 exnref)))
(type $none_=>_none (func))
- (type $none_=>_f32_i64_funcref (func (result f32 i64 funcref)))
+ (type $f32_=>_none (func (param f32)))
(type $i32_=>_none (func (param i32)))
- (type $i32_f64_=>_none (func (param i32 f64)))
(type $i64_=>_none (func (param i64)))
(type $f64_=>_none (func (param f64)))
(type $v128_=>_none (func (param v128)))
(type $exnref_=>_none (func (param exnref)))
(type $none_=>_i32 (func (result i32)))
- (type $funcref_anyref_=>_f64 (func (param funcref anyref) (result f64)))
- (type $anyref_eqref_=>_f64 (func (param anyref eqref) (result f64)))
- (type $funcref_f64_=>_v128 (func (param funcref f64) (result v128)))
- (type $none_=>_funcref (func (result funcref)))
- (type $v128_=>_funcref (func (param v128) (result funcref)))
- (type $v128_anyref_f32_=>_funcref (func (param v128 anyref f32) (result funcref)))
- (type $externref_i32_v128_i64_=>_externref (func (param externref i32 v128 i64) (result externref)))
- (type $f32_eqref_=>_anyref (func (param f32 eqref) (result anyref)))
- (type $none_=>_eqref_eqref_eqref_eqref_eqref (func (result eqref eqref eqref eqref eqref)))
- (type $exnref_=>_eqref_eqref_eqref_eqref_eqref (func (param exnref) (result eqref eqref eqref eqref eqref)))
+ (type $f32_i32_anyref_=>_i64 (func (param f32 i32 anyref) (result i64)))
(import "fuzzing-support" "log-i32" (func $log-i32 (param i32)))
(import "fuzzing-support" "log-i64" (func $log-i64 (param i64)))
(import "fuzzing-support" "log-f32" (func $log-f32 (param f32)))
@@ -27,8 +17,7 @@
(import "fuzzing-support" "log-exnref" (func $log-exnref (param exnref)))
(memory $0 (shared 1 1))
(data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3")
- (table $0 12 12 funcref)
- (elem (i32.const 0) $func_7 $func_7 $func_8 $func_8 $func_9 $func_9 $func_9 $func_13 $func_13 $func_13 $func_17 $func_19)
+ (table $0 0 0 funcref)
(global $global$5 (mut eqref) (ref.null eq))
(global $global$4 (mut externref) (ref.null extern))
(global $global$3 (mut exnref) (ref.null exn))
@@ -44,14 +33,8 @@
(global $hangLimit (mut i32) (i32.const 10))
(export "hashMemory" (func $hashMemory))
(export "memory" (memory $0))
- (export "func_9" (func $func_9))
- (export "func_10_invoker" (func $func_10_invoker))
- (export "func_12" (func $func_12))
- (export "func_13_invoker" (func $func_13_invoker))
- (export "func_17" (func $func_17))
- (export "func_19" (func $func_19))
- (export "func_19_invoker" (func $func_19_invoker))
- (export "func_21" (func $func_21))
+ (export "func_7" (func $func_7))
+ (export "func_8_invoker" (func $func_8_invoker))
(export "hangLimitInitializer" (func $hangLimitInitializer))
(func $hashMemory (result i32)
(local $0 i32)
@@ -312,528 +295,97 @@
(i32.eqz
(i32.const 32768)
)
- (block $label$1 (result f64)
+ (block $label$1
(br_if $label$0
(i32.eqz
- (loop $label$2 (result i32)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
+ (ref.eq
+ (ref.null eq)
+ (loop $label$21
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
)
- )
- )
- (block $label$3 (result i32)
- (nop)
- (local.tee $7
- (local.tee $2
- (local.tee $7
- (local.tee $2
- (local.tee $2
- (local.tee $2
- (local.tee $2
- (local.tee $2
- (local.get $7)
- )
- )
- )
- )
- )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
)
)
)
+ (block $label$22
+ (nop)
+ (br $label$21)
+ )
)
)
)
)
- (call $log-exnref
- (ref.null exn)
- )
- (f64.const 11839)
- )
- (block $label$4 (result f64)
- (nop)
- (f64.nearest
- (f64.const 1.6005841300030413e-215)
- )
- )
- )
- )
- (call $log-exnref
- (ref.null exn)
- )
- )
- )
- (func $func_8 (param $0 funcref) (param $1 anyref) (result f64)
- (local $2 i64)
- (local $3 (f64 i32 anyref i64 exnref))
- (local $4 v128)
- (local $5 (v128 f32 exnref))
- (local $6 f32)
- (local $7 i32)
- (local $8 (funcref eqref))
- (local $9 i64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (f64.const 4806734720588042541890704e256)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (f64.const 9223372036854775808)
- )
- (func $func_9 (param $0 i32) (param $1 f64)
- (local $2 i32)
- (local $3 funcref)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0
- (f32.store offset=3 align=2
- (i32.and
- (local.get $0)
- (i32.const 15)
- )
- (if (result f32)
- (local.tee $2
- (local.tee $2
- (block $label$1
- (call_indirect (type $f32_=>_none)
- (f32.div
- (f32.const 4189)
- (f32.const 1396855168)
- )
- (i32.atomic.rmw8.cmpxchg_u offset=3
- (i32.and
- (call $hashMemory)
- (i32.const 15)
- )
- (local.tee $0
- (local.get $2)
- )
- (loop $label$3 (result i32)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (loop $label$4 (result i32)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$5 (result i32)
- (v128.store offset=22 align=8
- (i32.and
- (i32.load16_u offset=4 align=1
- (i32.and
- (ref.is_null
- (ref.null extern)
- )
- (i32.const 15)
- )
- )
- (i32.const 15)
- )
- (i16x8.ne
- (i16x8.gt_u
- (select
- (if (result v128)
- (i32.eqz
- (i32.const 2147483647)
- )
- (block $label$8 (result v128)
- (nop)
- (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
- )
- (block $label$9 (result v128)
- (if (result v128)
- (i32.const -96)
- (v128.const i32x4 0xffffff99 0xffffffff 0x00000000 0x40648000)
- (v128.const i32x4 0x00005f01 0x0000b03f 0x644b1d80 0x4fb2ff39)
- )
- )
- )
- (v128.const i32x4 0x00000000 0x40eff640 0x00000000 0xc1300000)
- (local.tee $0
- (if (result i32)
- (local.tee $0
- (local.get $0)
- )
- (block $label$6 (result i32)
- (local.set $0
- (local.get $2)
- )
- (if (result i32)
- (if (result i32)
- (i32.eqz
- (local.get $2)
- )
- (i32.const 127)
- (i32.const -128)
- )
- (i32.const 26)
- (i32.const -32768)
- )
- )
- (block $label$7
- (atomic.fence)
- (br $label$3)
- )
- )
- )
- )
- (tuple.extract 4
- (tuple.make
- (ref.null extern)
- (i32.const 126)
- (f32.const 2.5923033978570846e-30)
- (i64.const 6796583934299212805)
- (v128.const i32x4 0x00000008 0x00000000 0x000000fe 0x00000000)
- )
- )
- )
- (v128.const i32x4 0x0057ff7f 0x00470000 0x00014359 0x007f3028)
- )
- )
- (atomic.notify offset=3
- (i32.and
- (if (result i32)
- (i32.eqz
- (f32.ge
- (f32.sqrt
- (f32.const -0.1029999852180481)
- )
- (f32x4.extract_lane 0
- (v128.const i32x4 0x080a617e 0xcf000000 0xda800000 0xc20c0000)
- )
- )
- )
- (select
- (local.tee $0
- (local.tee $2
- (local.tee $2
- (local.tee $2
- (local.get $2)
- )
- )
- )
- )
- (local.get $2)
- (i32.const 0)
- )
- (local.tee $0
- (br_if $label$5
- (f64.gt
- (select
- (local.get $1)
- (if (result f64)
- (i32.eqz
- (local.get $2)
- )
- (local.get $1)
- (f64.const 2.5823598491911832e-236)
- )
- (local.get $0)
- )
- (local.get $1)
- )
- (i32.const 609887560)
- )
- )
- )
- (i32.const 15)
- )
- (i64.eq
- (tuple.extract 0
- (tuple.make
- (i64.const 82)
- (i32.const 0)
- )
- )
- (i64.const 2147483646)
- )
- )
- )
- )
- )
+ (if
+ (i32.eqz
+ (i32.const -33554432)
+ )
+ (block $label$2
+ (br_if $label$2
+ (i32.eqz
+ (local.get $2)
)
)
- (br $label$0)
+ (call $log-i32
+ (call $hashMemory)
+ )
+ )
+ (drop
+ (ref.null extern)
)
)
+ (br $label$0)
)
- (f32.demote_f64
- (block $label$2
- (call_indirect (type $f32_=>_none)
- (f32.div
- (f32.const 4189)
- (f32.const 1396855168)
+ (loop $label$4 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
)
- (i32.atomic.rmw8.cmpxchg_u offset=3
- (i32.and
- (call $hashMemory)
- (i32.const 15)
- )
- (local.tee $0
- (local.get $2)
- )
- (i32.const -94)
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
)
)
- (br $label$0)
)
+ (f64.const 82)
)
- (f32.const -2147483648)
- )
- )
- (call_indirect (type $f32_=>_none)
- (f32.sqrt
- (f32.const -0.1029999852180481)
- )
- (i32.atomic.rmw8.cmpxchg_u offset=3
- (i32.and
- (call $hashMemory)
- (i32.const 2147483647)
- )
- (local.tee $0
- (local.get $2)
- )
- (i32.const 536870912)
)
)
- )
- )
- (func $func_10 (result f32 i64 funcref)
- (local $0 i64)
- (local $1 (exnref exnref exnref exnref f32))
- (local $2 externref)
- (local $3 (v128 funcref))
- (local $4 externref)
- (local $5 (i32 f32))
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (tuple.make
- (f32.const 2047.8480224609375)
- (i64.const -127)
- (ref.null func)
- )
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0 (result f32 i64 funcref)
- (call $log-f64
- (f64.const 1.44)
- )
- (call $log-i32
- (call $hashMemory)
- )
- (tuple.make
- (f32.const 527435904)
- (i64.const 2147483648)
- (ref.null func)
- )
- )
- )
- (func $func_10_invoker
- (drop
- (call $func_10)
- )
- (call $log-i32
- (call $hashMemory)
- )
- (drop
- (call $func_10)
- )
- (call $log-i32
- (call $hashMemory)
- )
- )
- (func $func_12 (result funcref)
- (local $0 anyref)
- (local $1 eqref)
- (local $2 i64)
- (local $3 (anyref exnref i64 i32 anyref v128))
- (local $4 externref)
- (local $5 anyref)
- (local $6 f32)
- (local $7 v128)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (ref.func $func_10)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (ref.null func)
- )
- (func $func_13 (param $0 exnref) (result eqref eqref eqref eqref eqref)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (tuple.make
- (ref.null eq)
- (ref.null eq)
- (ref.null eq)
- (ref.null eq)
- (ref.null eq)
- )
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0
- (return
- (tuple.make
- (ref.null eq)
- (ref.null eq)
- (ref.null eq)
- (ref.null eq)
- (ref.null eq)
- )
- )
- )
- )
- (func $func_13_invoker
- (drop
- (call $func_13
- (ref.null exn)
- )
- )
- )
- (func $func_15 (param $0 anyref) (param $1 eqref) (result f64)
- (local $2 (f64 eqref funcref i32))
- (local $3 v128)
- (local $4 i64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (f64.const 303201560)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (f64.const 1.8039635330443502e-221)
- )
- (func $func_16 (param $0 funcref) (param $1 f64) (result v128)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (v128.const i32x4 0x00000000 0x41400000 0x00000000 0x40458000)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0
- (if
- (i32.const 10793)
- (call_indirect (type $f32_=>_none)
- (f32.const 3402823466385288598117041e14)
- (i32.const 0)
- )
- (block $label$1
- (call $log-i32
- (call $hashMemory)
+ (call $log-v128
+ (loop $label$50 (result v128)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
)
- (call $log-f32
- (loop $label$2 (result f32)
+ (block $label$51 (result v128)
+ (loop $label$52
(block
(if
(i32.eqz
(global.get $hangLimit)
)
- (return
- (v128.const i32x4 0x41700000 0x5f000000 0x3f800000 0x41a00000)
- )
+ (return)
)
(global.set $hangLimit
(i32.sub
@@ -842,73 +394,26 @@
)
)
)
- (block (result f32)
- (block $label$3
- (call $log-i32
- (call $hashMemory)
- )
- (call $log-v128
- (loop $label$4 (result v128)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (v128.const i32x4 0x152dffff 0x8000ffa4 0x1f484608 0x02193720)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$5 (result v128)
- (call $log-i32
- (i32.const -1)
- )
- (v128.const i32x4 0x00020000 0xff8000b0 0xffb40001 0xffff5657)
- )
- )
- )
- )
- (br_if $label$2
- (if (result i32)
- (i32.eqz
- (f32.ge
- (f32.const 3402823466385288598117041e14)
- (f32.const 3402823466385288598117041e14)
- )
- )
- (i32.const 0)
- (i32.const -65537)
- )
+ (block $label$53
+ (call $log-i32
+ (call $hashMemory)
)
- (f32.const 0.004999999888241291)
)
)
+ (local.get $5)
)
)
)
- (return
- (v128.const i32x4 0x1b145c08 0xffffffe0 0x00400000 0x00000052)
- )
)
)
- (func $func_17 (param $0 v128) (param $1 anyref) (param $2 f32) (result funcref)
- (local $3 i64)
- (local $4 (externref i32))
- (local $5 i32)
- (local $6 f64)
+ (func $func_8 (param $0 f32) (param $1 i32) (param $2 anyref) (result i64)
(block
(if
(i32.eqz
(global.get $hangLimit)
)
(return
- (ref.func $log-exnref)
+ (i64.const -2147483647)
)
)
(global.set $hangLimit
@@ -918,80 +423,40 @@
)
)
)
- (ref.null func)
+ (i64.const 6438275382591167256)
)
- (func $func_18 (param $0 externref) (param $1 i32) (param $2 v128) (param $3 i64) (result externref)
- (local $4 funcref)
- (local $5 eqref)
- (local $6 eqref)
- (local $7 (f64 funcref f64 i32))
- (local $8 externref)
- (local $9 i32)
- (local $10 i64)
- (local $11 eqref)
- (local $12 externref)
- (local $13 funcref)
- (local $14 f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $8)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0 (result externref)
- (nop)
- (local.get $0)
- )
- )
- (func $func_19 (param $0 f32) (param $1 eqref) (result anyref)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (ref.null any)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (ref.null any)
- )
- (func $func_19_invoker
+ (func $func_8_invoker
(drop
- (call $func_19
- (f32.const 58)
- (ref.null eq)
+ (call $func_8
+ (f32.const -nan:0x7fffcb)
+ (i32.const -51)
+ (ref.null any)
)
)
- (call $log-i32
- (call $hashMemory)
- )
)
- (func $func_21 (param $0 v128) (result funcref)
- (local $1 i64)
+ (func $func_10 (result funcref anyref f32 exnref)
+ (local $0 f64)
+ (local $1 v128)
+ (local $2 (i32 eqref anyref exnref))
+ (local $3 eqref)
+ (local $4 externref)
+ (local $5 anyref)
+ (local $6 f64)
+ (local $7 funcref)
+ (local $8 (i64 externref v128 f64 f32 exnref))
+ (local $9 anyref)
(block
(if
(i32.eqz
(global.get $hangLimit)
)
(return
- (ref.func $hashMemory)
+ (tuple.make
+ (ref.null func)
+ (ref.null any)
+ (f32.const -nan:0x7ffffc)
+ (ref.null exn)
+ )
)
)
(global.set $hangLimit
@@ -1001,127 +466,21 @@
)
)
)
- (block $label$0 (result funcref)
- (drop
- (tuple.make
- (ref.null exn)
- (ref.null eq)
- (i32.const 26)
- (v128.const i32x4 0x1715037b 0x00000027 0x000007ff 0xf8000000)
- (f64.const 9.532824124368358e-130)
- )
- )
+ (block (result funcref anyref f32 exnref)
(block $label$1
- (block $label$2
- (local.tee $1
- (i64.shr_s
- (loop $label$3 (result i64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (ref.func $log-f32)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block (result i64)
- (nop)
- (br_if $label$3
- (i32.eqz
- (i32.const -32766)
- )
- )
- (i64.trunc_f32_s
- (f32.min
- (f32.load offset=3
- (i32.and
- (i32.const 454758683)
- (i32.const 15)
- )
- )
- (f32.const 1023.5869750976562)
- )
- )
- )
- )
- (if
- (i32.eqz
- (i32.const 2049)
- )
- (block $label$4
- (nop)
- (br $label$1)
- )
- (block $label$5
- (i64.store16 offset=2
- (i32.and
- (block $label$6 (result i32)
- (call $log-i64
- (i64.const 1949228928397086024)
- )
- (i32.const 2)
- )
- (i32.const 15)
- )
- (local.get $1)
- )
- (br $label$2)
- )
- )
- )
- )
- (nop)
+ (call $log-i32
+ (call $hashMemory)
)
- (block $label$7
- (nop)
+ (call $log-v128
+ (local.get $1)
)
)
- (call $func_21
- (if (result v128)
- (i32.eqz
- (i32.const 760829235)
- )
- (block $label$8
- (return
- (ref.null func)
- )
- )
- (loop $label$9 (result v128)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (ref.func $func_19)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block (result v128)
- (nop)
- (br_if $label$9
- (ref.is_null
- (global.get $global$2)
- )
- )
- (local.get $0)
- )
- )
- )
+ (nop)
+ (tuple.make
+ (ref.func $func_10)
+ (ref.null any)
+ (f32.const 7710)
+ (ref.null exn)
)
)
)