From 2b326379e7deac4b37e0db5f064d06f7daf46aac Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 16 Mar 2023 11:45:40 -0500 Subject: Add bulk-array.wast spec test outline (#5568) Add spec/bulk-array.wast, which contains an outline of the tests that will be necessary for the upcoming bulk array instructions: array.copy (already implemented), array.fill, array.init_data, and array.init_elem. Although the test file does not actually contain any tests yet, it contains some setup code defining types, globals, and element segments that the tests will use. Fix miscellaneous bugs in parsing, validation, and printing to allow this setup code to run without issues. --- src/passes/Print.cpp | 2 +- src/wasm/wasm-binary.cpp | 3 --- src/wasm/wasm-s-parser.cpp | 12 +----------- src/wasm/wasm-validator.cpp | 29 +++++++++++------------------ 4 files changed, 13 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 4a4fe60c7..c9a717058 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3283,7 +3283,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor { } else { for (auto* entry : curr->data) { o << ' '; - printExpression(entry, o); + visit(entry); } } o << ')' << maybeNewLine; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 518a809fa..9368325b0 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3222,9 +3222,6 @@ void WasmBinaryBuilder::readElementSegments() { if (isPassive || hasTableIdx) { if (usesExpressions) { segment->type = getType(); - if (!segment->type.isFunction()) { - throwError("Invalid type for a usesExpressions element segment"); - } } else { auto elemKind = getU32LEB(); if (elemKind != 0x0) { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 522c3f3c6..77e265f16 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -3561,7 +3561,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) { void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { std::unique_ptr global = make_unique(); size_t i = 1; - if (s[i]->dollared() && !(s[i]->isStr() && isType(s[i]->str()))) { + if (s[i]->dollared()) { global->setExplicitName(s[i++]->str()); } else if (preParseImport) { global->name = Name("gimport$" + std::to_string(globalCounter)); @@ -3572,7 +3572,6 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { globalNames.push_back(global->name); bool mutable_ = false; Type type = Type::none; - bool exported = false; Name importModule, importBase; while (i < s.size() && s[i]->isList()) { auto& inner = *s[i++]; @@ -3585,7 +3584,6 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { throw ParseException("duplicate export", s.line, s.col); } wasm.addExport(ex.release()); - exported = true; } else if (elementStartsWith(inner, IMPORT)) { importModule = inner[1]->str(); importBase = inner[2]->str(); @@ -3598,9 +3596,6 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { break; } } - if (exported && mutable_) { - throw ParseException("cannot export a mutable global", s.line, s.col); - } if (type == Type::none) { type = stringToType(s[i++]->str()); } @@ -3784,11 +3779,6 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) { segment->type = elementToType(*s[i]); usesExpressions = true; i += 1; - - if (!segment->type.isFunction()) { - throw ParseException( - "Invalid type for an element segment.", s.line, s.col); - } } } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index e0391a73d..123a15c1e 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -3405,13 +3405,9 @@ static void validateTables(Module& module, ValidationInfo& info) { } for (auto& segment : module.elementSegments) { - // Since element segment items need to be constant expressions, that leaves - // us with ref.null, ref.func and global.get. As a result, the only possible - // type for element segments will be function references. - // TODO: This is not true! Allow GC data here (#4846). - info.shouldBeTrue(segment->type.isFunction(), + info.shouldBeTrue(segment->type.isRef(), "elem", - "element segment type must be of function type."); + "element segment type must be of reference type."); info.shouldBeTrue( segment->type.isNullable(), "elem", @@ -3443,18 +3439,15 @@ static void validateTables(Module& module, ValidationInfo& info) { "elem", "non-table segment offset should have no offset"); } - // Avoid double checking items - if (module.features.hasReferenceTypes()) { - for (auto* expr : segment->data) { - info.shouldBeTrue(Properties::isValidConstantExpression(module, expr), - expr, - "element must be a constant expression"); - info.shouldBeSubType(expr->type, - segment->type, - expr, - "element must be a subtype of the segment type"); - validator.validate(expr); - } + for (auto* expr : segment->data) { + info.shouldBeTrue(Properties::isValidConstantExpression(module, expr), + expr, + "element must be a constant expression"); + info.shouldBeSubType(expr->type, + segment->type, + expr, + "element must be a subtype of the segment type"); + validator.validate(expr); } } } -- cgit v1.2.3