diff options
-rwxr-xr-x | scripts/gen-s-parser.py | 20 | ||||
-rw-r--r-- | src/binaryen-c.cpp | 47 | ||||
-rw-r--r-- | src/binaryen-c.h | 24 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 195 | ||||
-rw-r--r-- | src/ir/ExpressionAnalyzer.cpp | 34 | ||||
-rw-r--r-- | src/ir/ExpressionManipulator.cpp | 36 | ||||
-rw-r--r-- | src/ir/ReFinalize.cpp | 15 | ||||
-rw-r--r-- | src/ir/effects.h | 30 | ||||
-rw-r--r-- | src/ir/utils.h | 24 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 14 | ||||
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 24 | ||||
-rw-r--r-- | src/passes/Print.cpp | 104 | ||||
-rw-r--r-- | src/wasm-binary.h | 37 | ||||
-rw-r--r-- | src/wasm-builder.h | 72 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 48 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 14 | ||||
-rw-r--r-- | src/wasm-stack.h | 12 | ||||
-rw-r--r-- | src/wasm-traversal.h | 192 | ||||
-rw-r--r-- | src/wasm.h | 96 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 212 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 98 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 56 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 88 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 37 | ||||
-rw-r--r-- | src/wasm2js.h | 48 | ||||
-rw-r--r-- | test/binaryen.js/kitchen-sink.js | 12 | ||||
-rw-r--r-- | test/binaryen.js/kitchen-sink.js.txt | 12 |
27 files changed, 1556 insertions, 45 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 5bf5ec942..4c33fcf78 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -500,7 +500,25 @@ instructions = [ ("ref.eq", "makeRefEq(s)"), ("i31.new", "makeI31New(s)"), ("i31.get_s", "makeI31Get(s, true)"), - ("i31.get_u", "makeI31Get(s, false)") + ("i31.get_u", "makeI31Get(s, false)"), + ("ref.test", "makeRefTest(s)"), + ("ref.cast", "makeRefCast(s)"), + ("br_on_cast", "makeBrOnCast(s)"), + ("rtt.canon", "makeRttCanon(s)"), + ("rtt.sub", "makeRttSub(s)"), + ("struct.new_with_rtt", "makeStructNew(s, false)"), + ("struct.new_default_with_rtt", "makeStructNew(s, true)"), + ("struct.get", "makeStructGet(s)"), + ("struct.get_s", "makeStructGet(s, true)"), + ("struct.get_u", "makeStructGet(s, false)"), + ("struct.set", "makeStructSet(s)"), + ("array.new_with_rtt", "makeArrayNew(s, false)"), + ("array.new_default_with_rtt", "makeArrayNew(s, true)"), + ("array.get", "makeArrayGet(s)"), + ("array.get_s", "makeArrayGet(s, true)"), + ("array.get_u", "makeArrayGet(s, false)"), + ("array.set", "makeArraySet(s)"), + ("array.len", "makeArrayLen(s)") ] diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 0fcb158d9..f4515208f 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -289,6 +289,40 @@ BinaryenExpressionId BinaryenTupleExtractId(void) { BinaryenExpressionId BinaryenPopId(void) { return Expression::Id::PopId; } BinaryenExpressionId BinaryenI31NewId(void) { return Expression::Id::I31NewId; } BinaryenExpressionId BinaryenI31GetId(void) { return Expression::Id::I31GetId; } +BinaryenExpressionId BinaryenRefTestId(void) { + return Expression::Id::RefTestId; +} +BinaryenExpressionId BinaryenRefCastId(void) { + return Expression::Id::RefCastId; +} +BinaryenExpressionId BinaryenBrOnCastId(void) { + return Expression::Id::BrOnCastId; +} +BinaryenExpressionId BinaryenRttCanonId(void) { + return Expression::Id::RttCanonId; +} +BinaryenExpressionId BinaryenRttSubId(void) { return Expression::Id::RttSubId; } +BinaryenExpressionId BinaryenStructNewId(void) { + return Expression::Id::StructNewId; +} +BinaryenExpressionId BinaryenStructGetId(void) { + return Expression::Id::StructGetId; +} +BinaryenExpressionId BinaryenStructSetId(void) { + return Expression::Id::StructSetId; +} +BinaryenExpressionId BinaryenArrayNewId(void) { + return Expression::Id::ArrayNewId; +} +BinaryenExpressionId BinaryenArrayGetId(void) { + return Expression::Id::ArrayGetId; +} +BinaryenExpressionId BinaryenArraySetId(void) { + return Expression::Id::ArraySetId; +} +BinaryenExpressionId BinaryenArrayLenId(void) { + return Expression::Id::ArrayLenId; +} // External kinds @@ -1353,6 +1387,19 @@ BinaryenExpressionRef BinaryenI31Get(BinaryenModuleRef module, Builder(*(Module*)module).makeI31Get((Expression*)i31, signed_ != 0)); } +// TODO (gc): ref.test +// TODO (gc): ref.cast +// TODO (gc): br_on_cast +// TODO (gc): rtt.canon +// TODO (gc): rtt.sub +// TODO (gc): struct.new +// TODO (gc): struct.get +// TODO (gc): struct.set +// TODO (gc): array.new +// TODO (gc): array.get +// TODO (gc): array.set +// TODO (gc): array.len + // Expression utility BinaryenExpressionId BinaryenExpressionGetId(BinaryenExpressionRef expr) { diff --git a/src/binaryen-c.h b/src/binaryen-c.h index f695fa6f0..4ca76657d 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -176,6 +176,18 @@ BINARYEN_API BinaryenExpressionId BinaryenTupleExtractId(void); BINARYEN_API BinaryenExpressionId BinaryenPopId(void); BINARYEN_API BinaryenExpressionId BinaryenI31NewId(void); BINARYEN_API BinaryenExpressionId BinaryenI31GetId(void); +BINARYEN_API BinaryenExpressionId BinaryenRefTestId(void); +BINARYEN_API BinaryenExpressionId BinaryenRefCastId(void); +BINARYEN_API BinaryenExpressionId BinaryenBrOnCastId(void); +BINARYEN_API BinaryenExpressionId BinaryenRttCanonId(void); +BINARYEN_API BinaryenExpressionId BinaryenRttSubId(void); +BINARYEN_API BinaryenExpressionId BinaryenStructNewId(void); +BINARYEN_API BinaryenExpressionId BinaryenStructGetId(void); +BINARYEN_API BinaryenExpressionId BinaryenStructSetId(void); +BINARYEN_API BinaryenExpressionId BinaryenArrayNewId(void); +BINARYEN_API BinaryenExpressionId BinaryenArrayGetId(void); +BINARYEN_API BinaryenExpressionId BinaryenArraySetId(void); +BINARYEN_API BinaryenExpressionId BinaryenArrayLenId(void); // External kinds (call to get the value of each; you can cache them) @@ -867,6 +879,18 @@ BINARYEN_API BinaryenExpressionRef BinaryenI31New(BinaryenModuleRef module, BINARYEN_API BinaryenExpressionRef BinaryenI31Get(BinaryenModuleRef module, BinaryenExpressionRef i31, int signed_); +// TODO (gc): ref.test +// TODO (gc): ref.cast +// TODO (gc): br_on_cast +// TODO (gc): rtt.canon +// TODO (gc): rtt.sub +// TODO (gc): struct.new +// TODO (gc): struct.get +// TODO (gc): struct.set +// TODO (gc): array.new +// TODO (gc): array.get +// TODO (gc): array.set +// TODO (gc): array.len // Expression diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 041a6d519..8a2c9163c 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -4,17 +4,63 @@ #ifdef INSTRUCTION_PARSER #undef INSTRUCTION_PARSER -char op[27] = {'\0'}; -strncpy(op, s[0]->c_str(), 26); +char op[28] = {'\0'}; +strncpy(op, s[0]->c_str(), 27); switch (op[0]) { case 'a': { - switch (op[7]) { - case 'f': - if (strcmp(op, "atomic.fence") == 0) { return makeAtomicFence(s); } - goto parse_error; - case 'n': - if (strcmp(op, "atomic.notify") == 0) { return makeAtomicNotify(s); } - goto parse_error; + switch (op[1]) { + case 'r': { + switch (op[6]) { + case 'g': { + switch (op[9]) { + case '\0': + if (strcmp(op, "array.get") == 0) { return makeArrayGet(s); } + goto parse_error; + case '_': { + switch (op[10]) { + case 's': + if (strcmp(op, "array.get_s") == 0) { return makeArrayGet(s, true); } + goto parse_error; + case 'u': + if (strcmp(op, "array.get_u") == 0) { return makeArrayGet(s, false); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } + case 'l': + if (strcmp(op, "array.len") == 0) { return makeArrayLen(s); } + goto parse_error; + case 'n': { + switch (op[10]) { + case 'd': + if (strcmp(op, "array.new_default_with_rtt") == 0) { return makeArrayNew(s, true); } + goto parse_error; + case 'w': + if (strcmp(op, "array.new_with_rtt") == 0) { return makeArrayNew(s, false); } + goto parse_error; + default: goto parse_error; + } + } + case 's': + if (strcmp(op, "array.set") == 0) { return makeArraySet(s); } + goto parse_error; + default: goto parse_error; + } + } + case 't': { + switch (op[7]) { + case 'f': + if (strcmp(op, "atomic.fence") == 0) { return makeAtomicFence(s); } + goto parse_error; + case 'n': + if (strcmp(op, "atomic.notify") == 0) { return makeAtomicNotify(s); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } @@ -33,9 +79,17 @@ switch (op[0]) { case 'i': if (strcmp(op, "br_if") == 0) { return makeBreak(s); } goto parse_error; - case 'o': - if (strcmp(op, "br_on_exn") == 0) { return makeBrOnExn(s); } - goto parse_error; + case 'o': { + switch (op[6]) { + case 'c': + if (strcmp(op, "br_on_cast") == 0) { return makeBrOnCast(s); } + goto parse_error; + case 'e': + if (strcmp(op, "br_on_exn") == 0) { return makeBrOnExn(s); } + goto parse_error; + default: goto parse_error; + } + } case 't': if (strcmp(op, "br_table") == 0) { return makeBreakTable(s); } goto parse_error; @@ -2545,41 +2599,95 @@ switch (op[0]) { if (strcmp(op, "pop") == 0) { return makePop(s); } goto parse_error; case 'r': { - switch (op[2]) { - case 'f': { + switch (op[1]) { + case 'e': { + switch (op[2]) { + case 'f': { + switch (op[4]) { + case 'c': + if (strcmp(op, "ref.cast") == 0) { return makeRefCast(s); } + goto parse_error; + 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; + case 'i': + if (strcmp(op, "ref.is_null") == 0) { return makeRefIsNull(s); } + goto parse_error; + case 'n': + if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); } + goto parse_error; + case 't': + if (strcmp(op, "ref.test") == 0) { return makeRefTest(s); } + goto parse_error; + default: goto parse_error; + } + } + case 't': { + switch (op[3]) { + case 'h': + if (strcmp(op, "rethrow") == 0) { return makeRethrow(s); } + goto parse_error; + case 'u': { + switch (op[6]) { + case '\0': + if (strcmp(op, "return") == 0) { return makeReturn(s); } + goto parse_error; + case '_': { + switch (op[11]) { + case '\0': + if (strcmp(op, "return_call") == 0) { return makeCall(s, /*isReturn=*/true); } + goto parse_error; + case '_': + if (strcmp(op, "return_call_indirect") == 0) { return makeCallIndirect(s, /*isReturn=*/true); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } + default: goto parse_error; + } + } + default: goto parse_error; + } + } + case 't': { switch (op[4]) { - case 'e': - if (strcmp(op, "ref.eq") == 0) { return makeRefEq(s); } + case 'c': + if (strcmp(op, "rtt.canon") == 0) { return makeRttCanon(s); } goto parse_error; - case 'f': - if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); } - goto parse_error; - case 'i': - if (strcmp(op, "ref.is_null") == 0) { return makeRefIsNull(s); } - goto parse_error; - case 'n': - if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); } + case 's': + if (strcmp(op, "rtt.sub") == 0) { return makeRttSub(s); } goto parse_error; default: goto parse_error; } } + default: goto parse_error; + } + } + case 's': { + switch (op[1]) { + case 'e': + if (strcmp(op, "select") == 0) { return makeSelect(s); } + goto parse_error; case 't': { - switch (op[3]) { - case 'h': - if (strcmp(op, "rethrow") == 0) { return makeRethrow(s); } - goto parse_error; - case 'u': { - switch (op[6]) { + switch (op[7]) { + case 'g': { + switch (op[10]) { case '\0': - if (strcmp(op, "return") == 0) { return makeReturn(s); } + if (strcmp(op, "struct.get") == 0) { return makeStructGet(s); } goto parse_error; case '_': { switch (op[11]) { - case '\0': - if (strcmp(op, "return_call") == 0) { return makeCall(s, /*isReturn=*/true); } + case 's': + if (strcmp(op, "struct.get_s") == 0) { return makeStructGet(s, true); } goto parse_error; - case '_': - if (strcmp(op, "return_call_indirect") == 0) { return makeCallIndirect(s, /*isReturn=*/true); } + case 'u': + if (strcmp(op, "struct.get_u") == 0) { return makeStructGet(s, false); } goto parse_error; default: goto parse_error; } @@ -2587,15 +2695,26 @@ switch (op[0]) { default: goto parse_error; } } + case 'n': { + switch (op[11]) { + case 'd': + if (strcmp(op, "struct.new_default_with_rtt") == 0) { return makeStructNew(s, true); } + goto parse_error; + case 'w': + if (strcmp(op, "struct.new_with_rtt") == 0) { return makeStructNew(s, false); } + goto parse_error; + default: goto parse_error; + } + } + case 's': + if (strcmp(op, "struct.set") == 0) { return makeStructSet(s); } + goto parse_error; default: goto parse_error; } } default: goto parse_error; } } - case 's': - if (strcmp(op, "select") == 0) { return makeSelect(s); } - goto parse_error; case 't': { switch (op[1]) { case 'h': { diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp index 562631420..9b0bdd007 100644 --- a/src/ir/ExpressionAnalyzer.cpp +++ b/src/ir/ExpressionAnalyzer.cpp @@ -237,6 +237,40 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) { } void visitI31New(I31New* curr) {} void visitI31Get(I31Get* curr) { visitor.visitInt(curr->signed_); } + void visitRefTest(RefTest* curr) { + WASM_UNREACHABLE("TODO (gc): ref.test"); + } + void visitRefCast(RefCast* curr) { + WASM_UNREACHABLE("TODO (gc): ref.cast"); + } + void visitBrOnCast(BrOnCast* curr) { + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + } + void visitRttCanon(RttCanon* curr) { + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + } + void visitRttSub(RttSub* curr) { WASM_UNREACHABLE("TODO (gc): rtt.sub"); } + void visitStructNew(StructNew* curr) { + WASM_UNREACHABLE("TODO (gc): struct.new"); + } + void visitStructGet(StructGet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.get"); + } + void visitStructSet(StructSet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.set"); + } + void visitArrayNew(ArrayNew* curr) { + WASM_UNREACHABLE("TODO (gc): array.new"); + } + void visitArrayGet(ArrayGet* curr) { + WASM_UNREACHABLE("TODO (gc): array.get"); + } + void visitArraySet(ArraySet* curr) { + WASM_UNREACHABLE("TODO (gc): array.set"); + } + void visitArrayLen(ArrayLen* curr) { + WASM_UNREACHABLE("TODO (gc): array.len"); + } } singleton(curr, visitor); } diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp index b0616e34d..5fb98d86a 100644 --- a/src/ir/ExpressionManipulator.cpp +++ b/src/ir/ExpressionManipulator.cpp @@ -275,6 +275,42 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) { Expression* visitI31Get(I31Get* curr) { return builder.makeI31Get(copy(curr->i31), curr->signed_); } + Expression* visitRefTest(RefTest* curr) { + WASM_UNREACHABLE("TODO (gc): ref.test"); + } + Expression* visitRefCast(RefCast* curr) { + WASM_UNREACHABLE("TODO (gc): ref.cast"); + } + Expression* visitBrOnCast(BrOnCast* curr) { + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + } + Expression* visitRttCanon(RttCanon* curr) { + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + } + Expression* visitRttSub(RttSub* curr) { + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + } + Expression* visitStructNew(StructNew* curr) { + WASM_UNREACHABLE("TODO (gc): struct.new"); + } + Expression* visitStructGet(StructGet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.get"); + } + Expression* visitStructSet(StructSet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.set"); + } + Expression* visitArrayNew(ArrayNew* curr) { + WASM_UNREACHABLE("TODO (gc): array.new"); + } + Expression* visitArrayGet(ArrayGet* curr) { + WASM_UNREACHABLE("TODO (gc): array.get"); + } + Expression* visitArraySet(ArraySet* curr) { + WASM_UNREACHABLE("TODO (gc): array.set"); + } + Expression* visitArrayLen(ArrayLen* curr) { + WASM_UNREACHABLE("TODO (gc): array.len"); + } }; Copier copier(wasm, custom); diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index c6b3ab855..c3516be0a 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -143,6 +143,21 @@ void ReFinalize::visitTupleMake(TupleMake* curr) { curr->finalize(); } void ReFinalize::visitTupleExtract(TupleExtract* curr) { curr->finalize(); } void ReFinalize::visitI31New(I31New* curr) { curr->finalize(); } void ReFinalize::visitI31Get(I31Get* curr) { curr->finalize(); } +void ReFinalize::visitRefTest(RefTest* curr) { curr->finalize(); } +void ReFinalize::visitRefCast(RefCast* curr) { curr->finalize(); } +void ReFinalize::visitBrOnCast(BrOnCast* curr) { + curr->finalize(); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); +} +void ReFinalize::visitRttCanon(RttCanon* curr) { curr->finalize(); } +void ReFinalize::visitRttSub(RttSub* curr) { curr->finalize(); } +void ReFinalize::visitStructNew(StructNew* curr) { curr->finalize(); } +void ReFinalize::visitStructGet(StructGet* curr) { curr->finalize(); } +void ReFinalize::visitStructSet(StructSet* curr) { curr->finalize(); } +void ReFinalize::visitArrayNew(ArrayNew* curr) { curr->finalize(); } +void ReFinalize::visitArrayGet(ArrayGet* curr) { curr->finalize(); } +void ReFinalize::visitArraySet(ArraySet* curr) { curr->finalize(); } +void ReFinalize::visitArrayLen(ArrayLen* curr) { curr->finalize(); } void ReFinalize::visitFunction(Function* curr) { // we may have changed the body from unreachable to none, which might be bad diff --git a/src/ir/effects.h b/src/ir/effects.h index 8199092ea..dc6c10645 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -507,6 +507,36 @@ struct EffectAnalyzer void visitTupleExtract(TupleExtract* curr) {} void visitI31New(I31New* curr) {} void visitI31Get(I31Get* curr) {} + void visitRefTest(RefTest* curr) { WASM_UNREACHABLE("TODO (gc): ref.test"); } + void visitRefCast(RefCast* curr) { WASM_UNREACHABLE("TODO (gc): ref.cast"); } + void visitBrOnCast(BrOnCast* curr) { + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + } + void visitRttCanon(RttCanon* curr) { + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + } + void visitRttSub(RttSub* curr) { WASM_UNREACHABLE("TODO (gc): rtt.sub"); } + void visitStructNew(StructNew* curr) { + WASM_UNREACHABLE("TODO (gc): struct.new"); + } + void visitStructGet(StructGet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.get"); + } + void visitStructSet(StructSet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.set"); + } + void visitArrayNew(ArrayNew* curr) { + WASM_UNREACHABLE("TODO (gc): array.new"); + } + void visitArrayGet(ArrayGet* curr) { + WASM_UNREACHABLE("TODO (gc): array.get"); + } + void visitArraySet(ArraySet* curr) { + WASM_UNREACHABLE("TODO (gc): array.set"); + } + void visitArrayLen(ArrayLen* curr) { + WASM_UNREACHABLE("TODO (gc): array.len"); + } // Helpers diff --git a/src/ir/utils.h b/src/ir/utils.h index 7d8b28759..c2d7645f7 100644 --- a/src/ir/utils.h +++ b/src/ir/utils.h @@ -162,6 +162,18 @@ struct ReFinalize void visitTupleExtract(TupleExtract* curr); void visitI31New(I31New* curr); void visitI31Get(I31Get* curr); + void visitRefTest(RefTest* curr); + void visitRefCast(RefCast* curr); + void visitBrOnCast(BrOnCast* curr); + void visitRttCanon(RttCanon* curr); + void visitRttSub(RttSub* curr); + void visitStructNew(StructNew* curr); + void visitStructGet(StructGet* curr); + void visitStructSet(StructSet* curr); + void visitArrayNew(ArrayNew* curr); + void visitArrayGet(ArrayGet* curr); + void visitArraySet(ArraySet* curr); + void visitArrayLen(ArrayLen* curr); void visitFunction(Function* curr); @@ -234,6 +246,18 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> { void visitTupleExtract(TupleExtract* curr) { curr->finalize(); } void visitI31New(I31New* curr) { curr->finalize(); } void visitI31Get(I31Get* curr) { curr->finalize(); } + void visitRefTest(RefTest* curr) { curr->finalize(); } + void visitRefCast(RefCast* curr) { curr->finalize(); } + void visitBrOnCast(BrOnCast* curr) { curr->finalize(); } + void visitRttCanon(RttCanon* curr) { curr->finalize(); } + void visitRttSub(RttSub* curr) { curr->finalize(); } + void visitStructNew(StructNew* curr) { curr->finalize(); } + void visitStructGet(StructGet* curr) { curr->finalize(); } + void visitStructSet(StructSet* curr) { curr->finalize(); } + void visitArrayNew(ArrayNew* curr) { curr->finalize(); } + void visitArrayGet(ArrayGet* curr) { curr->finalize(); } + void visitArraySet(ArraySet* curr) { curr->finalize(); } + void visitArrayLen(ArrayLen* curr) { curr->finalize(); } void visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); } void visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index d3cf7d449..529474098 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -98,7 +98,19 @@ function initializeConstants() { 'TupleExtract', 'Pop', 'I31New', - 'I31Get' + 'I31Get', + 'RefTest', + 'RefCast', + 'BrOnCast', + 'RttCanon', + 'RttSub', + 'StructNew', + 'StructGet', + 'StructSet', + 'ArrayNew', + 'ArrayGet', + 'ArraySet', + 'ArrayLen' ].forEach(name => { Module['ExpressionIds'][name] = Module[name + 'Id'] = Module['_Binaryen' + name + 'Id'](); }); diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index 7562645e0..067bc81e1 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -379,6 +379,30 @@ struct DeadCodeElimination DELEGATE(I31New); case Expression::Id::I31GetId: DELEGATE(I31Get); + case Expression::Id::RefTestId: + DELEGATE(RefTest); + case Expression::Id::RefCastId: + DELEGATE(RefCast); + case Expression::Id::BrOnCastId: + DELEGATE(BrOnCast); + case Expression::Id::RttCanonId: + DELEGATE(RttCanon); + case Expression::Id::RttSubId: + DELEGATE(RttSub); + case Expression::Id::StructNewId: + DELEGATE(StructNew); + case Expression::Id::StructGetId: + DELEGATE(StructGet); + case Expression::Id::StructSetId: + DELEGATE(StructSet); + case Expression::Id::ArrayNewId: + DELEGATE(ArrayNew); + case Expression::Id::ArrayGetId: + DELEGATE(ArrayGet); + case Expression::Id::ArraySetId: + DELEGATE(ArraySet); + case Expression::Id::ArrayLenId: + DELEGATE(ArrayLen); case Expression::Id::InvalidId: WASM_UNREACHABLE("unimp"); case Expression::Id::NumExpressionIds: diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index ac115edc3..a8e5b0f9c 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1478,6 +1478,50 @@ struct PrintExpressionContents void visitI31Get(I31Get* curr) { printMedium(o, curr->signed_ ? "i31.get_s" : "i31.get_u"); } + void visitRefTest(RefTest* curr) { + printMedium(o, "ref.test"); + WASM_UNREACHABLE("TODO (gc): ref.test"); + } + void visitRefCast(RefCast* curr) { + printMedium(o, "ref.cast"); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + } + void visitBrOnCast(BrOnCast* curr) { + printMedium(o, "br_on_cast"); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + } + void visitRttCanon(RttCanon* curr) { + printMedium(o, "rtt.canon"); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + } + void visitRttSub(RttSub* curr) { + printMedium(o, "rtt.sub"); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + } + void visitStructNew(StructNew* curr) { + WASM_UNREACHABLE("TODO (gc): struct.new"); + } + void visitStructGet(StructGet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.get"); + } + void visitStructSet(StructSet* curr) { + printMedium(o, "struct.set"); + WASM_UNREACHABLE("TODO (gc): struct.set"); + } + void visitArrayNew(ArrayNew* curr) { + WASM_UNREACHABLE("TODO (gc): array.new"); + } + void visitArrayGet(ArrayGet* curr) { + WASM_UNREACHABLE("TODO (gc): array.get"); + } + void visitArraySet(ArraySet* curr) { + printMedium(o, "array.set"); + WASM_UNREACHABLE("TODO (gc): array.set"); + } + void visitArrayLen(ArrayLen* curr) { + printMedium(o, "array.len"); + WASM_UNREACHABLE("TODO (gc): array.len"); + } }; // Prints an expression in s-expr format, including both the @@ -2081,6 +2125,66 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { printFullLine(curr->i31); decIndent(); } + void visitRefTest(RefTest* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): ref.test"); + } + void visitRefCast(RefCast* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + } + void visitBrOnCast(BrOnCast* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + } + void visitRttCanon(RttCanon* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + } + void visitRttSub(RttSub* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + } + void visitStructNew(StructNew* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): struct.new"); + } + void visitStructGet(StructGet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): struct.get"); + } + void visitStructSet(StructSet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): struct.set"); + } + void visitArrayNew(ArrayNew* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): array.new"); + } + void visitArrayGet(ArrayGet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): array.get"); + } + void visitArraySet(ArraySet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): array.set"); + } + void visitArrayLen(ArrayLen* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + WASM_UNREACHABLE("TODO (gc): array.len"); + } // Module-level visitors void handleSignature(Signature curr, Name* funcName = nullptr) { o << "(func"; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index c869adf06..8c502d6b7 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -936,10 +936,6 @@ enum ASTNodes { RefIsNull = 0xd1, RefFunc = 0xd2, - // GC opcodes - - RefEq = 0xd5, - // exception handling opcodes Try = 0x06, @@ -950,9 +946,28 @@ enum ASTNodes { // gc opcodes + RefEq = 0xd5, + StructNewWithRtt = 0x01, + StructNewDefaultWithRtt = 0x02, + StructGet = 0x03, + StructGetS = 0x04, + StructGetU = 0x05, + StructSet = 0x06, + ArrayNewWithRtt = 0x11, + ArrayNewDefaultWithRtt = 0x12, + ArrayGet = 0x13, + ArrayGetS = 0x14, + ArrayGetU = 0x15, + ArraySet = 0x16, + ArrayLen = 0x17, I31New = 0x20, I31GetS = 0x21, - I31GetU = 0x22 + I31GetU = 0x22, + RttCanon = 0x30, + RttSub = 0x31, + RefTest = 0x40, + RefCast = 0x41, + BrOnCast = 0x42 }; enum MemoryAccess { @@ -1477,6 +1492,18 @@ public: bool maybeVisitMemoryFill(Expression*& out, uint32_t code); bool maybeVisitI31New(Expression*& out, uint32_t code); bool maybeVisitI31Get(Expression*& out, uint32_t code); + bool maybeVisitRefTest(Expression*& out, uint32_t code); + bool maybeVisitRefCast(Expression*& out, uint32_t code); + bool maybeVisitBrOnCast(Expression*& out, uint32_t code); + bool maybeVisitRttCanon(Expression*& out, uint32_t code); + bool maybeVisitRttSub(Expression*& out, uint32_t code); + bool maybeVisitStructNew(Expression*& out, uint32_t code); + bool maybeVisitStructGet(Expression*& out, uint32_t code); + bool maybeVisitStructSet(Expression*& out, uint32_t code); + bool maybeVisitArrayNew(Expression*& out, uint32_t code); + bool maybeVisitArrayGet(Expression*& out, uint32_t code); + bool maybeVisitArraySet(Expression*& out, uint32_t code); + bool maybeVisitArrayLen(Expression*& out, uint32_t code); void visitSelect(Select* curr, uint8_t code); void visitReturn(Return* curr); void visitMemorySize(MemorySize* curr); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index d90ccb9ae..a2f098a54 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -639,6 +639,78 @@ public: ret->finalize(); return ret; } + RefTest* makeRefTest() { + auto* ret = wasm.allocator.alloc<RefTest>(); + WASM_UNREACHABLE("TODO (gc): ref.test"); + ret->finalize(); + return ret; + } + RefCast* makeRefCast() { + auto* ret = wasm.allocator.alloc<RefCast>(); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + ret->finalize(); + return ret; + } + BrOnCast* makeBrOnCast() { + auto* ret = wasm.allocator.alloc<BrOnCast>(); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + ret->finalize(); + return ret; + } + RttCanon* makeRttCanon() { + auto* ret = wasm.allocator.alloc<RttCanon>(); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + ret->finalize(); + return ret; + } + RttSub* makeRttSub() { + auto* ret = wasm.allocator.alloc<RttSub>(); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + ret->finalize(); + return ret; + } + StructNew* makeStructNew() { + auto* ret = wasm.allocator.alloc<StructNew>(); + WASM_UNREACHABLE("TODO (gc): struct.new"); + ret->finalize(); + return ret; + } + StructGet* makeStructGet() { + auto* ret = wasm.allocator.alloc<StructGet>(); + WASM_UNREACHABLE("TODO (gc): struct.get"); + ret->finalize(); + return ret; + } + StructSet* makeStructSet() { + auto* ret = wasm.allocator.alloc<StructSet>(); + WASM_UNREACHABLE("TODO (gc): struct.set"); + ret->finalize(); + return ret; + } + ArrayNew* makeArrayNew() { + auto* ret = wasm.allocator.alloc<ArrayNew>(); + WASM_UNREACHABLE("TODO (gc): array.new"); + ret->finalize(); + return ret; + } + ArrayGet* makeArrayGet() { + auto* ret = wasm.allocator.alloc<ArrayGet>(); + WASM_UNREACHABLE("TODO (gc): array.get"); + ret->finalize(); + return ret; + } + ArraySet* makeArraySet() { + auto* ret = wasm.allocator.alloc<ArraySet>(); + WASM_UNREACHABLE("TODO (gc): array.set"); + ret->finalize(); + return ret; + } + ArrayLen* makeArrayLen() { + auto* ret = wasm.allocator.alloc<ArrayLen>(); + WASM_UNREACHABLE("TODO (gc): array.len"); + ret->finalize(); + return ret; + } // Additional helpers diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 4f3de9078..e44ffca3a 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1344,6 +1344,54 @@ public: NOTE_EVAL1(value); return Literal(value.geti31(curr->signed_)); } + Flow visitRefTest(RefTest* curr) { + NOTE_ENTER("RefTest"); + WASM_UNREACHABLE("TODO (gc): ref.test"); + } + Flow visitRefCast(RefCast* curr) { + NOTE_ENTER("RefCast"); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + } + Flow visitBrOnCast(BrOnCast* curr) { + NOTE_ENTER("BrOnCast"); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + } + Flow visitRttCanon(RttCanon* curr) { + NOTE_ENTER("RttCanon"); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + } + Flow visitRttSub(RttSub* curr) { + NOTE_ENTER("RttSub"); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + } + Flow visitStructNew(StructNew* curr) { + NOTE_ENTER("StructNew"); + WASM_UNREACHABLE("TODO (gc): struct.new"); + } + Flow visitStructGet(StructGet* curr) { + NOTE_ENTER("StructGet"); + WASM_UNREACHABLE("TODO (gc): struct.get"); + } + Flow visitStructSet(StructSet* curr) { + NOTE_ENTER("StructSet"); + WASM_UNREACHABLE("TODO (gc): struct.set"); + } + Flow visitArrayNew(ArrayNew* curr) { + NOTE_ENTER("ArrayNew"); + WASM_UNREACHABLE("TODO (gc): array.new"); + } + Flow visitArrayGet(ArrayGet* curr) { + NOTE_ENTER("ArrayGet"); + WASM_UNREACHABLE("TODO (gc): array.get"); + } + Flow visitArraySet(ArraySet* curr) { + NOTE_ENTER("ArraySet"); + WASM_UNREACHABLE("TODO (gc): array.set"); + } + Flow visitArrayLen(ArrayLen* curr) { + NOTE_ENTER("ArrayLen"); + WASM_UNREACHABLE("TODO (gc): array.len"); + } virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 3b0d1a92d..0f9a27abc 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -245,6 +245,20 @@ private: Expression* makeTupleExtract(Element& s); Expression* makeI31New(Element& s); Expression* makeI31Get(Element& s, bool signed_); + Expression* makeRefTest(Element& s); + Expression* makeRefCast(Element& s); + Expression* makeBrOnCast(Element& s); + Expression* makeRttCanon(Element& s); + Expression* makeRttSub(Element& s); + Expression* makeStructNew(Element& s, bool default_); + Expression* makeStructGet(Element& s); + Expression* makeStructGet(Element& s, bool signed_); + Expression* makeStructSet(Element& s); + Expression* makeArrayNew(Element& s, bool default_); + Expression* makeArrayGet(Element& s); + Expression* makeArrayGet(Element& s, bool signed_); + Expression* makeArraySet(Element& s); + Expression* makeArrayLen(Element& s); // Helper functions Type parseOptionalResultType(Element& s, Index& i); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 740473106..d4d04f850 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -150,6 +150,18 @@ public: void visitTupleExtract(TupleExtract* curr); void visitI31New(I31New* curr); void visitI31Get(I31Get* curr); + void visitRefTest(RefTest* curr); + void visitRefCast(RefCast* curr); + void visitBrOnCast(BrOnCast* curr); + void visitRttCanon(RttCanon* curr); + void visitRttSub(RttSub* curr); + void visitStructNew(StructNew* curr); + void visitStructGet(StructGet* curr); + void visitStructSet(StructSet* curr); + void visitArrayNew(ArrayNew* curr); + void visitArrayGet(ArrayGet* curr); + void visitArraySet(ArraySet* curr); + void visitArrayLen(ArrayLen* curr); void emitResultType(Type type); void emitIfElse(If* curr); diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h index cd83aa1b6..b32babf74 100644 --- a/src/wasm-traversal.h +++ b/src/wasm-traversal.h @@ -88,6 +88,18 @@ template<typename SubType, typename ReturnType = void> struct Visitor { ReturnType visitTupleExtract(TupleExtract* curr) { return ReturnType(); } ReturnType visitI31New(I31New* curr) { return ReturnType(); } ReturnType visitI31Get(I31Get* curr) { return ReturnType(); } + ReturnType visitRefTest(RefTest* curr) { return ReturnType(); } + ReturnType visitRefCast(RefCast* curr) { return ReturnType(); } + ReturnType visitBrOnCast(BrOnCast* curr) { return ReturnType(); } + ReturnType visitRttCanon(RttCanon* curr) { return ReturnType(); } + ReturnType visitRttSub(RttSub* curr) { return ReturnType(); } + ReturnType visitStructNew(StructNew* curr) { return ReturnType(); } + ReturnType visitStructGet(StructGet* curr) { return ReturnType(); } + ReturnType visitStructSet(StructSet* curr) { return ReturnType(); } + ReturnType visitArrayNew(ArrayNew* curr) { return ReturnType(); } + ReturnType visitArrayGet(ArrayGet* curr) { return ReturnType(); } + ReturnType visitArraySet(ArraySet* curr) { return ReturnType(); } + ReturnType visitArrayLen(ArrayLen* curr) { return ReturnType(); } // Module-level visitors ReturnType visitExport(Export* curr) { return ReturnType(); } ReturnType visitGlobal(Global* curr) { return ReturnType(); } @@ -207,6 +219,30 @@ template<typename SubType, typename ReturnType = void> struct Visitor { DELEGATE(I31New); case Expression::Id::I31GetId: DELEGATE(I31Get); + case Expression::Id::RefTestId: + DELEGATE(RefTest); + case Expression::Id::RefCastId: + DELEGATE(RefCast); + case Expression::Id::BrOnCastId: + DELEGATE(BrOnCast); + case Expression::Id::RttCanonId: + DELEGATE(RttCanon); + case Expression::Id::RttSubId: + DELEGATE(RttSub); + case Expression::Id::StructNewId: + DELEGATE(StructNew); + case Expression::Id::StructGetId: + DELEGATE(StructGet); + case Expression::Id::StructSetId: + DELEGATE(StructSet); + case Expression::Id::ArrayNewId: + DELEGATE(ArrayNew); + case Expression::Id::ArrayGetId: + DELEGATE(ArrayGet); + case Expression::Id::ArraySetId: + DELEGATE(ArraySet); + case Expression::Id::ArrayLenId: + DELEGATE(ArrayLen); case Expression::Id::InvalidId: default: WASM_UNREACHABLE("unexpected expression type"); @@ -281,6 +317,18 @@ struct OverriddenVisitor { UNIMPLEMENTED(TupleExtract); UNIMPLEMENTED(I31New); UNIMPLEMENTED(I31Get); + UNIMPLEMENTED(RefTest); + UNIMPLEMENTED(RefCast); + UNIMPLEMENTED(BrOnCast); + UNIMPLEMENTED(RttCanon); + UNIMPLEMENTED(RttSub); + UNIMPLEMENTED(StructNew); + UNIMPLEMENTED(StructGet); + UNIMPLEMENTED(StructSet); + UNIMPLEMENTED(ArrayNew); + UNIMPLEMENTED(ArrayGet); + UNIMPLEMENTED(ArraySet); + UNIMPLEMENTED(ArrayLen); UNIMPLEMENTED(Export); UNIMPLEMENTED(Global); UNIMPLEMENTED(Function); @@ -401,6 +449,30 @@ struct OverriddenVisitor { DELEGATE(I31New); case Expression::Id::I31GetId: DELEGATE(I31Get); + case Expression::Id::RefTestId: + DELEGATE(RefTest); + case Expression::Id::RefCastId: + DELEGATE(RefCast); + case Expression::Id::BrOnCastId: + DELEGATE(BrOnCast); + case Expression::Id::RttCanonId: + DELEGATE(RttCanon); + case Expression::Id::RttSubId: + DELEGATE(RttSub); + case Expression::Id::StructNewId: + DELEGATE(StructNew); + case Expression::Id::StructGetId: + DELEGATE(StructGet); + case Expression::Id::StructSetId: + DELEGATE(StructSet); + case Expression::Id::ArrayNewId: + DELEGATE(ArrayNew); + case Expression::Id::ArrayGetId: + DELEGATE(ArrayGet); + case Expression::Id::ArraySetId: + DELEGATE(ArraySet); + case Expression::Id::ArrayLenId: + DELEGATE(ArrayLen); case Expression::Id::InvalidId: default: WASM_UNREACHABLE("unexpected expression type"); @@ -572,6 +644,42 @@ struct UnifiedExpressionVisitor : public Visitor<SubType, ReturnType> { ReturnType visitI31Get(I31Get* curr) { return static_cast<SubType*>(this)->visitExpression(curr); } + ReturnType visitRefTest(RefTest* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitRefCast(RefCast* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitBrOnCast(BrOnCast* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitRttCanon(RttCanon* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitRttSub(RttSub* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitStructNew(StructNew* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitStructGet(StructGet* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitStructSet(StructSet* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitArrayNew(ArrayNew* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitArrayGet(ArrayGet* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitArraySet(ArraySet* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } + ReturnType visitArrayLen(ArrayLen* curr) { + return static_cast<SubType*>(this)->visitExpression(curr); + } }; // @@ -898,6 +1006,42 @@ struct Walker : public VisitorType { static void doVisitI31Get(SubType* self, Expression** currp) { self->visitI31Get((*currp)->cast<I31Get>()); } + static void doVisitRefTest(SubType* self, Expression** currp) { + self->visitRefTest((*currp)->cast<RefTest>()); + } + static void doVisitRefCast(SubType* self, Expression** currp) { + self->visitRefCast((*currp)->cast<RefCast>()); + } + static void doVisitBrOnCast(SubType* self, Expression** currp) { + self->visitBrOnCast((*currp)->cast<BrOnCast>()); + } + static void doVisitRttCanon(SubType* self, Expression** currp) { + self->visitRttCanon((*currp)->cast<RttCanon>()); + } + static void doVisitRttSub(SubType* self, Expression** currp) { + self->visitRttSub((*currp)->cast<RttSub>()); + } + static void doVisitStructNew(SubType* self, Expression** currp) { + self->visitStructNew((*currp)->cast<StructNew>()); + } + static void doVisitStructGet(SubType* self, Expression** currp) { + self->visitStructGet((*currp)->cast<StructGet>()); + } + static void doVisitStructSet(SubType* self, Expression** currp) { + self->visitStructSet((*currp)->cast<StructSet>()); + } + static void doVisitArrayNew(SubType* self, Expression** currp) { + self->visitArrayNew((*currp)->cast<ArrayNew>()); + } + static void doVisitArrayGet(SubType* self, Expression** currp) { + self->visitArrayGet((*currp)->cast<ArrayGet>()); + } + static void doVisitArraySet(SubType* self, Expression** currp) { + self->visitArraySet((*currp)->cast<ArraySet>()); + } + static void doVisitArrayLen(SubType* self, Expression** currp) { + self->visitArrayLen((*currp)->cast<ArrayLen>()); + } void setModule(Module* module) { currModule = module; } @@ -1209,6 +1353,54 @@ struct PostWalker : public Walker<SubType, VisitorType> { self->pushTask(SubType::scan, &curr->cast<I31Get>()->i31); break; } + case Expression::Id::RefTestId: + self->pushTask(SubType::doVisitRefTest, currp); + WASM_UNREACHABLE("TODO (gc): ref.test"); + break; + case Expression::Id::RefCastId: + self->pushTask(SubType::doVisitRefCast, currp); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + break; + case Expression::Id::BrOnCastId: + self->pushTask(SubType::doVisitBrOnCast, currp); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + break; + case Expression::Id::RttCanonId: + self->pushTask(SubType::doVisitRttCanon, currp); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + break; + case Expression::Id::RttSubId: + self->pushTask(SubType::doVisitRttSub, currp); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + break; + case Expression::Id::StructNewId: + self->pushTask(SubType::doVisitStructNew, currp); + WASM_UNREACHABLE("TODO (gc): struct.new"); + break; + case Expression::Id::StructGetId: + self->pushTask(SubType::doVisitStructGet, currp); + WASM_UNREACHABLE("TODO (gc): struct.get"); + break; + case Expression::Id::StructSetId: + self->pushTask(SubType::doVisitStructSet, currp); + WASM_UNREACHABLE("TODO (gc): struct.set"); + break; + case Expression::Id::ArrayNewId: + self->pushTask(SubType::doVisitArrayNew, currp); + WASM_UNREACHABLE("TODO (gc): array.new"); + break; + case Expression::Id::ArrayGetId: + self->pushTask(SubType::doVisitArrayGet, currp); + WASM_UNREACHABLE("TODO (gc): array.get"); + break; + case Expression::Id::ArraySetId: + self->pushTask(SubType::doVisitArraySet, currp); + WASM_UNREACHABLE("TODO (gc): array.set"); + break; + case Expression::Id::ArrayLenId: + self->pushTask(SubType::doVisitArrayLen, currp); + WASM_UNREACHABLE("TODO (gc): array.len"); + break; case Expression::Id::NumExpressionIds: WASM_UNREACHABLE("unexpected expression type"); } diff --git a/src/wasm.h b/src/wasm.h index d41ad863a..0a4c0db16 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -562,6 +562,18 @@ public: TupleExtractId, I31NewId, I31GetId, + RefTestId, + RefCastId, + BrOnCastId, + RttCanonId, + RttSubId, + StructNewId, + StructGetId, + StructSetId, + ArrayNewId, + ArrayGetId, + ArraySetId, + ArrayLenId, NumExpressionIds }; Id _id; @@ -1224,6 +1236,90 @@ public: void finalize(); }; +class RefTest : public SpecificExpression<Expression::RefTestId> { +public: + RefTest(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): ref.test"); } +}; + +class RefCast : public SpecificExpression<Expression::RefCastId> { +public: + RefCast(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): ref.cast"); } +}; + +class BrOnCast : public SpecificExpression<Expression::BrOnCastId> { +public: + BrOnCast(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): br_on_cast"); } +}; + +class RttCanon : public SpecificExpression<Expression::RttCanonId> { +public: + RttCanon(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): rtt.canon"); } +}; + +class RttSub : public SpecificExpression<Expression::RttSubId> { +public: + RttSub(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): rtt.sub"); } +}; + +class StructNew : public SpecificExpression<Expression::StructNewId> { +public: + StructNew(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): struct.new"); } +}; + +class StructGet : public SpecificExpression<Expression::StructGetId> { +public: + StructGet(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): struct.get"); } +}; + +class StructSet : public SpecificExpression<Expression::StructSetId> { +public: + StructSet(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): struct.set"); } +}; + +class ArrayNew : public SpecificExpression<Expression::ArrayNewId> { +public: + ArrayNew(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): array.new"); } +}; + +class ArrayGet : public SpecificExpression<Expression::ArrayGetId> { +public: + ArrayGet(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): array.get"); } +}; + +class ArraySet : public SpecificExpression<Expression::ArraySetId> { +public: + ArraySet(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): array.set"); } +}; + +class ArrayLen : public SpecificExpression<Expression::ArrayLenId> { +public: + ArrayLen(MixedArena& allocator) {} + + void finalize() { WASM_UNREACHABLE("TODO (gc): array.len"); } +}; + // Globals struct Importable { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 48564a897..38a85bd1b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2715,6 +2715,42 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitI31Get(curr, opcode)) { break; } + if (maybeVisitRefTest(curr, opcode)) { + break; + } + if (maybeVisitRefCast(curr, opcode)) { + break; + } + if (maybeVisitBrOnCast(curr, opcode)) { + break; + } + if (maybeVisitRttCanon(curr, opcode)) { + break; + } + if (maybeVisitRttSub(curr, opcode)) { + break; + } + if (maybeVisitStructNew(curr, opcode)) { + break; + } + if (maybeVisitStructGet(curr, opcode)) { + break; + } + if (maybeVisitStructSet(curr, opcode)) { + break; + } + if (maybeVisitArrayNew(curr, opcode)) { + break; + } + if (maybeVisitArrayGet(curr, opcode)) { + break; + } + if (maybeVisitArraySet(curr, opcode)) { + break; + } + if (maybeVisitArrayLen(curr, opcode)) { + break; + } throwError("invalid code after GC prefix: " + std::to_string(opcode)); break; } @@ -5190,6 +5226,182 @@ bool WasmBinaryBuilder::maybeVisitI31Get(Expression*& out, uint32_t code) { return true; } +bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RefTest) { + return false; + } + auto* curr = allocator.alloc<RefTest>(); + WASM_UNREACHABLE("TODO (gc): ref.test"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RefCast) { + return false; + } + auto* curr = allocator.alloc<RefCast>(); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitBrOnCast(Expression*& out, uint32_t code) { + if (code != BinaryConsts::BrOnCast) { + return false; + } + auto* curr = allocator.alloc<BrOnCast>(); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitRttCanon(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RttCanon) { + return false; + } + auto* curr = allocator.alloc<RttCanon>(); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitRttSub(Expression*& out, uint32_t code) { + if (code != BinaryConsts::RttSub) { + return false; + } + auto* curr = allocator.alloc<RttSub>(); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitStructNew(Expression*& out, uint32_t code) { + StructNew* curr; + switch (code) { + case BinaryConsts::StructNewWithRtt: + curr = allocator.alloc<StructNew>(); + // ... + break; + case BinaryConsts::StructNewDefaultWithRtt: + curr = allocator.alloc<StructNew>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): struct.new"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitStructGet(Expression*& out, uint32_t code) { + StructGet* curr; + switch (code) { + case BinaryConsts::StructGet: + curr = allocator.alloc<StructGet>(); + // ... + break; + case BinaryConsts::StructGetS: + curr = allocator.alloc<StructGet>(); + // ... + break; + case BinaryConsts::StructGetU: + curr = allocator.alloc<StructGet>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): struct.get"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitStructSet(Expression*& out, uint32_t code) { + if (code != BinaryConsts::StructSet) { + return false; + } + auto* curr = allocator.alloc<StructSet>(); + WASM_UNREACHABLE("TODO (gc): struct.set"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) { + ArrayNew* curr; + switch (code) { + case BinaryConsts::ArrayNewWithRtt: + curr = allocator.alloc<ArrayNew>(); + // ... + break; + case BinaryConsts::ArrayNewDefaultWithRtt: + curr = allocator.alloc<ArrayNew>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): array.new"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArrayGet(Expression*& out, uint32_t code) { + ArrayGet* curr; + switch (code) { + case BinaryConsts::ArrayGet: + curr = allocator.alloc<ArrayGet>(); + // ... + break; + case BinaryConsts::ArrayGetS: + curr = allocator.alloc<ArrayGet>(); + // ... + break; + case BinaryConsts::ArrayGetU: + curr = allocator.alloc<ArrayGet>(); + // ... + break; + default: + return false; + } + WASM_UNREACHABLE("TODO (gc): array.get"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArraySet(Expression*& out, uint32_t code) { + if (code != BinaryConsts::ArraySet) { + return false; + } + auto* curr = allocator.alloc<ArraySet>(); + WASM_UNREACHABLE("TODO (gc): array.set"); + curr->finalize(); + out = curr; + return true; +} + +bool WasmBinaryBuilder::maybeVisitArrayLen(Expression*& out, uint32_t code) { + if (code != BinaryConsts::ArrayLen) { + return false; + } + auto* curr = allocator.alloc<ArrayLen>(); + WASM_UNREACHABLE("TODO (gc): array.len"); + curr->finalize(); + out = curr; + return true; +} + void WasmBinaryBuilder::throwError(std::string text) { throw ParseException(text, 0, pos); } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 166fc88bb..63157b314 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1994,6 +1994,104 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { return ret; } +Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { + auto ret = allocator.alloc<RefTest>(); + WASM_UNREACHABLE("TODO (gc): ref.test"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { + auto ret = allocator.alloc<RefCast>(); + WASM_UNREACHABLE("TODO (gc): ref.cast"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s) { + auto ret = allocator.alloc<BrOnCast>(); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeRttCanon(Element& s) { + auto ret = allocator.alloc<RttCanon>(); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeRttSub(Element& s) { + auto ret = allocator.alloc<RttSub>(); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { + auto ret = allocator.alloc<StructNew>(); + WASM_UNREACHABLE("TODO (gc): struct.new"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructGet(Element& s) { + auto ret = allocator.alloc<StructGet>(); + WASM_UNREACHABLE("TODO (gc): struct.get"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) { + auto ret = allocator.alloc<StructGet>(); + WASM_UNREACHABLE("TODO (gc): struct.get_s/u"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeStructSet(Element& s) { + auto ret = allocator.alloc<StructSet>(); + WASM_UNREACHABLE("TODO (gc): struct.set"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) { + auto ret = allocator.alloc<ArrayNew>(); + WASM_UNREACHABLE("TODO (gc): array.new"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayGet(Element& s) { + auto ret = allocator.alloc<ArrayGet>(); + WASM_UNREACHABLE("TODO (gc): array.get"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayGet(Element& s, bool signed_) { + auto ret = allocator.alloc<ArrayGet>(); + WASM_UNREACHABLE("TODO (gc): array.get_s/u"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArraySet(Element& s) { + auto ret = allocator.alloc<ArraySet>(); + WASM_UNREACHABLE("TODO (gc): array.set"); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeArrayLen(Element& s) { + auto ret = allocator.alloc<ArrayLen>(); + WASM_UNREACHABLE("TODO (gc): array.len"); + ret->finalize(); + return ret; +} + // converts an s-expression string representing binary data into an output // sequence of raw bytes this appends to data, which may already contain // content. diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1c16dff16..1ca8869c7 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1784,6 +1784,62 @@ void BinaryInstWriter::visitI31Get(I31Get* curr) { << U32LEB(curr->signed_ ? BinaryConsts::I31GetS : BinaryConsts::I31GetU); } +void BinaryInstWriter::visitRefTest(RefTest* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefTest); + WASM_UNREACHABLE("TODO (gc): ref.test"); +} + +void BinaryInstWriter::visitRefCast(RefCast* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefCast); + WASM_UNREACHABLE("TODO (gc): ref.cast"); +} + +void BinaryInstWriter::visitBrOnCast(BrOnCast* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnCast); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); +} + +void BinaryInstWriter::visitRttCanon(RttCanon* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttCanon); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); +} + +void BinaryInstWriter::visitRttSub(RttSub* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttSub); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); +} + +void BinaryInstWriter::visitStructNew(StructNew* curr) { + WASM_UNREACHABLE("TODO (gc): struct.new"); +} + +void BinaryInstWriter::visitStructGet(StructGet* curr) { + WASM_UNREACHABLE("TODO (gc): struct.get"); +} + +void BinaryInstWriter::visitStructSet(StructSet* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StructSet); + WASM_UNREACHABLE("TODO (gc): struct.set"); +} + +void BinaryInstWriter::visitArrayNew(ArrayNew* curr) { + WASM_UNREACHABLE("TODO (gc): array.new"); +} + +void BinaryInstWriter::visitArrayGet(ArrayGet* curr) { + WASM_UNREACHABLE("TODO (gc): array.get"); +} + +void BinaryInstWriter::visitArraySet(ArraySet* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArraySet); + WASM_UNREACHABLE("TODO (gc): array.set"); +} + +void BinaryInstWriter::visitArrayLen(ArrayLen* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayLen); + WASM_UNREACHABLE("TODO (gc): array.len"); +} + void BinaryInstWriter::emitScopeEnd(Expression* curr) { assert(!breakStack.empty()); breakStack.pop_back(); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index ff2ed7e39..96871ad8e 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -340,6 +340,18 @@ public: void visitTupleExtract(TupleExtract* curr); void visitI31New(I31New* curr); void visitI31Get(I31Get* curr); + void visitRefTest(RefTest* curr); + void visitRefCast(RefCast* curr); + void visitBrOnCast(BrOnCast* curr); + void visitRttCanon(RttCanon* curr); + void visitRttSub(RttSub* curr); + void visitStructNew(StructNew* curr); + void visitStructGet(StructGet* curr); + void visitStructSet(StructSet* curr); + void visitArrayNew(ArrayNew* curr); + void visitArrayGet(ArrayGet* curr); + void visitArraySet(ArraySet* curr); + void visitArrayLen(ArrayLen* curr); void visitFunction(Function* curr); // helpers @@ -2135,6 +2147,82 @@ void FunctionValidator::visitI31Get(I31Get* curr) { "i31.get_s/u's argument should be i31ref"); } +void FunctionValidator::visitRefTest(RefTest* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "ref.test requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): ref.test"); +} + +void FunctionValidator::visitRefCast(RefCast* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "ref.cast requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): ref.cast"); +} + +void FunctionValidator::visitBrOnCast(BrOnCast* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "br_on_cast requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): br_on_cast"); +} + +void FunctionValidator::visitRttCanon(RttCanon* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "rtt.canon requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): rtt.canon"); +} + +void FunctionValidator::visitRttSub(RttSub* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "rtt.sub requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): rtt.sub"); +} + +void FunctionValidator::visitStructNew(StructNew* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "struct.new requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): struct.new"); +} + +void FunctionValidator::visitStructGet(StructGet* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "struct.get requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): struct.get"); +} + +void FunctionValidator::visitStructSet(StructSet* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "struct.set requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): struct.set"); +} + +void FunctionValidator::visitArrayNew(ArrayNew* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.new requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.new"); +} + +void FunctionValidator::visitArrayGet(ArrayGet* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.get requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.get"); +} + +void FunctionValidator::visitArraySet(ArraySet* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.set requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.set"); +} + +void FunctionValidator::visitArrayLen(ArrayLen* curr) { + shouldBeTrue( + getModule()->features.hasGC(), curr, "array.len requires gc to be enabled"); + WASM_UNREACHABLE("TODO (gc): array.len"); +} + void FunctionValidator::visitFunction(Function* curr) { if (curr->sig.results.isTuple()) { shouldBeTrue(getModule()->features.hasMultivalue(), diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index c857b202c..738823d66 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -210,6 +210,30 @@ const char* getExpressionName(Expression* curr) { return "i31.new"; case Expression::Id::I31GetId: return "i31.get"; + case Expression::Id::RefTestId: + return "ref.test"; + case Expression::Id::RefCastId: + return "ref.cast"; + case Expression::Id::BrOnCastId: + return "br_on_cast"; + case Expression::Id::RttCanonId: + return "rtt.canon"; + case Expression::Id::RttSubId: + return "rtt.sub"; + case Expression::Id::StructNewId: + return "struct.new"; + case Expression::Id::StructGetId: + return "struct.get"; + case Expression::Id::StructSetId: + return "struct.set"; + case Expression::Id::ArrayNewId: + return "array.new"; + case Expression::Id::ArrayGetId: + return "array.get"; + case Expression::Id::ArraySetId: + return "array.set"; + case Expression::Id::ArrayLenId: + return "array.len"; case Expression::Id::NumExpressionIds: WASM_UNREACHABLE("invalid expr id"); } @@ -986,6 +1010,19 @@ void I31Get::finalize() { } } +// TODO (gc): ref.test +// TODO (gc): ref.cast +// TODO (gc): br_on_cast +// TODO (gc): rtt.canon +// TODO (gc): rtt.sub +// TODO (gc): struct.new +// TODO (gc): struct.get +// TODO (gc): struct.set +// TODO (gc): array.new +// TODO (gc): array.get +// TODO (gc): array.set +// TODO (gc): array.len + size_t Function::getNumParams() { return sig.params.size(); } size_t Function::getNumVars() { return vars.size(); } diff --git a/src/wasm2js.h b/src/wasm2js.h index 013e56335..cb7bfd20d 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2126,6 +2126,54 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, unimplemented(curr); WASM_UNREACHABLE("unimp"); } + Ref visitRefTest(RefTest* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitRefCast(RefCast* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitBrOnCast(BrOnCast* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitRttCanon(RttCanon* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitRttSub(RttSub* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitStructNew(StructNew* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitStructGet(StructGet* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitStructSet(StructSet* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitArrayNew(ArrayNew* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitArrayGet(ArrayGet* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitArraySet(ArraySet* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } + Ref visitArrayLen(ArrayLen* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } private: Ref makePointer(Expression* ptr, Address offset) { diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 051f53c54..769b1a7e0 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -169,6 +169,18 @@ function test_ids() { console.log("TupleExtractId: " + binaryen.TupleExtractId); console.log("I31NewId: " + binaryen.I31NewId); console.log("I31GetId: " + binaryen.I31GetId); + console.log("RefTestId: " + binaryen.RefTestId); + console.log("RefCastId: " + binaryen.RefCastId); + console.log("BrOnCastId: " + binaryen.BrOnCastId); + console.log("RttCanonId: " + binaryen.RttCanonId); + console.log("RttSubId: " + binaryen.RttSubId); + console.log("StructNewId: " + binaryen.StructNewId); + console.log("StructGetId: " + binaryen.StructGetId); + console.log("StructSetId: " + binaryen.StructSetId); + console.log("ArrayNewId: " + binaryen.ArrayNewId); + console.log("ArrayGetId: " + binaryen.ArrayGetId); + console.log("ArraySetId: " + binaryen.ArraySetId); + console.log("ArrayLenId: " + binaryen.ArrayLenId); } function test_core() { diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 491f11cec..db3ee1605 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -93,6 +93,18 @@ TupleMakeId: 48 TupleExtractId: 49 I31NewId: 50 I31GetId: 51 +RefTestId: 52 +RefCastId: 53 +BrOnCastId: 54 +RttCanonId: 55 +RttSubId: 56 +StructNewId: 57 +StructGetId: 58 +StructSetId: 59 +ArrayNewId: 60 +ArrayGetId: 61 +ArraySetId: 62 +ArrayLenId: 63 getExpressionInfo={"id":15,"type":4,"op":6} (f32.neg (f32.const -33.61199951171875) |