diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/passes/Memory64Lowering.cpp | 87 | ||||
-rw-r--r-- | src/passes/pass.cpp | 4 | ||||
-rw-r--r-- | src/passes/passes.h | 1 |
4 files changed, 93 insertions, 0 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index 12914e590..d352e841b 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -39,6 +39,7 @@ set(passes_SOURCES LocalCSE.cpp LogExecution.cpp LoopInvariantCodeMotion.cpp + Memory64Lowering.cpp MemoryPacking.cpp MergeBlocks.cpp MergeLocals.cpp diff --git a/src/passes/Memory64Lowering.cpp b/src/passes/Memory64Lowering.cpp new file mode 100644 index 000000000..7905c944f --- /dev/null +++ b/src/passes/Memory64Lowering.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2020 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Lowers a module with loads and stores that access a 64-bit memory with +// one that works as-is on wasm32. +// +// TODO(wvo): make this run in parallel if needed. + +#include "ir/bits.h" +#include "pass.h" +#include "wasm-builder.h" +#include "wasm.h" + +namespace wasm { + +struct Memory64Lowering : public WalkerPass<PostWalker<Memory64Lowering>> { + + void run(PassRunner* runner, Module* module) override { + if (module->memory.is64()) { + super::run(runner, module); + } + } + + void WrapAddress64(Expression*& ptr) { + if (ptr->type == Type::unreachable) { + return; + } + auto& module = *getModule(); + assert(module.memory.is64()); + assert(ptr->type == Type::i64); + Builder builder(module); + ptr = builder.makeUnary(UnaryOp::WrapInt64, ptr); + } + + void visitLoad(Load* curr) { WrapAddress64(curr->ptr); } + + void visitStore(Store* curr) { WrapAddress64(curr->ptr); } + + void visitMemorySize(MemorySize* curr) { + auto size = static_cast<Expression*>(curr); + WrapAddress64(size); + replaceCurrent(size); + } + + void visitMemoryGrow(MemoryGrow* curr) { + WrapAddress64(curr->delta); + auto size = static_cast<Expression*>(curr); + WrapAddress64(size); + replaceCurrent(size); + } + + void visitMemoryInit(MemoryInit* curr) { WrapAddress64(curr->dest); } + + void visitMemoryFill(MemoryFill* curr) { + WrapAddress64(curr->dest); + WrapAddress64(curr->size); + } + + void visitMemoryCopy(MemoryCopy* curr) { + WrapAddress64(curr->dest); + WrapAddress64(curr->source); + WrapAddress64(curr->size); + } + + void visitMemory(Memory* memory) { + // This is visited last. + memory->indexType = Type::i32; + } +}; + +Pass* createMemory64LoweringPass() { return new Memory64Lowering(); } + +} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index b653269bf..d115b4533 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -190,6 +190,10 @@ void PassRegistry::registerPasses() { registerPass("limit-segments", "attempt to merge segments to fit within web limits", createLimitSegmentsPass); + registerPass("memory64-lowering", + "lower loads and stores to a 64-bit memory to instead use a " + "32-bit one", + createMemory64LoweringPass); registerPass("memory-packing", "packs memory into separate segments, skipping zeros", createMemoryPackingPass); diff --git a/src/passes/passes.h b/src/passes/passes.h index 53a7d3aa2..434b6e382 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -63,6 +63,7 @@ Pass* createLogExecutionPass(); Pass* createInstrumentLocalsPass(); Pass* createInstrumentMemoryPass(); Pass* createLoopInvariantCodeMotionPass(); +Pass* createMemory64LoweringPass(); Pass* createMemoryPackingPass(); Pass* createMergeBlocksPass(); Pass* createMergeLocalsPass(); |