Skip to content
Closed
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
3 changes: 2 additions & 1 deletion src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1765,7 +1765,7 @@ BinaryenImportRef BinaryenAddMemoryImport(BinaryenModuleRef module, const char*
wasm->addImport(ret);
return ret;
}
BinaryenImportRef BinaryenAddGlobalImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char* externalBaseName, BinaryenType globalType) {
BinaryenImportRef BinaryenAddGlobalImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char* externalBaseName, BinaryenType globalType, int8_t mutable_) {
auto* wasm = (Module*)module;
auto* ret = new Import();

Expand All @@ -1780,6 +1780,7 @@ BinaryenImportRef BinaryenAddGlobalImport(BinaryenModuleRef module, const char*
ret->base = externalBaseName;
ret->globalType = Type(globalType);
ret->kind = ExternalKind::Global;
ret->mutable_ = !!mutable_;
wasm->addImport(ret);
return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ WASM_DEPRECATED BinaryenImportRef BinaryenAddImport(BinaryenModuleRef module, co
BinaryenImportRef BinaryenAddFunctionImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char *externalBaseName, BinaryenFunctionTypeRef functionType);
BinaryenImportRef BinaryenAddTableImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char *externalBaseName);
BinaryenImportRef BinaryenAddMemoryImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char *externalBaseName);
BinaryenImportRef BinaryenAddGlobalImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char *externalBaseName, BinaryenType globalType);
BinaryenImportRef BinaryenAddGlobalImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char *externalBaseName, BinaryenType globalType, int8_t mutable_);
void BinaryenRemoveImport(BinaryenModuleRef module, const char* internalName);

