Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/tools/wasm-opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ int main(int argc, const char* argv[]) {
// It should be safe to just always enable atomics in wasm-opt, because we
// don't expect any passes to accidentally generate atomic ops
FeatureSet features = Feature::Atomics;
// Same for MutableGlobals
features |= Feature::MutableGlobals;

if (options.debug) std::cerr << "reading...\n";

Expand Down
1 change: 1 addition & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ namespace wasm {
enum Feature : uint32_t {
MVP = 0,
Atomics = 1 << 0,
MutableGlobals = 1 << 1,
All = 0xffffffff,
};
typedef uint32_t FeatureSet;
Expand Down
3 changes: 1 addition & 2 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ void WasmBinaryWriter::writeImports() {
writeImportHeader(global);
o << U32LEB(int32_t(ExternalKind::Global));
o << binaryType(global->type);
o << U32LEB(0); // Mutable globals can't be imported for now.
o << U32LEB(global->mutable_);
});
if (wasm->memory.imported()) {
if (debug) std::cerr << "write one memory" << std::endl;
Expand Down Expand Up @@ -1009,7 +1009,6 @@ void WasmBinaryBuilder::readImports() {
auto name = Name(std::string("gimport$") + std::to_string(i));
auto type = getConcreteType();
auto mutable_ = getU32LEB();
assert(!mutable_); // for now, until mutable globals
auto* curr = builder.makeGlobal(name, type, nullptr, mutable_ ? Builder::Mutable : Builder::Immutable);
curr->module = module;
curr->base = base;
Expand Down
6 changes: 4 additions & 2 deletions src/wasm/wasm-s-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1487,19 +1487,21 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.addFunction(func.release());
} else if (kind == ExternalKind::Global) {
Type type;
bool mutable_ = false;
if (inner[j]->isStr()) {
type = stringToType(inner[j]->str());
} else {
auto& inner2 = *inner[j];
if (inner2[0]->str() != MUT) throw ParseException("expected mut");
type = stringToType(inner2[1]->str());
throw ParseException("cannot import a mutable global", s.line, s.col);
mutable_ = true;
}
auto global = make_unique<Global>();
global->name = name;
global->module = module;
global->base = base;
global->type = type;
global->mutable_ = mutable_;
wasm.addGlobal(global.release());
} else if (kind == ExternalKind::Table) {
wasm.table.module = module;
Expand Down Expand Up @@ -1571,12 +1573,12 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
if (importModule.is()) {
// this is an import, actually
if (!preParseImport) throw ParseException("!preParseImport in global");
if (mutable_) throw ParseException("cannot import a mutable global", s.line, s.col);
auto im = make_unique<Global>();
im->name = global->name;
im->module = importModule;
im->base = importBase;
im->type = type;
im->mutable_ = mutable_;
if (wasm.getGlobalOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
wasm.addGlobal(im.release());
return;
Expand Down
9 changes: 9 additions & 0 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,11 @@ static void validateImports(Module& module, ValidationInfo& info) {
}
}
});
if (!(info.features & Feature::MutableGlobals)) {
ModuleUtils::iterImportedGlobals(module, [&](Global* curr) {
info.shouldBeFalse(curr->mutable_, curr->name, "Imported global cannot be mutable");
});
}
}

static void validateExports(Module& module, ValidationInfo& info) {
Expand All @@ -935,6 +940,10 @@ static void validateExports(Module& module, ValidationInfo& info) {
info.shouldBeUnequal(param, i64, f->name, "Exported function must not have i64 parameters");
}
}
} else if (curr->kind == ExternalKind::Global && !(info.features & Feature::MutableGlobals)) {
if (Global* g = module.getGlobalOrNull(curr->value)) {
info.shouldBeFalse(g->mutable_, g->name, "Exported global cannot be mutable");
}
}
}
std::unordered_set<Name> exportNames;
Expand Down
Binary file added test/mutable-global.wasm
Binary file not shown.
13 changes: 13 additions & 0 deletions test/mutable-global.wasm.fromBinary
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(module
(type $0 (func))
(import "env" "global-mut" (global $gimport$0 (mut i32)))
(func $0 (; 0 ;) (type $0)
(set_global $gimport$0
(i32.add
(get_global $gimport$0)
(i32.const 1)
)
)
)
)

12 changes: 12 additions & 0 deletions test/mutable-global.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(module
(type $0 (func))
(import "env" "global-mut" (global $global-mut (mut i32)))
(func $foo (type $0)
(set_global $global-mut
(i32.add
(get_global $global-mut)
(i32.const 1)
)
)
)
)
12 changes: 12 additions & 0 deletions test/mutable-global.wast.from-wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(module
(type $0 (func))
(import "env" "global-mut" (global $global-mut (mut i32)))
(func $foo (; 0 ;) (type $0)
(set_global $global-mut
(i32.add
(get_global $global-mut)
(i32.const 1)
)
)
)
)
13 changes: 13 additions & 0 deletions test/mutable-global.wast.fromBinary
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(module
(type $0 (func))
(import "env" "global-mut" (global $gimport$0 (mut i32)))
(func $foo (; 0 ;) (type $0)
(set_global $gimport$0
(i32.add
(get_global $gimport$0)
(i32.const 1)
)
)
)
)

13 changes: 13 additions & 0 deletions test/mutable-global.wast.fromBinary.noDebugInfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(module
(type $0 (func))
(import "env" "global-mut" (global $gimport$0 (mut i32)))
(func $0 (; 0 ;) (type $0)
(set_global $gimport$0
(i32.add
(get_global $gimport$0)
(i32.const 1)
)
)
)
)