summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp11
-rw-r--r--src/wasm/wasm-stack.cpp8
-rw-r--r--src/wasm/wasm-validator.cpp35
-rw-r--r--src/wasm/wasm.cpp6
4 files changed, 59 insertions, 1 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index df99fabb9..d449d4bdb 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -3978,7 +3978,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
}
if (opcode == BinaryConsts::RefAsFunc ||
opcode == BinaryConsts::RefAsData ||
- opcode == BinaryConsts::RefAsI31) {
+ opcode == BinaryConsts::RefAsI31 ||
+ opcode == BinaryConsts::ExternInternalize ||
+ opcode == BinaryConsts::ExternExternalize) {
visitRefAs((curr = allocator.alloc<RefAs>())->cast<RefAs>(), opcode);
break;
}
@@ -7347,6 +7349,12 @@ void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
case BinaryConsts::RefAsI31:
curr->op = RefAsI31;
break;
+ case BinaryConsts::ExternInternalize:
+ curr->op = ExternInternalize;
+ break;
+ case BinaryConsts::ExternExternalize:
+ curr->op = ExternExternalize;
+ break;
default:
WASM_UNREACHABLE("invalid code for ref.as_*");
}
@@ -7356,6 +7364,7 @@ void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
}
curr->finalize();
}
+
void WasmBinaryBuilder::throwError(std::string text) {
throw ParseException(text, 0, pos);
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 13bd09927..fddb7e41c 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2170,6 +2170,14 @@ void BinaryInstWriter::visitRefAs(RefAs* curr) {
case RefAsI31:
o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsI31);
break;
+ case ExternInternalize:
+ o << int8_t(BinaryConsts::GCPrefix)
+ << U32LEB(BinaryConsts::ExternInternalize);
+ break;
+ case ExternExternalize:
+ o << int8_t(BinaryConsts::GCPrefix)
+ << U32LEB(BinaryConsts::ExternExternalize);
+ break;
default:
WASM_UNREACHABLE("invalid ref.as_*");
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 532529d2a..75cbcf53a 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -424,6 +424,7 @@ public:
void visitMemoryGrow(MemoryGrow* curr);
void visitRefNull(RefNull* curr);
void visitRefIs(RefIs* curr);
+ void visitRefAs(RefAs* curr);
void visitRefFunc(RefFunc* curr);
void visitRefEq(RefEq* curr);
void visitTableGet(TableGet* curr);
@@ -2125,6 +2126,40 @@ void FunctionValidator::visitRefIs(RefIs* curr) {
"ref.is_*'s argument should be a reference type");
}
+void FunctionValidator::visitRefAs(RefAs* curr) {
+ switch (curr->op) {
+ default:
+ // TODO: validate all the other ref.as_*
+ break;
+ case ExternInternalize: {
+ shouldBeTrue(getModule()->features.hasGC(),
+ curr,
+ "extern.internalize requries GC to be enabled");
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ shouldBeSubType(curr->value->type,
+ Type(HeapType::ext, Nullable),
+ curr->value,
+ "extern.internalize value should be an externref");
+ break;
+ }
+ case ExternExternalize: {
+ shouldBeTrue(getModule()->features.hasGC(),
+ curr,
+ "extern.externalize requries GC to be enabled");
+ if (curr->type == Type::unreachable) {
+ return;
+ }
+ shouldBeSubType(curr->value->type,
+ Type(HeapType::any, Nullable),
+ curr->value,
+ "extern.externalize value should be an anyref");
+ break;
+ }
+ }
+}
+
void FunctionValidator::visitRefFunc(RefFunc* curr) {
// If we are not in a function, this is a global location like a table. We
// allow RefFunc there as we represent tables that way regardless of what
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 8226e9079..56db8d7a9 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1122,6 +1122,12 @@ void RefAs::finalize() {
case RefAsI31:
type = Type(HeapType::i31, NonNullable);
break;
+ case ExternInternalize:
+ type = Type(HeapType::any, value->type.getNullability());
+ break;
+ case ExternExternalize:
+ type = Type(HeapType::ext, value->type.getNullability());
+ break;
default:
WASM_UNREACHABLE("invalid ref.as_*");
}