// Exports
Expand Down
10 changes: 9 additions & 1 deletion src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,15 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
case ExternalKind::Function: if (curr->functionType.is()) visitFunctionType(currModule->getFunctionType(curr->functionType), &curr->name); break;
case ExternalKind::Table: printTableHeader(&currModule->table); break;
case ExternalKind::Memory: printMemoryHeader(&currModule->memory); break;
case ExternalKind::Global: o << "(global " << curr->name << ' ' << printType(curr->globalType) << ")"; break;
case ExternalKind::Global:
o << "(global " << curr->name << ' ';
if (curr->mutable_) {
o << "(mut " << printType(curr->globalType) << ")";
} else {
o << printType(curr->globalType);
}
o << ")";
break;
default: WASM_UNREACHABLE();
}
o << ')';
Expand Down
2 changes: 2 additions & 0 deletions src/tools/wasm-merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct Mergeable {
import->base = MEMORY_BASE;
import->kind = ExternalKind::Global;
import->globalType = i32;
import->mutable_ = false;
wasm.addImport(import);
memoryBaseGlobals.insert(import->name);
}
Expand All @@ -143,6 +144,7 @@ struct Mergeable {
import->base = TABLE_BASE;
import->kind = ExternalKind::Global;
import->globalType = i32;
import->mutable_ = false;
wasm.addImport(import);
tableBaseGlobals.insert(import->name);
}
Expand Down
3 changes: 2 additions & 1 deletion src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -650,12 +650,13 @@ enum class ExternalKind {

class Import {
public:
Import() : globalType(none) {}
Import() : globalType(none), mutable_(false) {}

Name name, module, base; // name = module.base
ExternalKind kind;
Name functionType; // for Function imports
Type globalType; // for Global imports
bool mutable_; // for Global imports
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels dirty but seemed like a simple solution without deciding to completely rethink about imports/globals are represented

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to me. Might be nice to eventually think about a union or other cleaner approach, but Imports are not that common, so I'm not worried about it.

};

class Export {
Expand Down
6 changes: 2 additions & 4 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ void WasmBinaryWriter::writeImports() {
}
case ExternalKind::Global:
o << binaryType(import->globalType);
o << U32LEB(0); // Mutable global's can't be imported for now.
o << U32LEB(import->mutable_);
break;
default: WASM_UNREACHABLE();
}
Expand Down Expand Up @@ -959,9 +959,7 @@ void WasmBinaryBuilder::readImports() {
curr->name = Name(std::string("gimport$") + std::to_string(i));
curr->globalType = getConcreteType();
auto globalMutable = getU32LEB();
// TODO: actually use the globalMutable flag. Currently mutable global
// imports is a future feature, to be implemented with thread support.
(void)globalMutable;
curr->mutable_ = !!globalMutable;
break;
}
default: {
Expand Down
7 changes: 4 additions & 3 deletions src/wasm/wasm-s-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1754,7 +1754,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
auto& inner2 = *inner[j];
if (inner2[0]->str() != MUT) throw ParseException("expected mut");
im->globalType = stringToType(inner2[1]->str());
throw ParseException("cannot import a mutable global", s.line, s.col);
im->mutable_ = true;
}
} else if (im->kind == ExternalKind::Table) {
if (j < inner.size() - 1) {
Expand Down Expand Up @@ -1824,14 +1824,15 @@ 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);
std::unique_ptr<Import> im = make_unique<Import>();
im->name = global->name;
im->module = importModule;
im->base = importBase;
im->kind = ExternalKind::Global;
im->globalType = type;
if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
im->mutable_ = mutable_;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testing revealed I missed adding the support to this file.

if (wasm.getImportOrNull(im->name))
throw ParseException("duplicate import", s.line, s.col);
wasm.addImport(im.release());
return;
}
Expand Down
11 changes: 10 additions & 1 deletion src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,10 +509,19 @@ void FunctionValidator::visitGetGlobal(GetGlobal* curr) {
void FunctionValidator::visitSetGlobal(SetGlobal* curr) {
if (!info.validateGlobally) return;
auto* global = getModule()->getGlobalOrNull(curr->name);
if (shouldBeTrue(global != NULL, curr, "set_global name must be valid (and not an import; imports can't be modified)")) {
if (global) {
shouldBeTrue(global->mutable_, curr, "set_global global must be mutable");
shouldBeEqualOrFirstIsUnreachable(curr->value->type, global->type, curr, "set_global value must have right type");
return;
}
auto* import = getModule()->getImportOrNull(curr->name);
if (import) {
shouldBeTrue(import->kind == ExternalKind::Global, curr, "set_global imported name is not a global");
shouldBeTrue(import->mutable_, curr, "set_global imported global must be mutable");
shouldBeEqualOrFirstIsUnreachable(curr->value->type, import->globalType, curr, "set_global value must have right type");
return;
}
info.fail("set_global global must exist", curr, getFunction());
}

void FunctionValidator::visitLoad(Load* curr) {
Expand Down
2 changes: 1 addition & 1 deletion test/emcc_hello_world.fromasm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 18 18 anyfunc))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32))
(import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import (mut i32)))
(import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32))
(import "env" "tempDoublePtr" (global $tempDoublePtr$asm2wasm$import i32))
(import "env" "abort" (func $abort))
Expand Down
4 changes: 2 additions & 2 deletions test/empty.fromasm.clamp.no-opts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kripken It's not clear why all these changed to mutable. Perhaps this is revealing a bug I introduced?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Is it because those asmjs globals were actually mutable but previously we couldn’t represent that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting - I think that's a coincidence actually, but a good one here as it pointed out something useful :) What I think is going on is that we forgot an initial value for bool mutable_; (unlike the other fields near it, it doesn't have a default value) - we should set that to bool mutable_ = false;.

It's also a good question what we should do for asm.js imports. Yeah, in asm.js they are mutable, and to work around that in wasm we created a mutable global with the initial value of the import, then we just use that global from then on. In theory we could simplify that to use a mutable import, however, I think it would be more complicated than it would be worth since we do want the old form supported too (and also a mutable import may have perf overhead).

(import "env" "tableBase" (global $tableBase (mut i32)))
)
4 changes: 2 additions & 2 deletions test/empty.fromasm.imprecise.no-opts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase (mut i32)))
)
4 changes: 2 additions & 2 deletions test/empty.fromasm.no-opts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase (mut i32)))
)
2 changes: 1 addition & 1 deletion test/hello_world.fromasm.clamp.no-opts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(export "add" (func $add))
(func $add (; 0 ;) (param $x i32) (param $y i32) (result i32)
Expand Down
2 changes: 1 addition & 1 deletion test/hello_world.fromasm.imprecise.no-opts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(export "add" (func $add))
(func $add (; 0 ;) (param $x i32) (param $y i32) (result i32)
Expand Down
2 changes: 1 addition & 1 deletion test/hello_world.fromasm.no-opts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(export "add" (func $add))
(func $add (; 0 ;) (param $x i32) (param $y i32) (result i32)
Expand Down
2 changes: 1 addition & 1 deletion test/i64-setTempRet0.fromasm.clamp.no-opts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
(type $legaltype$illegalImportResult (func (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "illegalImportResult" (func $illegalImportResult (result i64)))
(import "env" "illegalImportResult" (func $legalimport$illegalImportResult (result i32)))
Expand Down
2 changes: 1 addition & 1 deletion test/i64-setTempRet0.fromasm.no-opts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
(type $legaltype$illegalImportResult (func (result i32)))
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "illegalImportResult" (func $illegalImportResult (result i64)))
(import "env" "illegalImportResult" (func $legalimport$illegalImportResult (result i32)))
Expand Down
4 changes: 2 additions & 2 deletions test/memorygrowth.fromasm.clamp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 8 8 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase (mut i32)))
(import "env" "STACKTOP" (global $r$asm2wasm$import i32))
(import "env" "STACK_MAX" (global $s$asm2wasm$import i32))
(import "env" "abort" (func $ja (param i32)))
Expand Down
2 changes: 1 addition & 1 deletion test/merge/fusing.wast.combined
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase$0 i32))
(import "env" "memoryBase" (global $memoryBase$0 (mut i32)))
(import "env" "tableBase" (global $tableBase$0 i32))
(global $a-global i32 (i32.const 0))
(global $b-global f64 (f64.const 2.14281428))
Expand Down
2 changes: 1 addition & 1 deletion test/merge/fusing.wast.combined.finalized
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 8 anyfunc))
(import "env" "memoryBase" (global $memoryBase$0 i32))
(import "env" "memoryBase" (global $memoryBase$0 (mut i32)))
(import "env" "tableBase" (global $tableBase$0 i32))
(global $a-global i32 (i32.const 0))
(global $b-global f64 (f64.const 2.14281428))
Expand Down
4 changes: 2 additions & 2 deletions test/merge/main-lacks-segments.wast.combined.finalized
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(type $0 (func))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase (mut i32)))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 10 anyfunc))
(import "env" "memoryBase" (global $memoryBase$0 i32))
Expand Down
2 changes: 1 addition & 1 deletion test/merge/post-instantiate-b.wast.combined.finalized
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
(type $0 (func))
(type $0$0 (func))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "tableBase" (global $tableBase (mut i32)))
(import "env" "memoryBase" (global $memoryBase$0 i32))
(import "env" "tableBase" (global $tableBase$0 i32))
(export "__post_instantiate" (func $0$0))
Expand Down
2 changes: 1 addition & 1 deletion test/min.fromasm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(global $M (mut i32) (i32.const 0))
(data (get_global $memoryBase) "min.asm.js")
(export "floats" (func $legalstub$floats))
Expand Down
2 changes: 1 addition & 1 deletion test/min.fromasm.clamp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(global $M (mut i32) (i32.const 0))
(data (get_global $memoryBase) "min.asm.js")
(export "floats" (func $legalstub$floats))
Expand Down
2 changes: 1 addition & 1 deletion test/min.fromasm.clamp.no-opts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "tempDoublePtr" (global $tDP$asm2wasm$import i32))
(global $tDP (mut i32) (get_global $tDP$asm2wasm$import))
Expand Down
2 changes: 1 addition & 1 deletion test/min.fromasm.imprecise.no-opts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "tempDoublePtr" (global $tDP$asm2wasm$import i32))
(global $tDP (mut i32) (get_global $tDP$asm2wasm$import))
Expand Down
2 changes: 1 addition & 1 deletion test/min.fromasm.no-opts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "table" (table 0 0 anyfunc))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(import "env" "tableBase" (global $tableBase i32))
(import "env" "tempDoublePtr" (global $tDP$asm2wasm$import i32))
(global $tDP (mut i32) (get_global $tDP$asm2wasm$import))
Expand Down
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)
)
)
)
)

6 changes: 3 additions & 3 deletions test/passes/memory-packing.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(module
(import "env" "memory" (memory $0 2048 2048))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(data (get_global $memoryBase) "waka this cannot be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we don\'t know where it will go")
(data (i32.const 1024) "waka this CAN be optimized")
(data (i32.const 1107) "we DO know where it will go")
Expand All @@ -12,9 +12,9 @@
)
(module
(import "env" "memory" (memory $0 2048 2048))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
)
(module
(import "env" "memory" (memory $0 2048 2048))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
)
2 changes: 1 addition & 1 deletion test/use-import-and-drop.fromasm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(module
(import "env" "memory" (memory $0 256 256))
(import "env" "memoryBase" (global $memoryBase i32))
(import "env" "memoryBase" (global $memoryBase (mut i32)))
(data (get_global $memoryBase) "use-import-and-drop.asm.js")
)
Loading