summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-08-19 09:49:38 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-09-07 09:55:03 -0700
commit266e922cddf0a5c78ed22f046eeebc053a9305c0 (patch)
tree2dec707b00304b1a6c888efb8f2c1b9a19ce38f3 /src
parent9660c200eff60c10266a85aae0637b495c4cba39 (diff)
downloadbinaryen-266e922cddf0a5c78ed22f046eeebc053a9305c0.tar.gz
binaryen-266e922cddf0a5c78ed22f046eeebc053a9305c0.tar.bz2
binaryen-266e922cddf0a5c78ed22f046eeebc053a9305c0.zip
use globals in asm2wasm
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h94
-rw-r--r--src/js/wasm.js-post.js28
-rw-r--r--src/passes/Print.cpp6
-rw-r--r--src/passes/Vacuum.cpp2
-rw-r--r--src/shell-interface.h8
-rw-r--r--src/tools/asm2wasm.cpp12
-rw-r--r--src/wasm-binary.h49
-rw-r--r--src/wasm-interpreter.h18
-rw-r--r--src/wasm-js.cpp42
-rw-r--r--src/wasm-s-parser.h15
10 files changed, 131 insertions, 143 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 48c52080d..a85fd4676 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -143,15 +143,13 @@ class Asm2WasmBuilder {
// globals
- unsigned nextGlobal; // next place to put a global
- unsigned maxGlobal; // highest address we can put a global
struct MappedGlobal {
- unsigned address;
WasmType type;
bool import; // if true, this is an import - we should read the value, not just set a zero
IString module, base;
- MappedGlobal() : address(0), type(none), import(false) {}
- MappedGlobal(unsigned address, WasmType type, bool import, IString module, IString base) : address(address), type(type), import(import), module(module), base(base) {}
+ MappedGlobal() : type(none), import(false) {}
+ MappedGlobal(WasmType type) : type(type), import(false) {}
+ MappedGlobal(WasmType type, bool import, IString module, IString base) : type(type), import(import), module(module), base(base) {}
};
// function table
@@ -165,31 +163,20 @@ class Asm2WasmBuilder {
public:
std::map<IString, MappedGlobal> mappedGlobals;
- // the global mapping info is not present in the output wasm. We need to save it on the side
- // if we intend to load and run this module's wasm.
- void serializeMappedGlobals(const char *filename) {
- FILE *f = fopen(filename, "w");
- assert(f);
- fprintf(f, "{\n");
- bool first = true;
- for (auto& pair : mappedGlobals) {
- auto name = pair.first;
- auto& global = pair.second;
- if (first) first = false;
- else fprintf(f, ",");
- fprintf(f, "\"%s\": { \"address\": %d, \"type\": %d, \"import\": %d, \"module\": \"%s\", \"base\": \"%s\" }\n",
- name.str, global.address, global.type, global.import, global.module.str, global.base.str);
- }
- fprintf(f, "}");
- fclose(f);
- }
-
private:
- void allocateGlobal(IString name, WasmType type, bool import, IString module = IString(), IString base = IString()) {
+ void allocateGlobal(IString name, WasmType type) {
assert(mappedGlobals.find(name) == mappedGlobals.end());
- mappedGlobals.emplace(name, MappedGlobal(nextGlobal, type, import, module, base));
- nextGlobal += 8;
- assert(nextGlobal < maxGlobal);
+ mappedGlobals.emplace(name, MappedGlobal(type));
+ auto global = new Global();
+ global->name = name;
+ global->type = type;
+ Literal value;
+ if (type == i32) value = Literal(uint32_t(0));
+ else if (type == f32) value = Literal(float(0));
+ else if (type == f64) value = Literal(double(0));
+ else WASM_UNREACHABLE();
+ global->init = wasm.allocator.alloc<Const>()->set(value);
+ wasm.addGlobal(global);
}
struct View {
@@ -278,8 +265,6 @@ public:
: wasm(wasm),
allocator(wasm.allocator),
builder(wasm),
- nextGlobal(8),
- maxGlobal(1000),
memoryGrowth(memoryGrowth),
debug(debug),
imprecise(imprecise),
@@ -520,13 +505,13 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
type = WasmType::f64;
}
if (type != WasmType::none) {
- // wasm has no imported constants, so allocate a global, and we need to write the value into that
- allocateGlobal(name, type, true, import->module, import->base);
- delete import;
+ import->kind = Import::Global;
+ import->globalType = type;
+ mappedGlobals.emplace(name, type);
} else {
import->kind = Import::Function;
- wasm.addImport(import);
}
+ wasm.addImport(import);
};
IString Int8Array, Int16Array, Int32Array, UInt8Array, UInt16Array, UInt32Array, Float32Array, Float64Array;
@@ -554,7 +539,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
if (value[0] == NUM) {
// global int
assert(value[1]->getNumber() == 0);
- allocateGlobal(name, WasmType::i32, false);
+ allocateGlobal(name, WasmType::i32);
} else if (value[0] == BINARY) {
// int import
assert(value[1] == OR && value[3][0] == NUM && value[3][1]->getNumber() == 0);
@@ -567,14 +552,14 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
if (import[0] == NUM) {
// global
assert(import[1]->getNumber() == 0);
- allocateGlobal(name, WasmType::f64, false);
+ allocateGlobal(name, WasmType::f64);
} else {
// import
addImport(name, import, WasmType::f64);
}
} else if (value[0] == CALL) {
assert(value[1][0] == NAME && value[1][1] == Math_fround && value[2][0][0] == NUM && value[2][0][1]->getNumber() == 0);
- allocateGlobal(name, WasmType::f32, false);
+ allocateGlobal(name, WasmType::f32);
} else if (value[0] == DOT) {
// simple module.base import. can be a view, or a function.
if (value[1][0] == NAME) {
@@ -721,11 +706,9 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
if (optimize) {
optimizingBuilder->finish();
- if (maxGlobal < 1024) {
- PassRunner passRunner(&wasm);
- passRunner.add("post-emscripten");
- passRunner.run();
- }
+ PassRunner passRunner(&wasm);
+ passRunner.add("post-emscripten");
+ passRunner.run();
}
// second pass. first, function imports
@@ -733,6 +716,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
std::vector<IString> toErase;
for (auto& import : wasm.imports) {
+ if (import->kind != Import::Function) continue;
IString name = import->name;
if (importedFunctionTypes.find(name) != importedFunctionTypes.end()) {
// special math builtins
@@ -1021,18 +1005,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
ret->finalize();
return ret;
}
- // global var, do a store to memory
+ // global var
assert(mappedGlobals.find(name) != mappedGlobals.end());
- MappedGlobal global = mappedGlobals[name];
- auto ret = allocator.alloc<Store>();
- ret->bytes = getWasmTypeSize(global.type);
- ret->offset = 0;
- ret->align = ret->bytes;
- ret->ptr = builder.makeConst(Literal(int32_t(global.address)));
- ret->value = process(ast[3]);
- ret->valueType = global.type;
- ret->finalize();
- return ret;
+ return builder.makeSetGlobal(name, process(ast[3]));
} else if (ast[2][0] == SUB) {
Ref target = ast[2];
assert(target[1][0] == NAME);
@@ -1158,17 +1133,10 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
}
return call;
}
- // global var, do a load from memory
+ // global var
assert(mappedGlobals.find(name) != mappedGlobals.end());
- MappedGlobal global = mappedGlobals[name];
- auto ret = allocator.alloc<Load>();
- ret->bytes = getWasmTypeSize(global.type);
- ret->signed_ = true; // but doesn't matter
- ret->offset = 0;
- ret->align = ret->bytes;
- ret->ptr = builder.makeConst(Literal(int32_t(global.address)));
- ret->type = global.type;
- return ret;
+ MappedGlobal& global = mappedGlobals[name];
+ return builder.makeGetGlobal(name, global.type);
} else if (what == SUB) {
Ref target = ast[1];
assert(target[0] == NAME);
diff --git a/src/js/wasm.js-post.js b/src/js/wasm.js-post.js
index ae42ef175..1c207b3f3 100644
--- a/src/js/wasm.js-post.js
+++ b/src/js/wasm.js-post.js
@@ -123,26 +123,6 @@ function integrateWasmJS(Module) {
f64: 4
};
- // wasm lacks globals, so asm2wasm maps them into locations in memory. that information cannot
- // be present in the wasm output of asm2wasm, so we store it in a side file. If we load asm2wasm
- // output, either generated ahead of time or on the client, we need to apply those mapped
- // globals after loading the module.
- function applyMappedGlobals(globalsFileBase) {
- var mappedGlobals = JSON.parse(Module['read'](globalsFileBase + '.mappedGlobals'));
- for (var name in mappedGlobals) {
- var global = mappedGlobals[name];
- if (!global.import) continue; // non-imports are initialized to zero in the typed array anyhow, so nothing to do here
- var value = lookupImport(global.module, global.base);
- var address = global.address;
- switch (global.type) {
- case WasmTypes.i32: Module['HEAP32'][address >> 2] = value; break;
- case WasmTypes.f32: Module['HEAPF32'][address >> 2] = value; break;
- case WasmTypes.f64: Module['HEAPF64'][address >> 3] = value; break;
- default: abort();
- }
- }
- }
-
function fixImports(imports) {
if (!{{{ WASM_BACKEND }}}) return imports;
var ret = {};
@@ -208,8 +188,6 @@ function integrateWasmJS(Module) {
exports = instance.exports;
mergeMemory(exports.memory);
- applyMappedGlobals(wasmBinaryFile);
-
Module["usingWasm"] = true;
return exports;
@@ -271,12 +249,6 @@ function integrateWasmJS(Module) {
Module['newBuffer'] = null;
}
- if (method == 'interpret-s-expr') {
- applyMappedGlobals(wasmTextFile);
- } else if (method == 'interpret-binary') {
- applyMappedGlobals(wasmBinaryFile);
- }
-
exports = wasmJS['asmExports'];
return exports;
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index fcd155650..fe125234d 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -531,6 +531,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
void visitImport(Import *curr) {
printOpening(o, "import ");
+ printName(curr->name) << ' ';
switch (curr->kind) {
case Export::Function: break;
case Export::Table: o << "table "; break;
@@ -538,14 +539,13 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
case Export::Global: o << "global "; break;
default: WASM_UNREACHABLE();
}
- printName(curr->name) << ' ';
printText(o, curr->module.str) << ' ';
printText(o, curr->base.str);
switch (curr->kind) {
case Export::Function: if (curr->functionType) visitFunctionType(curr->functionType); break;
case Export::Table: break;
case Export::Memory: break;
- case Export::Global: o << printWasmType(curr->globalType); break;
+ case Export::Global: o << ' ' << printWasmType(curr->globalType); break;
default: WASM_UNREACHABLE();
}
o << ')';
@@ -564,7 +564,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
void visitGlobal(Global *curr) {
printOpening(o, "global ");
- printName(curr->name) << ' ' << printWasmType(curr->type);
+ printName(curr->name) << ' ' << printWasmType(curr->type) << ' ';
visit(curr->init);
o << ')';
}
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index bb005e36c..150593713 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -50,6 +50,8 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum, Visitor<Vacuum>>
case Expression::Id::LoadId:
case Expression::Id::StoreId:
case Expression::Id::ReturnId:
+ case Expression::Id::GetGlobalId:
+ case Expression::Id::SetGlobalId:
case Expression::Id::HostId:
case Expression::Id::UnreachableId: return curr; // always needed
diff --git a/src/shell-interface.h b/src/shell-interface.h
index f9afe21fb..ee9ff166a 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -90,11 +90,11 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
ShellExternalInterface() : memory() {}
- void init(Module& wasm) override {
+ void init(Module& wasm, ModuleInstance& instance) override {
memory.resize(wasm.memory.initial * wasm::Memory::kPageSize);
// apply memory segments
for (auto& segment : wasm.memory.segments) {
- Address offset = ConstantExpressionRunner().visit(segment.offset).value.geti32();
+ Address offset = ConstantExpressionRunner(instance.globals).visit(segment.offset).value.geti32();
assert(offset + segment.data.size() <= wasm.memory.initial * wasm::Memory::kPageSize);
for (size_t i = 0; i != segment.data.size(); ++i) {
memory.set(offset + i, segment.data[i]);
@@ -103,7 +103,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
table.resize(wasm.table.initial);
for (auto& segment : wasm.table.segments) {
- Address offset = ConstantExpressionRunner().visit(segment.offset).value.geti32();
+ Address offset = ConstantExpressionRunner(instance.globals).visit(segment.offset).value.geti32();
assert(offset + segment.data.size() <= wasm.table.initial);
for (size_t i = 0; i != segment.data.size(); ++i) {
table[offset + i] = segment.data[i];
@@ -111,6 +111,8 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
}
}
+ void importGlobals(std::map<Name, Literal>& globals, Module& wasm) override {}
+
Literal callImport(Import *import, LiteralList& arguments) override {
if (import->module == SPECTEST && import->base == PRINT) {
for (auto argument : arguments) {
diff --git a/src/tools/asm2wasm.cpp b/src/tools/asm2wasm.cpp
index 7f1a07d1d..beacc884c 100644
--- a/src/tools/asm2wasm.cpp
+++ b/src/tools/asm2wasm.cpp
@@ -42,7 +42,7 @@ int main(int argc, const char *argv[]) {
})
.add("--mapped-globals", "-m", "Mapped globals", Options::Arguments::One,
[](Options *o, const std::string &argument) {
- o->extra["mapped globals"] = argument;
+ std::cerr << "warning: the --mapped-globals/-m option is deprecated (a mapped globals file is no longer needed as we use wasm globals)" << std::endl;
})
.add("--total-memory", "-m", "Total memory size", Options::Arguments::One,
[](Options *o, const std::string &argument) {
@@ -62,10 +62,6 @@ int main(int argc, const char *argv[]) {
});
options.parse(argc, argv);
- const auto &mg_it = options.extra.find("mapped globals");
- const char *mappedGlobals =
- mg_it == options.extra.end() ? nullptr : mg_it->second.c_str();
-
const auto &tm_it = options.extra.find("total memory");
size_t totalMemory =
tm_it == options.extra.end() ? 16 * 1024 * 1024 : atoi(tm_it->second.c_str());
@@ -99,11 +95,5 @@ int main(int argc, const char *argv[]) {
Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release);
WasmPrinter::printModule(&wasm, output.getStream());
- if (mappedGlobals) {
- if (options.debug)
- std::cerr << "serializing mapped globals..." << std::endl;
- asm2wasm.serializeMappedGlobals(mappedGlobals);
- }
-
if (options.debug) std::cerr << "done." << std::endl;
}
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index d6671be01..40671b082 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -741,7 +741,7 @@ public:
return mappedImports[name];
}
- std::map<Name, uint32_t> mappedFunctions; // name of the Function => index
+ std::map<Name, uint32_t> mappedFunctions; // name of the Function => index
uint32_t getFunctionIndex(Name name) {
if (!mappedFunctions.size()) {
// Create name => index mapping.
@@ -754,13 +754,20 @@ public:
return mappedFunctions[name];
}
- std::map<Name, uint32_t> mappedGlobals; // name of the Global => index
+ std::map<Name, uint32_t> mappedGlobals; // name of the Global => index. first imported globals, then internal globals
uint32_t getGlobalIndex(Name name) {
if (!mappedGlobals.size()) {
// Create name => index mapping.
+ for (auto& import : wasm->imports) {
+ if (import->kind != Import::Global) continue;
+ assert(mappedGlobals.count(import->name) == 0);
+ auto index = mappedGlobals.size();
+ mappedGlobals[import->name] = index;
+ }
for (size_t i = 0; i < wasm->globals.size(); i++) {
assert(mappedGlobals.count(wasm->globals[i]->name) == 0);
- mappedGlobals[wasm->globals[i]->name] = i;
+ auto index = mappedGlobals.size();
+ mappedGlobals[wasm->globals[i]->name] = index;
}
}
assert(mappedGlobals.count(name));
@@ -1664,6 +1671,24 @@ public:
return ret;
}
+ std::map<Index, Name> mappedGlobals; // index of the Global => name. first imported globals, then internal globals
+ Name getGlobalName(Index index) {
+ if (!mappedGlobals.size()) {
+ // Create name => index mapping.
+ for (auto& import : wasm.imports) {
+ if (import->kind != Import::Global) continue;
+ auto index = mappedGlobals.size();
+ mappedGlobals[index] = import->name;
+ }
+ for (size_t i = 0; i < wasm.globals.size(); i++) {
+ auto index = mappedGlobals.size();
+ mappedGlobals[index] = wasm.globals[i]->name;
+ }
+ }
+ assert(mappedGlobals.count(index));
+ return mappedGlobals[index];
+ }
+
void processFunctions() {
for (auto& func : functions) {
wasm.addFunction(func);
@@ -1680,7 +1705,7 @@ public:
case Export::Function: curr->value = wasm.functions[iter.second]->name; break;
case Export::Table: curr->value = Name::fromInt(0); break;
case Export::Memory: curr->value = Name::fromInt(0); break;
- case Export::Global: curr->value = wasm.globals[iter.second]->name; break;
+ case Export::Global: curr->value = getGlobalName(iter.second); break;
default: WASM_UNREACHABLE();
}
wasm.addExport(curr);
@@ -1975,13 +2000,23 @@ public:
void visitGetGlobal(GetGlobal *curr) {
if (debug) std::cerr << "zz node: GetGlobal " << pos << std::endl;
auto index = getU32LEB();
- curr->name = wasm.getGlobal(index)->name;
- curr->type = wasm.getGlobal(index)->type;
+ curr->name = getGlobalName(index);
+ auto* global = wasm.checkGlobal(curr->name);
+ if (global) {
+ curr->type = global->type;
+ return;
+ }
+ auto* import = wasm.checkImport(curr->name);
+ if (import && import->kind == Import::Global) {
+ curr->type = import->globalType;
+ return;
+ }
+ throw ParseException("bad get_global");
}
void visitSetGlobal(SetGlobal *curr) {
if (debug) std::cerr << "zz node: SetGlobal" << std::endl;
auto index = getU32LEB();
- curr->name = wasm.getGlobal(index)->name;
+ curr->name = getGlobalName(index);
curr->value = popExpression();
}
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index db55cd143..292d6a521 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -485,14 +485,17 @@ public:
// Execute an constant expression in a global init or memory offset
class ConstantExpressionRunner : public ExpressionRunner<ConstantExpressionRunner> {
+ std::map<Name, Literal>& globals;
public:
+ ConstantExpressionRunner(std::map<Name, Literal>& globals) : globals(globals) {}
+
Flow visitLoop(Loop* curr) { WASM_UNREACHABLE(); }
Flow visitCall(Call* curr) { WASM_UNREACHABLE(); }
Flow visitCallImport(CallImport* curr) { WASM_UNREACHABLE(); }
Flow visitCallIndirect(CallIndirect* curr) { WASM_UNREACHABLE(); }
Flow visitGetLocal(GetLocal *curr) { WASM_UNREACHABLE(); }
Flow visitSetLocal(SetLocal *curr) { WASM_UNREACHABLE(); }
- Flow visitGetGlobal(GetGlobal *curr) { WASM_UNREACHABLE(); }
+ Flow visitGetGlobal(GetGlobal *curr) { return Flow(globals[curr->name]); }
Flow visitSetGlobal(SetGlobal *curr) { WASM_UNREACHABLE(); }
Flow visitLoad(Load *curr) { WASM_UNREACHABLE(); }
Flow visitStore(Store *curr) { WASM_UNREACHABLE(); }
@@ -517,7 +520,8 @@ public:
// an imported function or accessing memory.
//
struct ExternalInterface {
- virtual void init(Module& wasm) {}
+ virtual void init(Module& wasm, ModuleInstance& instance) {}
+ virtual void importGlobals(std::map<Name, Literal>& globals, Module& wasm) = 0;
virtual Literal callImport(Import* import, LiteralList& arguments) = 0;
virtual Literal callTable(Index index, LiteralList& arguments, WasmType result, ModuleInstance& instance) = 0;
virtual Literal load(Load* load, Address addr) = 0;
@@ -532,11 +536,17 @@ public:
std::map<Name, Literal> globals;
ModuleInstance(Module& wasm, ExternalInterface* externalInterface) : wasm(wasm), externalInterface(externalInterface) {
+ // import globals from the outside
+ externalInterface->importGlobals(globals, wasm);
+ // prepare memory
memorySize = wasm.memory.initial;
+ // generate internal (non-imported) globals
for (auto& global : wasm.globals) {
- globals[global->name] = ConstantExpressionRunner().visit(global->init).value;
+ globals[global->name] = ConstantExpressionRunner(globals).visit(global->init).value;
}
- externalInterface->init(wasm);
+ // initialize the rest of the external interface
+ externalInterface->init(wasm, *this);
+ // run start, if present
if (wasm.start.is()) {
LiteralList arguments;
callFunction(wasm.start, arguments);
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index 3c3c4eec7..fc27bc37a 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -81,21 +81,6 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm2wasm(char *input) {
if (wasmJSDebug) std::cerr << "wasming...\n";
asm2wasm = new Asm2WasmBuilder(*module, pre.memoryGrowth, debug, false /* TODO: support imprecise? */, false /* TODO: support optimizing? */);
asm2wasm->processAsm(asmjs);
-
- if (wasmJSDebug) std::cerr << "mapping globals...\n";
- for (auto& pair : asm2wasm->mappedGlobals) {
- auto name = pair.first;
- auto& global = pair.second;
- if (!global.import) continue; // non-imports are initialized to zero in the typed array anyhow, so nothing to do here
- double value = EM_ASM_DOUBLE({ return Module['lookupImport'](Pointer_stringify($0), Pointer_stringify($1)) }, global.module.str, global.base.str);
- uint32_t address = global.address;
- switch (global.type) {
- case i32: EM_ASM_({ Module['info'].parent['HEAP32'][$0 >> 2] = $1 }, address, value); break;
- case f32: EM_ASM_({ Module['info'].parent['HEAPF32'][$0 >> 2] = $1 }, address, value); break;
- case f64: EM_ASM_({ Module['info'].parent['HEAPF64'][$0 >> 3] = $1 }, address, value); break;
- default: abort();
- }
- }
}
void finalizeModule() {
@@ -176,14 +161,14 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
var mod = Pointer_stringify($0);
var base = Pointer_stringify($1);
var name = Pointer_stringify($2);
- assert(Module['lookupImport'](mod, base), 'checking import ' + name + ' = ' + mod + '.' + base);
+ assert(Module['lookupImport'](mod, base) !== undefined, 'checking import ' + name + ' = ' + mod + '.' + base);
}, import->module.str, import->base.str, import->name.str);
}
if (wasmJSDebug) std::cerr << "creating instance...\n";
struct JSExternalInterface : ModuleInstance::ExternalInterface {
- void init(Module& wasm) override {
+ void init(Module& wasm, ModuleInstance& instance) override {
// create a new buffer here, just like native wasm support would.
EM_ASM_({
Module['outside']['newBuffer'] = new ArrayBuffer($0);
@@ -193,7 +178,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
var source = Module['HEAP8'].subarray($1, $1 + $2);
var target = new Int8Array(Module['outside']['newBuffer']);
target.set(source, $0);
- }, ConstantExpressionRunner().visit(segment.offset).value.geti32(), &segment.data[0], segment.data.size());
+ }, ConstantExpressionRunner(instance.globals).visit(segment.offset).value.geti32(), &segment.data[0], segment.data.size());
}
// Table support is in a JS array. If the entry is a number, it's a function pointer. If not, it's a JS method to be called directly
// TODO: make them all JS methods, wrapping a dynCall where necessary?
@@ -201,7 +186,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
Module['outside']['wasmTable'] = new Array($0);
}, wasm.table.initial);
for (auto segment : wasm.table.segments) {
- Address offset = ConstantExpressionRunner().visit(segment.offset).value.geti32();
+ Address offset = ConstantExpressionRunner(instance.globals).visit(segment.offset).value.geti32();
assert(offset + segment.data.size() <= wasm.table.initial);
for (size_t i = 0; i != segment.data.size(); ++i) {
EM_ASM_({
@@ -238,6 +223,23 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
}
}
+ void importGlobals(std::map<Name, Literal>& globals, Module& wasm) override {
+ for (auto& import : wasm.imports) {
+ if (import->kind == Import::Global) {
+ double ret = EM_ASM_DOUBLE({
+ var mod = Pointer_stringify($0);
+ var base = Pointer_stringify($1);
+ var lookup = Module['lookupImport'](mod, base);
+ return lookup;
+ }, import->module.str, import->base.str);
+
+ if (wasmJSDebug) std::cout << "calling importGlobal for " << import->name << " returning " << ret << '\n';
+
+ globals[import->name] = getResultFromJS(ret, import->globalType);
+ }
+ }
+ }
+
Literal callImport(Import *import, LiteralList& arguments) override {
if (wasmJSDebug) std::cout << "calling import " << import->name.str << '\n';
prepareTempArgments(arguments);
@@ -252,7 +254,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
if (wasmJSDebug) std::cout << "calling import returning " << ret << '\n';
- return getResultFromJS(ret, import->type->result);
+ return getResultFromJS(ret, import->functionType->result);
}
Literal callTable(Index index, LiteralList& arguments, WasmType result, ModuleInstance& instance) override {
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 60cc21e26..65335c1be 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -949,9 +949,16 @@ private:
auto ret = allocator.alloc<GetGlobal>();
ret->name = s[1]->str();
auto* global = wasm.checkGlobal(ret->name);
- if (!global) throw ParseException("bad get_global name", s.line, s.col);
- ret->type = global->type;
- return ret;
+ if (global) {
+ ret->type = global->type;
+ return ret;
+ }
+ auto* import = wasm.checkImport(ret->name);
+ if (import && import->kind == Import::Global) {
+ ret->type = import->globalType;
+ return ret;
+ }
+ throw ParseException("bad get_global name", s.line, s.col);
}
Expression* makeSetGlobal(Element& s) {
@@ -1434,7 +1441,7 @@ private:
} else if (s[2]->str() == TABLE) {
im->kind = Import::Table;
} else if (s[2]->str() == GLOBAL) {
- im->kind = Import::Table;
+ im->kind = Import::Global;
} else {
WASM_UNREACHABLE();
}