summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/gen-s-parser.py7
-rw-r--r--src/binaryen-c.cpp5
-rw-r--r--src/binaryen-c.h3
-rw-r--r--src/gen-s-parser.inc20
-rw-r--r--src/js/binaryen.js-post.js12
-rw-r--r--src/passes/Print.cpp9
-rw-r--r--src/wasm-binary.h6
-rw-r--r--src/wasm-interpreter.h7
-rw-r--r--src/wasm-s-parser.h2
-rw-r--r--src/wasm/wasm-binary.cpp15
-rw-r--r--src/wasm/wasm-s-parser.cpp10
-rw-r--r--src/wasm/wasm-stack.cpp9
-rw-r--r--src/wasm/wasm.cpp6
-rw-r--r--src/wasm2js.h3
-rw-r--r--test/binaryen.js/expressions.js16
-rw-r--r--test/heap-types.wast5
-rw-r--r--test/heap-types.wast.from-wast21
-rw-r--r--test/heap-types.wast.fromBinary21
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo21
19 files changed, 182 insertions, 16 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index 19cf093be..ff6172138 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -529,7 +529,7 @@ instructions = [
# reference types instructions
# TODO Add table instructions
("ref.null", "makeRefNull(s)"),
- ("ref.is_null", "makeRefIs(s)"),
+ ("ref.is_null", "makeRefIs(s, RefIsNull)"),
("ref.func", "makeRefFunc(s)"),
# exception handling instructions
("try", "makeTry(s)"),
@@ -564,7 +564,10 @@ instructions = [
("array.get_s", "makeArrayGet(s, true)"),
("array.get_u", "makeArrayGet(s, false)"),
("array.set", "makeArraySet(s)"),
- ("array.len", "makeArrayLen(s)")
+ ("array.len", "makeArrayLen(s)"),
+ ("ref.is_func", "makeRefIs(s, RefIsFunc)"),
+ ("ref.is_data", "makeRefIs(s, RefIsData)"),
+ ("ref.is_i31", "makeRefIs(s, RefIsI31)"),
]
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index d66efbe8b..545c4ab94 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -706,6 +706,9 @@ BinaryenOp BinaryenWidenHighUVecI16x8ToVecI32x4(void) {
}
BinaryenOp BinaryenSwizzleVec8x16(void) { return SwizzleVec8x16; }
BinaryenOp BinaryenRefIsNull(void) { return RefIsNull; }
+BinaryenOp BinaryenRefIsFunc(void) { return RefIsFunc; }
+BinaryenOp BinaryenRefIsData(void) { return RefIsData; }
+BinaryenOp BinaryenRefIsI31(void) { return RefIsI31; }
BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module,
const char* name,
@@ -2697,7 +2700,7 @@ void BinaryenMemoryFillSetSize(BinaryenExpressionRef expr,
assert(sizeExpr);
static_cast<MemoryFill*>(expression)->size = (Expression*)sizeExpr;
}
-// RefIsNull
+// RefIs
BinaryenExpressionRef BinaryenRefIsGetValue(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<RefIs>());
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 7a7ff9e30..83424ceb6 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -559,6 +559,9 @@ BINARYEN_API BinaryenOp BinaryenWidenLowUVecI16x8ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenWidenHighUVecI16x8ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenSwizzleVec8x16(void);
BINARYEN_API BinaryenOp BinaryenRefIsNull(void);
+BINARYEN_API BinaryenOp BinaryenRefIsFunc(void);
+BINARYEN_API BinaryenOp BinaryenRefIsData(void);
+BINARYEN_API BinaryenOp BinaryenRefIsI31(void);
BINARYEN_REF(Expression);
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 219e07ea4..2bc0ba36d 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -2833,9 +2833,23 @@ switch (op[0]) {
case 'f':
if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); }
goto parse_error;
- case 'i':
- if (strcmp(op, "ref.is_null") == 0) { return makeRefIs(s); }
- goto parse_error;
+ case 'i': {
+ switch (op[7]) {
+ case 'd':
+ if (strcmp(op, "ref.is_data") == 0) { return makeRefIs(s, RefIsData); }
+ goto parse_error;
+ case 'f':
+ if (strcmp(op, "ref.is_func") == 0) { return makeRefIs(s, RefIsFunc); }
+ goto parse_error;
+ case 'i':
+ if (strcmp(op, "ref.is_i31") == 0) { return makeRefIs(s, RefIsI31); }
+ goto parse_error;
+ case 'n':
+ if (strcmp(op, "ref.is_null") == 0) { return makeRefIs(s, RefIsNull); }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
case 'n':
if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); }
goto parse_error;
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index c6d1fe31d..9c9c4e036 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -487,6 +487,9 @@ function initializeConstants() {
'WidenHighUVecI16x8ToVecI32x4',
'SwizzleVec8x16',
'RefIsNull',
+ 'RefIsFunc',
+ 'RefIsData',
+ 'RefIsI31',
].forEach(name => {
Module['Operations'][name] = Module[name] = Module['_Binaryen' + name]();
});
@@ -2105,6 +2108,15 @@ function wrapModule(module, self = {}) {
'is_null'(value) {
return Module['_BinaryenRefIs'](module, Module['RefIsNull'], value);
},
+ 'is_func'(value) {
+ return Module['_BinaryenRefIs'](module, Module['RefIsFunc'], value);
+ },
+ 'is_data'(value) {
+ return Module['_BinaryenRefIs'](module, Module['RefIsData'], value);
+ },
+ 'is_i31'(value) {
+ return Module['_BinaryenRefIs'](module, Module['RefIsI31'], value);
+ },
'func'(func, type) {
return preserveStack(() => Module['_BinaryenRefFunc'](module, strToStack(func), type));
},
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 243c3ff8d..ba1371d9e 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1717,6 +1717,15 @@ struct PrintExpressionContents
case RefIsNull:
printMedium(o, "ref.is_null");
break;
+ case RefIsFunc:
+ printMedium(o, "ref.is_func");
+ break;
+ case RefIsData:
+ printMedium(o, "ref.is_data");
+ break;
+ case RefIsI31:
+ printMedium(o, "ref.is_i31");
+ break;
default:
WASM_UNREACHABLE("unimplemented ref.is_*");
}
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 2df38b282..4e1095056 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1034,7 +1034,11 @@ enum ASTNodes {
RttSub = 0x31,
RefTest = 0x40,
RefCast = 0x41,
- BrOnCast = 0x42
+ BrOnCast = 0x42,
+ RefIsFunc = 0x50,
+ RefIsData = 0x51,
+ RefIsI31 = 0x52
+
};
enum MemoryAccess {
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 1d07af46a..e8716efbc 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1317,6 +1317,13 @@ public:
switch (curr->op) {
case RefIsNull:
return Literal(value.isNull());
+ case RefIsFunc:
+ return Literal(!value.isNull() && value.type.isFunction());
+ case RefIsData:
+ return Literal(!value.isNull() && value.isGCData());
+ case RefIsI31:
+ return Literal(!value.isNull() &&
+ value.type.getHeapType() == HeapType::i31);
default:
WASM_UNREACHABLE("unimplemented ref.is_*");
}
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 0fba3bba0..db7b41178 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -244,7 +244,7 @@ private:
Expression* makeBreakTable(Element& s);
Expression* makeReturn(Element& s);
Expression* makeRefNull(Element& s);
- Expression* makeRefIs(Element& s);
+ Expression* makeRefIs(Element& s, RefIsOp op);
Expression* makeRefFunc(Element& s);
Expression* makeRefEq(Element& s);
Expression* makeTry(Element& s);
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b3f085b36..fc14510e9 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -3046,6 +3046,12 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitArrayLen(curr, opcode)) {
break;
}
+ if (opcode == BinaryConsts::RefIsFunc ||
+ opcode == BinaryConsts::RefIsData ||
+ opcode == BinaryConsts::RefIsI31) {
+ visitRefIs((curr = allocator.alloc<RefIs>())->cast<RefIs>(), opcode);
+ break;
+ }
throwError("invalid code after GC prefix: " + std::to_string(opcode));
break;
}
@@ -5534,6 +5540,15 @@ void WasmBinaryBuilder::visitRefIs(RefIs* curr, uint8_t code) {
case BinaryConsts::RefIsNull:
curr->op = RefIsNull;
break;
+ case BinaryConsts::RefIsFunc:
+ curr->op = RefIsFunc;
+ break;
+ case BinaryConsts::RefIsData:
+ curr->op = RefIsData;
+ break;
+ case BinaryConsts::RefIsI31:
+ curr->op = RefIsI31;
+ break;
default:
WASM_UNREACHABLE("invalid code for ref.is_*");
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index b2212db18..b9927cbc7 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -51,7 +51,7 @@ int unhex(char c) {
namespace wasm {
static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), I8("i8"),
- I16("i16"), RTT("rtt"), REF_IS_NULL("ref.is_null");
+ I16("i16"), RTT("rtt");
static Address getAddress(const Element* s) { return atoll(s->c_str()); }
@@ -1922,13 +1922,9 @@ Expression* SExpressionWasmBuilder::makeRefNull(Element& s) {
return ret;
}
-Expression* SExpressionWasmBuilder::makeRefIs(Element& s) {
+Expression* SExpressionWasmBuilder::makeRefIs(Element& s, RefIsOp op) {
auto ret = allocator.alloc<RefIs>();
- if (*s[0] == REF_IS_NULL) {
- ret->op = RefIsNull;
- } else {
- WASM_UNREACHABLE("unimplemented ref.is_*");
- }
+ ret->op = op;
ret->value = parseExpression(s[1]);
ret->finalize();
return ret;
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 7b902ad67..5609dbb0e 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1869,6 +1869,15 @@ void BinaryInstWriter::visitRefIs(RefIs* curr) {
case RefIsNull:
o << int8_t(BinaryConsts::RefIsNull);
break;
+ case RefIsFunc:
+ o << int8_t(BinaryConsts::GCPrefix) << int8_t(BinaryConsts::RefIsFunc);
+ break;
+ case RefIsData:
+ o << int8_t(BinaryConsts::GCPrefix) << int8_t(BinaryConsts::RefIsData);
+ break;
+ case RefIsI31:
+ o << int8_t(BinaryConsts::GCPrefix) << int8_t(BinaryConsts::RefIsI31);
+ break;
default:
WASM_UNREACHABLE("unimplemented ref.is_*");
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index f2f08033e..cd1fb716c 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -192,6 +192,12 @@ const char* getExpressionName(Expression* curr) {
switch (curr->cast<RefIs>()->op) {
case RefIsNull:
return "ref.is_null";
+ case RefIsFunc:
+ return "ref.is_func";
+ case RefIsData:
+ return "ref.is_data";
+ case RefIsI31:
+ return "ref.is_i31";
default:
WASM_UNREACHABLE("unimplemented ref.is_*");
}
diff --git a/src/wasm2js.h b/src/wasm2js.h
index ba7b55c08..4a58a20d8 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -1637,7 +1637,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
RSHIFT,
ValueBuilder::makeNum(16));
}
- default: { WASM_UNREACHABLE("unhandled unary"); }
+ default:
+ WASM_UNREACHABLE("unhandled unary");
}
}
case Type::f32:
diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js
index 6d4fa8011..3d2a5d138 100644
--- a/test/binaryen.js/expressions.js
+++ b/test/binaryen.js/expressions.js
@@ -1377,6 +1377,22 @@ console.log("# RefIs");
"(ref.is_null\n (local.get $2)\n)\n"
);
+ assert(
+ binaryen.RefIs(module.ref.is_func(value)).toText()
+ ==
+ "(ref.is_func\n (local.get $2)\n)\n"
+ );
+ assert(
+ binaryen.RefIs(module.ref.is_data(value)).toText()
+ ==
+ "(ref.is_data\n (local.get $2)\n)\n"
+ );
+ assert(
+ binaryen.RefIs(module.ref.is_i31(value)).toText()
+ ==
+ "(ref.is_i31\n (local.get $2)\n)\n"
+ );
+
module.dispose();
})();
diff --git a/test/heap-types.wast b/test/heap-types.wast
index da8baf1e0..614bbb1c5 100644
--- a/test/heap-types.wast
+++ b/test/heap-types.wast
@@ -182,4 +182,9 @@
)
)
)
+ (func $ref.is_X (param $x anyref)
+ (if (ref.is_func (local.get $x)) (unreachable))
+ (if (ref.is_data (local.get $x)) (unreachable))
+ (if (ref.is_i31 (local.get $x)) (unreachable))
+ )
)
diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast
index 33c86b903..b717de63f 100644
--- a/test/heap-types.wast.from-wast
+++ b/test/heap-types.wast.from-wast
@@ -4,6 +4,7 @@
(type ${} (struct ))
(type ${mut:f32} (struct (field (mut f32))))
(type $none_=>_none (func))
+ (type $anyref_=>_none (func (param anyref)))
(type ${i32} (struct (field i32)))
(type ${i32_i64} (struct (field i32) (field i64)))
(type $[mut:i32] (array (mut i32)))
@@ -196,4 +197,24 @@
)
)
)
+ (func $ref.is_X (param $x anyref)
+ (if
+ (ref.is_func
+ (local.get $x)
+ )
+ (unreachable)
+ )
+ (if
+ (ref.is_data
+ (local.get $x)
+ )
+ (unreachable)
+ )
+ (if
+ (ref.is_i31
+ (local.get $x)
+ )
+ (unreachable)
+ )
+ )
)
diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary
index 2e1f25235..5b6dca2f6 100644
--- a/test/heap-types.wast.fromBinary
+++ b/test/heap-types.wast.fromBinary
@@ -4,6 +4,7 @@
(type ${} (struct ))
(type ${mut:f32} (struct (field (mut f32))))
(type $none_=>_none (func))
+ (type $anyref_=>_none (func (param anyref)))
(type ${i32} (struct (field i32)))
(type ${i32_i64} (struct (field i32) (field i64)))
(type $[mut:i32] (array (mut i32)))
@@ -195,5 +196,25 @@
)
)
)
+ (func $ref.is_X (param $x anyref)
+ (if
+ (ref.is_func
+ (local.get $x)
+ )
+ (unreachable)
+ )
+ (if
+ (ref.is_data
+ (local.get $x)
+ )
+ (unreachable)
+ )
+ (if
+ (ref.is_i31
+ (local.get $x)
+ )
+ (unreachable)
+ )
+ )
)
diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo
index beb9732a1..fef210e11 100644
--- a/test/heap-types.wast.fromBinary.noDebugInfo
+++ b/test/heap-types.wast.fromBinary.noDebugInfo
@@ -4,6 +4,7 @@
(type ${} (struct ))
(type ${mut:f32} (struct (field (mut f32))))
(type $none_=>_none (func))
+ (type $anyref_=>_none (func (param anyref)))
(type ${i32} (struct (field i32)))
(type ${i32_i64} (struct (field i32) (field i64)))
(type $[mut:i32] (array (mut i32)))
@@ -195,5 +196,25 @@
)
)
)
+ (func $5 (param $0 anyref)
+ (if
+ (ref.is_func
+ (local.get $0)
+ )
+ (unreachable)
+ )
+ (if
+ (ref.is_data
+ (local.get $0)
+ )
+ (unreachable)
+ )
+ (if
+ (ref.is_i31
+ (local.get $0)
+ )
+ (unreachable)
+ )
+ )
)