diff options
author | Alon Zakai <alonzakai@gmail.com> | 2019-04-18 09:33:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-18 09:33:40 -0700 |
commit | 77c44ecded323174d79a98bd43c3d2c064ac08e4 (patch) | |
tree | 2d31ace4491b200d30b8f7d335da103e0db6db7b /src/passes/I64ToI32Lowering.cpp | |
parent | 13dd8771d57161618acec8907f739bcdbdcf66cb (diff) | |
download | binaryen-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.cpp | 54 |
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) { |