summaryrefslogtreecommitdiff
path: root/src/passes/I64ToI32Lowering.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2019-04-18 09:33:40 -0700
committerGitHub <noreply@github.com>2019-04-18 09:33:40 -0700
commit77c44ecded323174d79a98bd43c3d2c064ac08e4 (patch)
tree2d31ace4491b200d30b8f7d335da103e0db6db7b /src/passes/I64ToI32Lowering.cpp
parent13dd8771d57161618acec8907f739bcdbdcf66cb (diff)
downloadbinaryen-77c44ecded323174d79a98bd43c3d2c064ac08e4.tar.gz
binaryen-77c44ecded323174d79a98bd43c3d2c064ac08e4.tar.bz2
binaryen-77c44ecded323174d79a98bd43c3d2c064ac08e4.zip
Wasm2js: support i64 globals (#2021)
Split them into two i32 globals.
Diffstat (limited to 'src/passes/I64ToI32Lowering.cpp')
-rw-r--r--src/passes/I64ToI32Lowering.cpp54
1 files changed, 43 insertions, 11 deletions
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index 42566c0e2..a1686d27d 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -36,9 +36,7 @@
namespace wasm {
static Name makeHighName(Name n) {
- return Name(
- cashew::IString((std::string(n.c_str()) + "$hi").c_str(), false)
- );
+ return std::string(n.c_str()) + "$hi";
}
struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
@@ -104,12 +102,27 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (!builder) builder = make_unique<Builder>(*module);
// add new globals for high bits
for (size_t i = 0, globals = module->globals.size(); i < globals; ++i) {
- auto& curr = module->globals[i];
+ auto* curr = module->globals[i].get();
if (curr->type != i64) continue;
+ originallyI64Globals.insert(curr->name);
curr->type = i32;
- auto* high = ModuleUtils::copyGlobal(curr.get(), *module);
- high->name = makeHighName(curr->name);
+ auto* high = builder->makeGlobal(makeHighName(curr->name), i32, builder->makeConst(Literal(int32_t(0))), Builder::Mutable);
module->addGlobal(high);
+ if (curr->imported()) {
+ Fatal() << "TODO: imported i64 globals";
+ } else {
+ if (auto* c = curr->init->dynCast<Const>()) {
+ uint64_t value = c->value.geti64();
+ c->value = Literal(uint32_t(value));
+ c->type = i32;
+ high->init = builder->makeConst(Literal(uint32_t(value >> 32)));
+ } else if (auto* get = curr->init->dynCast<GetGlobal>()) {
+ high->init = builder->makeGetGlobal(makeHighName(get->name), i32);
+ } else {
+ WASM_UNREACHABLE();
+ }
+ curr->init->type = i32;
+ }
}
// For functions that return 64-bit values, we use this global variable
@@ -425,7 +438,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
return;
}
TempVar highBits = fetchOutParam(curr->value);
- SetLocal* setHigh = builder->makeSetLocal(
+ auto* setHigh = builder->makeSetLocal(
mappedIndex + 1,
builder->makeGetLocal(highBits, i32)
);
@@ -434,13 +447,30 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
void visitGetGlobal(GetGlobal* curr) {
- if (curr->type != i64) return;
- assert(false && "GetGlobal not implemented");
+ if (!getFunction()) return; // if in a global init, skip - we already handled that.
+ if (!originallyI64Globals.count(curr->name)) return;
+ curr->type = i32;
+ TempVar highBits = getTemp();
+ SetLocal *setHighBits = builder->makeSetLocal(
+ highBits,
+ builder->makeGetGlobal(
+ makeHighName(curr->name),
+ i32
+ )
+ );
+ Block* result = builder->blockify(setHighBits, curr);
+ replaceCurrent(result);
+ setOutParam(result, std::move(highBits));
}
void visitSetGlobal(SetGlobal* curr) {
- if (curr->type != i64) return;
- assert(false && "SetGlobal not implemented");
+ if (!originallyI64Globals.count(curr->name)) return;
+ TempVar highBits = fetchOutParam(curr->value);
+ auto* setHigh = builder->makeSetGlobal(
+ makeHighName(curr->name),
+ builder->makeGetLocal(highBits, i32)
+ );
+ replaceCurrent(builder->makeSequence(curr, setHigh));
}
void visitLoad(Load* curr) {
@@ -526,6 +556,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
void visitConst(Const* curr) {
+ if (!getFunction()) return; // if in a global init, skip - we already handled that.
if (curr->type != i64) return;
TempVar highBits = getTemp();
Const* lowVal = builder->makeConst(
@@ -1606,6 +1637,7 @@ private:
std::unordered_map<Expression*, TempVar> highBitVars;
std::unordered_map<Name, TempVar> labelHighBitVars;
std::unordered_map<Index, Type> tempTypes;
+ std::unordered_set<Name> originallyI64Globals;
Index nextTemp;
TempVar getTemp(Type ty = i32) {