summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp111
-rw-r--r--src/wasm/wasm-s-parser.cpp37
-rw-r--r--src/wasm/wasm-stack.cpp41
-rw-r--r--src/wasm/wasm-validator.cpp48
-rw-r--r--src/wasm/wasm.cpp25
5 files changed, 194 insertions, 68 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index e1ff43988..74895c868 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -6527,23 +6527,36 @@ bool WasmBinaryBuilder::maybeVisitRttSub(Expression*& out, uint32_t code) {
}
bool WasmBinaryBuilder::maybeVisitStructNew(Expression*& out, uint32_t code) {
- if (code != BinaryConsts::StructNewWithRtt &&
- code != BinaryConsts::StructNewDefaultWithRtt) {
- return false;
- }
- auto heapType = getIndexedHeapType();
- auto* rtt = popNonVoidExpression();
- validateHeapTypeUsingChild(rtt, heapType);
- std::vector<Expression*> operands;
- if (code == BinaryConsts::StructNewWithRtt) {
- auto numOperands = heapType.getStruct().fields.size();
- operands.resize(numOperands);
- for (Index i = 0; i < numOperands; i++) {
- operands[numOperands - i - 1] = popNonVoidExpression();
+ if (code == BinaryConsts::StructNew ||
+ code == BinaryConsts::StructNewDefault) {
+ auto heapType = getIndexedHeapType();
+ std::vector<Expression*> operands;
+ if (code == BinaryConsts::StructNew) {
+ auto numOperands = heapType.getStruct().fields.size();
+ operands.resize(numOperands);
+ for (Index i = 0; i < numOperands; i++) {
+ operands[numOperands - i - 1] = popNonVoidExpression();
+ }
+ }
+ out = Builder(wasm).makeStructNew(heapType, operands);
+ return true;
+ } else if (code == BinaryConsts::StructNewWithRtt ||
+ code == BinaryConsts::StructNewDefaultWithRtt) {
+ auto heapType = getIndexedHeapType();
+ auto* rtt = popNonVoidExpression();
+ validateHeapTypeUsingChild(rtt, heapType);
+ std::vector<Expression*> operands;
+ if (code == BinaryConsts::StructNewWithRtt) {
+ auto numOperands = heapType.getStruct().fields.size();
+ operands.resize(numOperands);
+ for (Index i = 0; i < numOperands; i++) {
+ operands[numOperands - i - 1] = popNonVoidExpression();
+ }
}
+ out = Builder(wasm).makeStructNew(rtt, operands);
+ return true;
}
- out = Builder(wasm).makeStructNew(rtt, operands);
- return true;
+ return false;
}
bool WasmBinaryBuilder::maybeVisitStructGet(Expression*& out, uint32_t code) {
@@ -6588,36 +6601,54 @@ bool WasmBinaryBuilder::maybeVisitStructSet(Expression*& out, uint32_t code) {
}
bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) {
- if (code != BinaryConsts::ArrayNewWithRtt &&
- code != BinaryConsts::ArrayNewDefaultWithRtt) {
- return false;
+ if (code == BinaryConsts::ArrayNew || code == BinaryConsts::ArrayNewDefault) {
+ auto heapType = getIndexedHeapType();
+ auto* size = popNonVoidExpression();
+ Expression* init = nullptr;
+ if (code == BinaryConsts::ArrayNew) {
+ init = popNonVoidExpression();
+ }
+ out = Builder(wasm).makeArrayNew(heapType, size, init);
+ return true;
+ } else if (code == BinaryConsts::ArrayNewWithRtt ||
+ code == BinaryConsts::ArrayNewDefaultWithRtt) {
+ auto heapType = getIndexedHeapType();
+ auto* rtt = popNonVoidExpression();
+ validateHeapTypeUsingChild(rtt, heapType);
+ auto* size = popNonVoidExpression();
+ Expression* init = nullptr;
+ if (code == BinaryConsts::ArrayNewWithRtt) {
+ init = popNonVoidExpression();
+ }
+ out = Builder(wasm).makeArrayNew(rtt, size, init);
+ return true;
}
- auto heapType = getIndexedHeapType();
- auto* rtt = popNonVoidExpression();
- validateHeapTypeUsingChild(rtt, heapType);
- auto* size = popNonVoidExpression();
- Expression* init = nullptr;
- if (code == BinaryConsts::ArrayNewWithRtt) {
- init = popNonVoidExpression();
- }
- out = Builder(wasm).makeArrayNew(rtt, size, init);
- return true;
+ return false;
}
bool WasmBinaryBuilder::maybeVisitArrayInit(Expression*& out, uint32_t code) {
- if (code != BinaryConsts::ArrayInit) {
- return false;
- }
- auto heapType = getIndexedHeapType();
- auto size = getU32LEB();
- auto* rtt = popNonVoidExpression();
- validateHeapTypeUsingChild(rtt, heapType);
- std::vector<Expression*> values(size);
- for (size_t i = 0; i < size; i++) {
- values[size - i - 1] = popNonVoidExpression();
+ if (code == BinaryConsts::ArrayInitStatic) {
+ auto heapType = getIndexedHeapType();
+ auto size = getU32LEB();
+ std::vector<Expression*> values(size);
+ for (size_t i = 0; i < size; i++) {
+ values[size - i - 1] = popNonVoidExpression();
+ }
+ out = Builder(wasm).makeArrayInit(heapType, values);
+ return true;
+ } else if (code == BinaryConsts::ArrayInit) {
+ auto heapType = getIndexedHeapType();
+ auto size = getU32LEB();
+ auto* rtt = popNonVoidExpression();
+ validateHeapTypeUsingChild(rtt, heapType);
+ std::vector<Expression*> values(size);
+ for (size_t i = 0; i < size; i++) {
+ values[size - i - 1] = popNonVoidExpression();
+ }
+ out = Builder(wasm).makeArrayInit(rtt, values);
+ return true;
}
- out = Builder(wasm).makeArrayInit(rtt, values);
- return true;
+ return false;
}
bool WasmBinaryBuilder::maybeVisitArrayGet(Expression*& out, uint32_t code) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 697e4e58d..e9ea6aaa5 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2652,6 +2652,21 @@ Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) {
return Builder(wasm).makeStructNew(rtt, operands);
}
+Expression* SExpressionWasmBuilder::makeStructNewStatic(Element& s,
+ bool default_) {
+ auto heapType = parseHeapType(*s[1]);
+ auto numOperands = s.size() - 2;
+ if (default_ && numOperands > 0) {
+ throw ParseException("arguments provided for struct.new", s.line, s.col);
+ }
+ std::vector<Expression*> operands;
+ operands.resize(numOperands);
+ for (Index i = 0; i < numOperands; i++) {
+ operands[i] = parseExpression(*s[i + 2]);
+ }
+ return Builder(wasm).makeStructNew(heapType, operands);
+}
+
Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) {
if (field.dollared()) {
auto name = field.str();
@@ -2708,6 +2723,18 @@ Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) {
return Builder(wasm).makeArrayNew(rtt, size, init);
}
+Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s,
+ bool default_) {
+ auto heapType = parseHeapType(*s[1]);
+ Expression* init = nullptr;
+ size_t i = 2;
+ if (!default_) {
+ init = parseExpression(*s[i++]);
+ }
+ auto* size = parseExpression(*s[i++]);
+ return Builder(wasm).makeArrayNew(heapType, size, init);
+}
+
Expression* SExpressionWasmBuilder::makeArrayInit(Element& s) {
auto heapType = parseHeapType(*s[1]);
size_t i = 2;
@@ -2720,6 +2747,16 @@ Expression* SExpressionWasmBuilder::makeArrayInit(Element& s) {
return Builder(wasm).makeArrayInit(rtt, values);
}
+Expression* SExpressionWasmBuilder::makeArrayInitStatic(Element& s) {
+ auto heapType = parseHeapType(*s[1]);
+ size_t i = 2;
+ std::vector<Expression*> values;
+ while (i < s.size()) {
+ values.push_back(parseExpression(*s[i++]));
+ }
+ return Builder(wasm).makeArrayInit(heapType, values);
+}
+
Expression* SExpressionWasmBuilder::makeArrayGet(Element& s, bool signed_) {
auto heapType = parseHeapType(*s[1]);
auto ref = parseExpression(*s[2]);
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index b6424cdde..70b52cfbb 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2025,12 +2025,20 @@ void BinaryInstWriter::visitRttSub(RttSub* curr) {
void BinaryInstWriter::visitStructNew(StructNew* curr) {
o << int8_t(BinaryConsts::GCPrefix);
- if (curr->isWithDefault()) {
- o << U32LEB(BinaryConsts::StructNewDefaultWithRtt);
+ if (curr->rtt) {
+ if (curr->isWithDefault()) {
+ o << U32LEB(BinaryConsts::StructNewDefaultWithRtt);
+ } else {
+ o << U32LEB(BinaryConsts::StructNewWithRtt);
+ }
} else {
- o << U32LEB(BinaryConsts::StructNewWithRtt);
+ if (curr->isWithDefault()) {
+ o << U32LEB(BinaryConsts::StructNewDefault);
+ } else {
+ o << U32LEB(BinaryConsts::StructNew);
+ }
}
- parent.writeIndexedHeapType(curr->rtt->type.getHeapType());
+ parent.writeIndexedHeapType(curr->type.getHeapType());
}
void BinaryInstWriter::visitStructGet(StructGet* curr) {
@@ -2057,17 +2065,30 @@ void BinaryInstWriter::visitStructSet(StructSet* curr) {
void BinaryInstWriter::visitArrayNew(ArrayNew* curr) {
o << int8_t(BinaryConsts::GCPrefix);
- if (curr->isWithDefault()) {
- o << U32LEB(BinaryConsts::ArrayNewDefaultWithRtt);
+ if (curr->rtt) {
+ if (curr->isWithDefault()) {
+ o << U32LEB(BinaryConsts::ArrayNewDefaultWithRtt);
+ } else {
+ o << U32LEB(BinaryConsts::ArrayNewWithRtt);
+ }
} else {
- o << U32LEB(BinaryConsts::ArrayNewWithRtt);
+ if (curr->isWithDefault()) {
+ o << U32LEB(BinaryConsts::ArrayNewDefault);
+ } else {
+ o << U32LEB(BinaryConsts::ArrayNew);
+ }
}
- parent.writeIndexedHeapType(curr->rtt->type.getHeapType());
+ parent.writeIndexedHeapType(curr->type.getHeapType());
}
void BinaryInstWriter::visitArrayInit(ArrayInit* curr) {
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayInit);
- parent.writeIndexedHeapType(curr->rtt->type.getHeapType());
+ o << int8_t(BinaryConsts::GCPrefix);
+ if (curr->rtt) {
+ o << U32LEB(BinaryConsts::ArrayInit);
+ } else {
+ o << U32LEB(BinaryConsts::ArrayInitStatic);
+ }
+ parent.writeIndexedHeapType(curr->type.getHeapType());
o << U32LEB(curr->values.size());
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 1f6421609..d03fc2446 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2332,11 +2332,19 @@ void FunctionValidator::visitStructNew(StructNew* curr) {
if (curr->type == Type::unreachable) {
return;
}
- if (!shouldBeTrue(
- curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) {
- return;
+ if (curr->rtt) {
+ if (!shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) {
+ return;
+ }
+ }
+ auto heapType = curr->type.getHeapType();
+ if (curr->rtt) {
+ shouldBeEqual(curr->rtt->type.getHeapType(),
+ heapType,
+ curr,
+ "struct.new heap type must match rtt");
}
- auto heapType = curr->rtt->type.getHeapType();
if (!shouldBeTrue(
heapType.isStruct(), curr, "struct.new heap type must be struct")) {
return;
@@ -2428,11 +2436,19 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) {
if (curr->type == Type::unreachable) {
return;
}
- if (!shouldBeTrue(
- curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) {
- return;
+ if (curr->rtt) {
+ if (!shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) {
+ return;
+ }
+ }
+ auto heapType = curr->type.getHeapType();
+ if (curr->rtt) {
+ shouldBeEqual(curr->rtt->type.getHeapType(),
+ heapType,
+ curr,
+ "array.new heap type must match rtt");
}
- auto heapType = curr->rtt->type.getHeapType();
if (!shouldBeTrue(
heapType.isArray(), curr, "array.new heap type must be array")) {
return;
@@ -2462,11 +2478,19 @@ void FunctionValidator::visitArrayInit(ArrayInit* curr) {
if (curr->type == Type::unreachable) {
return;
}
- if (!shouldBeTrue(
- curr->rtt->type.isRtt(), curr, "array.init rtt must be rtt")) {
- return;
+ if (curr->rtt) {
+ if (!shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "array.init rtt must be rtt")) {
+ return;
+ }
+ }
+ auto heapType = curr->type.getHeapType();
+ if (curr->rtt) {
+ shouldBeEqual(curr->rtt->type.getHeapType(),
+ heapType,
+ curr,
+ "array.init heap type must match rtt");
}
- auto heapType = curr->rtt->type.getHeapType();
if (!shouldBeTrue(
heapType.isArray(), curr, "array.init heap type must be array")) {
return;
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 0f1017e00..792e43cbe 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1018,14 +1018,18 @@ void RttSub::finalize() {
}
void StructNew::finalize() {
- if (rtt->type == Type::unreachable) {
+ if (rtt && rtt->type == Type::unreachable) {
type = Type::unreachable;
return;
}
if (handleUnreachableOperands(this)) {
return;
}
- type = Type(rtt->type.getHeapType(), NonNullable);
+ // A dynamic StructNew infers the type from the rtt. A static one has the type
+ // already in the type field.
+ if (rtt) {
+ type = Type(rtt->type.getHeapType(), NonNullable);
+ }
}
void StructGet::finalize() {
@@ -1045,16 +1049,21 @@ void StructSet::finalize() {
}
void ArrayNew::finalize() {
- if (rtt->type == Type::unreachable || size->type == Type::unreachable ||
+ if ((rtt && rtt->type == Type::unreachable) ||
+ size->type == Type::unreachable ||
(init && init->type == Type::unreachable)) {
type = Type::unreachable;
return;
}
- type = Type(rtt->type.getHeapType(), NonNullable);
+ // A dynamic ArrayNew infers the type from the rtt. A static one has the type
+ // already in the type field.
+ if (rtt) {
+ type = Type(rtt->type.getHeapType(), NonNullable);
+ }
}
void ArrayInit::finalize() {
- if (rtt->type == Type::unreachable) {
+ if (rtt && rtt->type == Type::unreachable) {
type = Type::unreachable;
return;
}
@@ -1064,7 +1073,11 @@ void ArrayInit::finalize() {
return;
}
}
- type = Type(rtt->type.getHeapType(), NonNullable);
+ // A dynamic ArrayInit infers the type from the rtt. A static one has the type
+ // already in the type field.
+ if (rtt) {
+ type = Type(rtt->type.getHeapType(), NonNullable);
+ }
}
void ArrayGet::finalize() {