diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 21 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 28 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 16 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 21 |
4 files changed, 58 insertions, 28 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index c36789828..3b8649d29 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -376,14 +376,25 @@ void WasmBinaryWriter::writeGlobals() { } BYN_TRACE("== writeglobals\n"); auto start = startSection(BinaryConsts::Section::Global); - auto num = importInfo->getNumDefinedGlobals(); + // Count and emit the total number of globals after tuple globals have been + // expanded into their constituent parts. + Index num = 0; + ModuleUtils::iterDefinedGlobals( + *wasm, [&num](Global* global) { num += global->type.size(); }); o << U32LEB(num); ModuleUtils::iterDefinedGlobals(*wasm, [&](Global* global) { BYN_TRACE("write one\n"); - o << binaryType(global->type); - o << U32LEB(global->mutable_); - writeExpression(global->init); - o << int8_t(BinaryConsts::End); + const auto& types = global->type.expand(); + for (size_t i = 0; i < types.size(); ++i) { + o << binaryType(types[i]); + o << U32LEB(global->mutable_); + if (types.size() == 1) { + writeExpression(global->init); + } else { + writeExpression(global->init->cast<TupleMake>()->operands[i]); + } + o << int8_t(BinaryConsts::End); + } }); finishSection(start); } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 4354b747a..a39e52b6d 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -546,12 +546,7 @@ SExpressionWasmBuilder::parseParamOrLocal(Element& s, size_t& localIndex) { throw ParseException( "params may not have tuple types", s[i]->line, s[i]->col); } - auto& tuple = s[i]->list(); - std::vector<Type> types; - for (size_t j = 0; j < s[i]->size(); ++j) { - types.push_back(stringToType(tuple[j]->str())); - } - type = Type(types); + type = elementToType(*s[i]); } namedParams.emplace_back(name, type); } @@ -886,6 +881,18 @@ Type SExpressionWasmBuilder::stringToType(const char* str, throw ParseException(std::string("invalid wasm type: ") + str); } +Type SExpressionWasmBuilder::elementToType(Element& s) { + if (s.isStr()) { + return stringToType(s.str(), false, false); + } + auto& tuple = s.list(); + std::vector<Type> types; + for (size_t i = 0; i < s.size(); ++i) { + types.push_back(stringToType(tuple[i]->str())); + } + return Type(types); +} + Type SExpressionWasmBuilder::stringToLaneType(const char* str) { if (strcmp(str, "i8x16") == 0) { return Type::i32; @@ -2278,7 +2285,7 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { bool exported = false; Name importModule, importBase; while (i < s.size() && s[i]->isList()) { - auto& inner = *s[i]; + auto& inner = *s[i++]; if (elementStartsWith(inner, EXPORT)) { auto ex = make_unique<Export>(); ex->name = inner[1]->str(); @@ -2289,16 +2296,15 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { } wasm.addExport(ex.release()); exported = true; - i++; } else if (elementStartsWith(inner, IMPORT)) { importModule = inner[1]->str(); importBase = inner[2]->str(); - i++; } else if (elementStartsWith(inner, MUT)) { mutable_ = true; - type = stringToType(inner[1]->str()); - i++; + type = elementToType(*inner[1]); + break; } else { + type = elementToType(inner); break; } } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 9b5dc3f22..48fe79fa1 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -114,13 +114,21 @@ void BinaryInstWriter::visitLocalSet(LocalSet* curr) { } void BinaryInstWriter::visitGlobalGet(GlobalGet* curr) { - o << int8_t(BinaryConsts::GlobalGet) - << U32LEB(parent.getGlobalIndex(curr->name)); + // Emit a global.get for each element if this is a tuple global + Index index = parent.getGlobalIndex(curr->name); + size_t numValues = curr->type.size(); + for (Index i = 0; i < numValues; ++i) { + o << int8_t(BinaryConsts::GlobalGet) << U32LEB(index + i); + } } void BinaryInstWriter::visitGlobalSet(GlobalSet* curr) { - o << int8_t(BinaryConsts::GlobalSet) - << U32LEB(parent.getGlobalIndex(curr->name)); + // Emit a global.set for each element if this is a tuple global + Index index = parent.getGlobalIndex(curr->name); + size_t numValues = parent.getModule()->getGlobal(curr->name)->type.size(); + for (int i = numValues - 1; i >= 0; --i) { + o << int8_t(BinaryConsts::GlobalSet) << U32LEB(index + i); + } } void BinaryInstWriter::visitLoad(Load* curr) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 368c01bdc..c152e4b98 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2137,12 +2137,14 @@ static void validateImports(Module& module, ValidationInfo& info) { } } }); - if (!module.features.hasMutableGlobals()) { - ModuleUtils::iterImportedGlobals(module, [&](Global* curr) { + ModuleUtils::iterImportedGlobals(module, [&](Global* curr) { + if (!module.features.hasMutableGlobals()) { info.shouldBeFalse( curr->mutable_, curr->name, "Imported global cannot be mutable"); - }); - } + } + info.shouldBeTrue( + curr->type.isSingle(), curr->name, "Imported global cannot be tuple"); + }); } static void validateExports(Module& module, ValidationInfo& info) { @@ -2164,11 +2166,14 @@ static void validateExports(Module& module, ValidationInfo& info) { "Exported function must not have i64 results"); } } - } else if (curr->kind == ExternalKind::Global && - !module.features.hasMutableGlobals()) { + } else if (curr->kind == ExternalKind::Global) { if (Global* g = module.getGlobalOrNull(curr->value)) { - info.shouldBeFalse( - g->mutable_, g->name, "Exported global cannot be mutable"); + if (!module.features.hasMutableGlobals()) { + info.shouldBeFalse( + g->mutable_, g->name, "Exported global cannot be mutable"); + } + info.shouldBeTrue( + g->type.isSingle(), g->name, "Exported global cannot be tuple"); } } } |