summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp21
-rw-r--r--src/wasm/wasm-s-parser.cpp28
-rw-r--r--src/wasm/wasm-stack.cpp16
-rw-r--r--src/wasm/wasm-validator.cpp21
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");
}
}
}