summaryrefslogtreecommitdiff
path: root/src/passes/I64ToI32Lowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/I64ToI32Lowering.cpp')
-rw-r--r--src/passes/I64ToI32Lowering.cpp59
1 files changed, 26 insertions, 33 deletions
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index 33bb7229e..e6dc90607 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -27,6 +27,7 @@
#include "emscripten-optimizer/istring.h"
#include "support/name.h"
#include "wasm-builder.h"
+#include "abi/js.h"
#include "ir/flat.h"
#include "ir/iteration.h"
#include "ir/memory-utils.h"
@@ -337,25 +338,30 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
template<typename T>
using BuilderFunc = std::function<T*(std::vector<Expression*>&, Type)>;
+ // Fixes up a call. If we performed fixups, returns the call; otherwise returns nullptr;
template<typename T>
- void visitGenericCall(T* curr, BuilderFunc<T> callBuilder) {
+ T* visitGenericCall(T* curr, BuilderFunc<T> callBuilder) {
+ bool fixed = false;
std::vector<Expression*> args;
for (auto* e : curr->operands) {
args.push_back(e);
if (hasOutParam(e)) {
TempVar argHighBits = fetchOutParam(e);
args.push_back(builder->makeGetLocal(argHighBits, i32));
+ fixed = true;
}
}
if (curr->type != i64) {
- replaceCurrent(callBuilder(args, curr->type));
- return;
+ auto* ret = callBuilder(args, curr->type);
+ replaceCurrent(ret);
+ return fixed ? ret : nullptr;
}
TempVar lowBits = getTemp();
TempVar highBits = getTemp();
+ auto* call = callBuilder(args, i32);
SetLocal* doCall = builder->makeSetLocal(
lowBits,
- callBuilder(args, i32)
+ call
);
SetLocal* setHigh = builder->makeSetLocal(
highBits,
@@ -365,14 +371,21 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
Block* result = builder->blockify(doCall, setHigh, getLow);
setOutParam(result, std::move(highBits));
replaceCurrent(result);
+ return call;
}
void visitCall(Call* curr) {
- visitGenericCall<Call>(
+ auto* fixedCall = visitGenericCall<Call>(
curr,
[&](std::vector<Expression*>& args, Type ty) {
return builder->makeCall(curr->target, args, ty);
}
);
+ // If this was to an import, we need to call the legal version. This assumes
+ // that legalize-js-interface has been run before.
+ if (fixedCall && getModule()->getFunction(fixedCall->target)->imported()) {
+ fixedCall->target = std::string("legalfunc$") + fixedCall->target.str;
+ return;
+ }
}
void visitCallIndirect(CallIndirect* curr) {
@@ -635,17 +648,17 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
// our f64 through memory at address 0
TempVar highBits = getTemp();
Block *result = builder->blockify(
- builder->makeStore(8, 0, 8, makeGetTempMemory(), curr->value, f64),
+ builder->makeCall(ABI::wasm2js::SCRATCH_STORE_F64, { curr->value }, none),
builder->makeSetLocal(
highBits,
- builder->makeLoad(4, true, 4, 4, makeGetTempMemory(), i32)
+ builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_I32, { builder->makeConst(Literal(int32_t(1))) }, i32)
),
- builder->makeLoad(4, true, 0, 4, makeGetTempMemory(), i32)
+ builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_I32, { builder->makeConst(Literal(int32_t(0))) }, i32)
);
setOutParam(result, std::move(highBits));
replaceCurrent(result);
MemoryUtils::ensureExists(getModule()->memory);
- ensureTempMemoryGlobal();
+ ABI::wasm2js::ensureScratchMemoryHelpers(getModule());
}
void lowerReinterpretInt64(Unary* curr) {
@@ -653,33 +666,13 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
// our i64 through memory at address 0
TempVar highBits = fetchOutParam(curr->value);
Block *result = builder->blockify(
- builder->makeStore(4, 0, 4, makeGetTempMemory(), curr->value, i32),
- builder->makeStore(4, 4, 4, makeGetTempMemory(), builder->makeGetLocal(highBits, i32), i32),
- builder->makeLoad(8, true, 0, 8, makeGetTempMemory(), f64)
+ builder->makeCall(ABI::wasm2js::SCRATCH_STORE_I32, { builder->makeConst(Literal(int32_t(0))), curr->value }, none),
+ builder->makeCall(ABI::wasm2js::SCRATCH_STORE_I32, { builder->makeConst(Literal(int32_t(1))), builder->makeGetLocal(highBits, i32) }, none),
+ builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_F64, {}, f64)
);
replaceCurrent(result);
MemoryUtils::ensureExists(getModule()->memory);
- ensureTempMemoryGlobal();
- }
-
- Name tempMemory = "__tempMemory__";
-
- void ensureTempMemoryGlobal() {
- // Ensure the existence of an imported global, __tempMemory__, which points to 8
- // bytes of scratch memory we can use for roundtrip purposes.
- if (!getModule()->getGlobalOrNull(tempMemory)) {
- auto global = make_unique<Global>();
- global->name = tempMemory;
- global->type = i32;
- global->mutable_ = false;
- global->module = ENV;
- global->base = tempMemory;
- getModule()->addGlobal(global.release());
- }
- }
-
- Expression* makeGetTempMemory() {
- return builder->makeGetGlobal(tempMemory, i32);
+ ABI::wasm2js::ensureScratchMemoryHelpers(getModule());
}
void lowerTruncFloatToInt(Unary *curr) {