summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/LegalizeJSInterface.cpp83
1 files changed, 26 insertions, 57 deletions
diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp
index 5f64ad2e6..96aed9636 100644
--- a/src/passes/LegalizeJSInterface.cpp
+++ b/src/passes/LegalizeJSInterface.cpp
@@ -28,14 +28,16 @@
#include "wasm.h"
#include "pass.h"
+#include "asm_v_wasm.h"
+#include "asmjs/shared-constants.h"
#include "wasm-builder.h"
#include "ir/function-type-utils.h"
+#include "ir/import-utils.h"
#include "ir/literal-utils.h"
#include "ir/utils.h"
namespace wasm {
-Name TEMP_RET_0("tempRet0");
Name GET_TEMP_RET_0("getTempRet0");
Name SET_TEMP_RET_0("setTempRet0");
@@ -103,18 +105,12 @@ struct LegalizeJSInterface : public Pass {
passRunner.add<FixImports>(&illegalImportsToLegal);
passRunner.run();
}
-
- if (needTempRet0Helpers) {
- addTempRet0Helpers(module);
- }
}
private:
// map of illegal to legal names for imports
std::map<Name, Name> illegalImportsToLegal;
- bool needTempRet0Helpers = false;
-
template<typename T>
bool isIllegal(T* t) {
for (auto param : t->params) {
@@ -124,6 +120,7 @@ private:
return false;
}
+
// JS calls the export, so it must call a legal stub that calls the actual wasm function
Name makeLegalStub(Function* func, Module* module) {
Builder builder(*module);
@@ -149,15 +146,12 @@ private:
}
if (func->result == i64) {
+ Function* f = getFunctionOrImport(module, SET_TEMP_RET_0, "vi");
legal->result = i32;
auto index = builder.addVar(legal, Name(), i64);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeSetLocal(index, call));
- ensureTempRet0(module);
- block->list.push_back(builder.makeSetGlobal(
- TEMP_RET_0,
- I64Utilities::getI64High(builder, index)
- ));
+ block->list.push_back(builder.makeCall(f->name, {I64Utilities::getI64High(builder, index)}, none));
block->list.push_back(I64Utilities::getI64Low(builder, index));
block->finalize();
legal->body = block;
@@ -211,10 +205,9 @@ private:
}
if (imFunctionType->result == i64) {
+ Function* f = getFunctionOrImport(module, GET_TEMP_RET_0, "i");
call->type = i32;
- Expression* get;
- ensureTempRet0(module);
- get = builder.makeGetGlobal(TEMP_RET_0, i32);
+ Expression* get = builder.makeCall(f->name, {}, call->type);
func->body = I64Utilities::recreateI64(builder, call, get);
type->result = i32;
} else if (imFunctionType->result == f32) {
@@ -241,50 +234,26 @@ private:
return func->name;
}
- void ensureTempRet0(Module* module) {
- if (!module->getGlobalOrNull(TEMP_RET_0)) {
- module->addGlobal(Builder::makeGlobal(
- TEMP_RET_0,
- i32,
- LiteralUtils::makeZero(i32, *module),
- Builder::Mutable
- ));
- needTempRet0Helpers = true;
+ static Function* getFunctionOrImport(Module* module, Name name, std::string sig) {
+ // First look for the function by name
+ if (Function* f = module->getFunctionOrNull(name)) {
+ return f;
}
- }
-
- void addTempRet0Helpers(Module* module) {
- // We should also let JS access the tempRet0 global, which
- // is necessary to send/receive 64-bit return values.
- auto exportIt = [&](Function* func) {
- auto* export_ = new Export;
- export_->name = func->name;
- export_->value = func->name;
- export_->kind = ExternalKind::Function;
- module->addExport(export_);
- };
- if (!module->getExportOrNull(GET_TEMP_RET_0)) {
- Builder builder(*module);
- auto* func = new Function();
- func->name = GET_TEMP_RET_0;
- func->result = i32;
- func->body = builder.makeGetGlobal(TEMP_RET_0, i32);
- module->addFunction(func);
- exportIt(func);
- }
- if (!module->getExportOrNull(SET_TEMP_RET_0)) {
- Builder builder(*module);
- auto* func = new Function();
- func->name = SET_TEMP_RET_0;
- func->result = none;
- func->params.push_back(i32);
- func->body = builder.makeSetGlobal(
- TEMP_RET_0,
- builder.makeGetLocal(0, i32)
- );
- module->addFunction(func);
- exportIt(func);
+ // Then see if its already imported
+ ImportInfo info(*module);
+ if (Function* f = info.getImportedFunction(ENV, name)) {
+ return f;
}
+ // Failing that create a new function import.
+ auto import = new Function;
+ import->name = name;
+ import->module = ENV;
+ import->base = name;
+ auto* functionType = ensureFunctionType(sig, module);
+ import->type = functionType->name;
+ FunctionTypeUtils::fillFunction(import, functionType);
+ module->addFunction(import);
+ return import;
}
};