diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 111 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 37 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 41 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 48 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 25 |
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() { |