diff options
-rwxr-xr-x | scripts/gen-s-parser.py | 7 | ||||
-rw-r--r-- | src/binaryen-c.cpp | 5 | ||||
-rw-r--r-- | src/binaryen-c.h | 3 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 20 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 12 | ||||
-rw-r--r-- | src/passes/Print.cpp | 9 | ||||
-rw-r--r-- | src/wasm-binary.h | 6 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 7 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 2 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 15 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 10 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 9 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 6 | ||||
-rw-r--r-- | src/wasm2js.h | 3 | ||||
-rw-r--r-- | test/binaryen.js/expressions.js | 16 | ||||
-rw-r--r-- | test/heap-types.wast | 5 | ||||
-rw-r--r-- | test/heap-types.wast.from-wast | 21 | ||||
-rw-r--r-- | test/heap-types.wast.fromBinary | 21 | ||||
-rw-r--r-- | test/heap-types.wast.fromBinary.noDebugInfo | 21 |
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) + ) + ) ) |