summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/gen-s-parser.py20
-rw-r--r--src/binaryen-c.cpp47
-rw-r--r--src/binaryen-c.h24
-rw-r--r--src/gen-s-parser.inc195
-rw-r--r--src/ir/ExpressionAnalyzer.cpp34
-rw-r--r--src/ir/ExpressionManipulator.cpp36
-rw-r--r--src/ir/ReFinalize.cpp15
-rw-r--r--src/ir/effects.h30
-rw-r--r--src/ir/utils.h24
-rw-r--r--src/js/binaryen.js-post.js14
-rw-r--r--src/passes/DeadCodeElimination.cpp24
-rw-r--r--src/passes/Print.cpp104
-rw-r--r--src/wasm-binary.h37
-rw-r--r--src/wasm-builder.h72
-rw-r--r--src/wasm-interpreter.h48
-rw-r--r--src/wasm-s-parser.h14
-rw-r--r--src/wasm-stack.h12
-rw-r--r--src/wasm-traversal.h192
-rw-r--r--src/wasm.h96
-rw-r--r--src/wasm/wasm-binary.cpp212
-rw-r--r--src/wasm/wasm-s-parser.cpp98
-rw-r--r--src/wasm/wasm-stack.cpp56
-rw-r--r--src/wasm/wasm-validator.cpp88
-rw-r--r--src/wasm/wasm.cpp37
-rw-r--r--src/wasm2js.h48
-rw-r--r--test/binaryen.js/kitchen-sink.js12
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt12
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)