/*
 * Copyright 2022 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.
 */

//
// Condensing a module with multiple memories into a module with a single memory
// for browsers that don’t support multiple memories.
//
// This pass also disables multimemory so that the target features section in
// the emitted module does not report the use of MultiMemories. Disabling the
// multimemory feature also prevents later passes from adding additional
// memories.
//
// The offset computation in function maybeMakeBoundsCheck is not precise
// according to the spec. In the spec offsets do not overflow as
// twos-complement, but i32.add does. Concretely, a load from address 1000 with
// offset 0xffffffff should actually trap, as the combined number is greater
// than 32 bits. But with an add, 1000 + 0xffffffff = 999 due to overflow, which
// would not trap. In theory we could compute like the spec, by expanding the
// i32s to i64s and adding there (where we won't overflow), but we don't have
// i128s to handle i64 overflow.
//
// The Atomic instructions memory.atomic.wait and memory.atomic.notify, have
// browser engine implementations that predate the still-in-progress threads
// spec (https://github.com/WebAssembly/threads). And whether or not
// atomic.notify should trap for out-of-bounds addresses remains an open issue
// (https://github.com/WebAssembly/threads/issues/105). For now, we are using
// the same semantics as v8, which is to bounds check all Atomic instructions
// the same way and trap for out-of-bounds.

#include "ir/abstract.h"
#include "ir/module-utils.h"
#include "ir/names.h"
#include "wasm-builder.h"
#include <pass.h>
#include <wasm.h>

namespace wasm {

struct MultiMemoryLowering : public Pass {
  Module* wasm = nullptr;
  // The name of the single memory that exists after this pass is run
  Name combinedMemory;
  // The type of the single memory
  Type pointerType;
  // Used to indicate the type of the single memory when creating instructions
  // (memory.grow, memory.size) for that memory
  Builder::MemoryInfo memoryInfo;
  // If the combined memory is shared
  bool isShared;
  // If the combined memory is imported
  bool isImported;
  // If the combined memory is exported
  bool isExported = false;
  // If the combined memory should be imported, the following two
  // properties will be set
  Name module;
  Name base;
  // The initial page size of the combined memory
  Address totalInitialPages;
  // The max page size of the combined memory
  Address totalMaxPages;
  // There is no offset for the first memory, so offsetGlobalNames will always
  // have a size that is one less than the count of memories at the time this
  // pass is run. Use helper getOffsetGlobal(Index) to index the vector
  // conveniently without having to manipulate the index directly
  std::vector<Name> offsetGlobalNames;
  // Maps from the name of the memory to its index as seen in the
  // module->memories vector
  std::unordered_map<Name, Index> memoryIdxMap;
  // A vector of the memory size function names that were created proactively
  // for each memory
  std::vector<Name> memorySizeNames;
  // A vector of the memory grow functions that were created proactively for
  // each memory
  std::vector<Name> memoryGrowNames;

  bool checkBounds = false;

  MultiMemoryLowering(bool checkBounds) : checkBounds(checkBounds) {}

  struct Replacer : public WalkerPass<PostWalker<Replacer>> {
    MultiMemoryLowering& parent;
    Builder builder;
    Replacer(MultiMemoryLowering& parent, Module& wasm)
      : parent(parent), builder(wasm) {}
    // Avoid visiting the custom functions added by the parent pass
    // MultiMemoryLowering
    void walkFunction(Function* func) {
      for (Name funcName : parent.memorySizeNames) {
        if (funcName == func->name) {
          return;
        }
      }
      for (Name funcName : parent.memoryGrowNames) {
        if (funcName == func->name) {
          return;
        }
      }
      Super::walkFunction(func);
    }

    void visitMemoryGrow(MemoryGrow* curr) {
      auto idx = parent.memoryIdxMap.at(curr->memory);
      Name funcName = parent.memoryGrowNames[idx];
      replaceCurrent(builder.makeCall(funcName, {curr->delta}, curr->type));
    }

    void visitMemorySize(MemorySize* curr) {
      auto idx = parent.memoryIdxMap.at(curr->memory);
      Name funcName = parent.memorySizeNames[idx];
      replaceCurrent(builder.makeCall(funcName, {}, curr->type));
    }

    Expression* addOffsetGlobal(Expression* toExpr, Name memory) {
      auto memoryIdx = parent.memoryIdxMap.at(memory);
      auto offsetGlobal = parent.getOffsetGlobal(memoryIdx);
      Expression* returnExpr;
      if (offsetGlobal) {
        returnExpr = builder.makeBinary(
          Abstract::getBinary(parent.pointerType, Abstract::Add),
          builder.makeGlobalGet(offsetGlobal, parent.pointerType),
          toExpr);
      } else {
        returnExpr = toExpr;
      }
      return returnExpr;
    }

    Expression* makeAddGtuTrap(Expression* leftOperand,
                               Expression* rightOperand,
                               Expression* limit) {
      Expression* gtuTrap = builder.makeIf(
        builder.makeBinary(
          Abstract::getBinary(parent.pointerType, Abstract::GtU),
          builder.makeBinary(
            Abstract::getBinary(parent.pointerType, Abstract::Add),
            leftOperand,
            rightOperand),
          limit),
        builder.makeUnreachable());
      return gtuTrap;
    }

    Expression* makeAddGtuMemoryTrap(Expression* leftOperand,
                                     Expression* rightOperand,
                                     Name memory) {
      auto memoryIdx = parent.memoryIdxMap.at(memory);
      Name memorySizeFunc = parent.memorySizeNames[memoryIdx];
      Expression* gtuMemoryTrap = makeAddGtuTrap(
        leftOperand,
        rightOperand,
        builder.makeCall(memorySizeFunc, {}, parent.pointerType));
      return gtuMemoryTrap;
    }

    template<typename T>
    Expression* makePtrBoundsCheck(T* curr, Index ptrIdx, Index bytes) {
      Expression* boundsCheck = makeAddGtuMemoryTrap(
        builder.makeBinary(
          // ptr + offset (ea from wasm spec) + bit width
          Abstract::getBinary(parent.pointerType, Abstract::Add),
          builder.makeLocalGet(ptrIdx, parent.pointerType),
          builder.makeConstPtr(curr->offset, parent.pointerType)),
        builder.makeConstPtr(bytes, parent.pointerType),
        curr->memory);
      return boundsCheck;
    }

    Expression* makeDataSegmentBoundsCheck(MemoryInit* curr,
                                           Index sizeIdx,
                                           Index offsetIdx) {
      auto* segment = parent.wasm->getDataSegment(curr->segment);
      Expression* addGtuTrap = makeAddGtuTrap(
        builder.makeLocalGet(offsetIdx, parent.pointerType),
        builder.makeLocalGet(sizeIdx, parent.pointerType),
        builder.makeConstPtr(segment->data.size(), parent.pointerType));
      return addGtuTrap;
    }

    template<typename T> Expression* getPtr(T* curr, Index bytes) {
      Expression* ptrValue = addOffsetGlobal(curr->ptr, curr->memory);
      if (parent.checkBounds) {
        Index ptrIdx = Builder::addVar(getFunction(), parent.pointerType);
        Expression* ptrSet = builder.makeLocalSet(ptrIdx, ptrValue);
        Expression* boundsCheck = makePtrBoundsCheck(curr, ptrIdx, bytes);
        Expression* ptrGet = builder.makeLocalGet(ptrIdx, parent.pointerType);
        return builder.makeBlock({ptrSet, boundsCheck, ptrGet});
      }

      return ptrValue;
    }

    template<typename T>
    Expression* getDest(T* curr,
                        Name memory,
                        Index sizeIdx = Index(-1),
                        Expression* localSet = nullptr,
                        Expression* additionalCheck = nullptr) {
      Expression* destValue = addOffsetGlobal(curr->dest, memory);

      if (parent.checkBounds) {
        Expression* sizeSet = builder.makeLocalSet(sizeIdx, curr->size);
        Index destIdx = Builder::addVar(getFunction(), parent.pointerType);
        Expression* destSet = builder.makeLocalSet(destIdx, destValue);
        Expression* boundsCheck = makeAddGtuMemoryTrap(
          builder.makeLocalGet(destIdx, parent.pointerType),
          builder.makeLocalGet(sizeIdx, parent.pointerType),
          memory);
        std::vector<Expression*> exprs = {
          destSet, localSet, sizeSet, boundsCheck};
        if (additionalCheck) {
          exprs.push_back(additionalCheck);
        }
        Expression* destGet = builder.makeLocalGet(destIdx, parent.pointerType);
        exprs.push_back(destGet);
        return builder.makeBlock(exprs);
      }

      return destValue;
    }

    Expression* getSource(MemoryCopy* curr,
                          Index sizeIdx = Index(-1),
                          Index sourceIdx = Index(-1)) {
      Expression* sourceValue =
        addOffsetGlobal(curr->source, curr->sourceMemory);

      if (parent.checkBounds) {
        Expression* boundsCheck = makeAddGtuMemoryTrap(
          builder.makeLocalGet(sourceIdx, parent.pointerType),
          builder.makeLocalGet(sizeIdx, parent.pointerType),
          curr->sourceMemory);
        Expression* sourceGet =
          builder.makeLocalGet(sourceIdx, parent.pointerType);
        std::vector<Expression*> exprs = {boundsCheck, sourceGet};
        return builder.makeBlock(exprs);
      }

      return sourceValue;
    }

    void visitMemoryInit(MemoryInit* curr) {
      if (parent.checkBounds) {
        Index offsetIdx = Builder::addVar(getFunction(), parent.pointerType);
        Index sizeIdx = Builder::addVar(getFunction(), parent.pointerType);
        curr->dest =
          getDest(curr,
                  curr->memory,
                  sizeIdx,
                  builder.makeLocalSet(offsetIdx, curr->offset),
                  makeDataSegmentBoundsCheck(curr, sizeIdx, offsetIdx));
        curr->offset = builder.makeLocalGet(offsetIdx, parent.pointerType);
        curr->size = builder.makeLocalGet(sizeIdx, parent.pointerType);
      } else {
        curr->dest = getDest(curr, curr->memory);
      }
      setMemory(curr);
    }

    void visitMemoryCopy(MemoryCopy* curr) {
      if (parent.checkBounds) {
        Index sourceIdx = Builder::addVar(getFunction(), parent.pointerType);
        Index sizeIdx = Builder::addVar(getFunction(), parent.pointerType);
        curr->dest = getDest(curr,
                             curr->destMemory,
                             sizeIdx,
                             builder.makeLocalSet(sourceIdx, curr->source));
        curr->source = getSource(curr, sizeIdx, sourceIdx);
        curr->size = builder.makeLocalGet(sizeIdx, parent.pointerType);
      } else {
        curr->dest = getDest(curr, curr->destMemory);
        curr->source = getSource(curr);
      }
      curr->destMemory = parent.combinedMemory;
      curr->sourceMemory = parent.combinedMemory;
    }

    void visitMemoryFill(MemoryFill* curr) {
      if (parent.checkBounds) {
        Index valueIdx = Builder::addVar(getFunction(), parent.pointerType);
        Index sizeIdx = Builder::addVar(getFunction(), parent.pointerType);
        curr->dest = getDest(curr,
                             curr->memory,
                             sizeIdx,
                             builder.makeLocalSet(valueIdx, curr->value));
        curr->value = builder.makeLocalGet(valueIdx, parent.pointerType);
        curr->size = builder.makeLocalGet(sizeIdx, parent.pointerType);
      } else {
        curr->dest = getDest(curr, curr->memory);
      }
      setMemory(curr);
    }

    template<typename T> void setMemory(T* curr) {
      curr->memory = parent.combinedMemory;
    }

    void visitLoad(Load* curr) {
      curr->ptr = getPtr(curr, curr->bytes);
      setMemory(curr);
    }

    void visitStore(Store* curr) {
      curr->ptr = getPtr(curr, curr->bytes);
      setMemory(curr);
    }

    void visitSIMDLoad(SIMDLoad* curr) {
      curr->ptr = getPtr(curr, curr->getMemBytes());
      setMemory(curr);
    }

    void visitSIMDLoadSplat(SIMDLoad* curr) {
      curr->ptr = getPtr(curr, curr->getMemBytes());
      setMemory(curr);
    }

    void visitSIMDLoadExtend(SIMDLoad* curr) {
      curr->ptr = getPtr(curr, curr->getMemBytes());
      setMemory(curr);
    }

    void visitSIMDLoadZero(SIMDLoad* curr) {
      curr->ptr = getPtr(curr, curr->getMemBytes());
      setMemory(curr);
    }

    void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
      curr->ptr = getPtr(curr, curr->getMemBytes());
      setMemory(curr);
    }

    void visitAtomicRMW(AtomicRMW* curr) {
      curr->ptr = getPtr(curr, curr->bytes);
      setMemory(curr);
    }

    void visitAtomicCmpxchg(AtomicCmpxchg* curr) {
      curr->ptr = getPtr(curr, curr->bytes);
      setMemory(curr);
    }

    void visitAtomicWait(AtomicWait* curr) {
      Index bytes;
      switch (curr->expectedType.getBasic()) {
        case Type::i32: {
          bytes = 4;
          break;
        }
        case Type::i64: {
          bytes = 8;
          break;
        }
        default:
          WASM_UNREACHABLE("unexpected type");
      }
      curr->ptr = getPtr(curr, bytes);
      setMemory(curr);
    }

    void visitAtomicNotify(AtomicNotify* curr) {
      curr->ptr = getPtr(curr, Index(4));
      setMemory(curr);
    }
  };

  void run(Module* module) override {
    module->features.disable(FeatureSet::MultiMemory);

    // If there are no memories or 1 memory, skip this pass
    if (module->memories.size() <= 1) {
      return;
    }

    this->wasm = module;

    prepCombinedMemory();
    makeOffsetGlobals();
    adjustActiveDataSegmentOffsets();
    createMemorySizeFunctions();
    createMemoryGrowFunctions();
    removeExistingMemories();
    addCombinedMemory();
    if (isExported) {
      updateMemoryExports();
    }

    Replacer(*this, *wasm).run(getPassRunner(), wasm);
  }

  // Returns the global name for the given idx. There is no global for the first
  // idx, so an empty name is returned
  Name getOffsetGlobal(Index idx) {
    // There is no offset global for the first memory
    if (idx == 0) {
      return Name();
    }

    // Since there is no offset global for the first memory, we need to
    // subtract one when indexing into the offsetGlobalName vector
    return offsetGlobalNames[idx - 1];
  }

  size_t getInitialOffset(Index idx) {
    if (idx == 0) {
      return 0;
    }
    auto* g = wasm->getGlobal(getOffsetGlobal(idx));
    return g->init->cast<Const>()->value.getUnsigned();
  }

  // Whether the idx represents the last memory. Since there is no offset global
  // for the first memory, the last memory is represented by the size of
  // offsetGlobalNames
  bool isLastMemory(Index idx) { return idx == offsetGlobalNames.size(); }

  Memory& getFirstMemory() { return *wasm->memories[0]; }

  void prepCombinedMemory() {
    pointerType = getFirstMemory().addressType;
    memoryInfo = pointerType == Type::i32 ? Builder::MemoryInfo::Memory32
                                          : Builder::MemoryInfo::Memory64;
    isShared = getFirstMemory().shared;
    isImported = getFirstMemory().imported();
    for (auto& memory : wasm->memories) {
      // We are assuming that each memory is configured the same as the first
      // and assert if any of the memories does not match this configuration
      assert(memory->shared == isShared);
      assert(memory->addressType == pointerType);

      // TODO: handle memory import for memories other than the first
      if (memory->name != getFirstMemory().name && memory->imported()) {
        Fatal() << "MultiMemoryLowering: only the first memory can be imported";
      }

      // Calculating the total initial and max page size for the combined memory
      // by totaling the initial and max page sizes for the memories in the
      // module
      totalInitialPages = totalInitialPages + memory->initial;
      if (memory->hasMax()) {
        totalMaxPages = totalMaxPages + memory->max;
      }
    }
    // Ensuring valid initial and max page sizes that do not exceed the number
    // of pages addressable by the pointerType
    Address maxSize =
      pointerType == Type::i32 ? Memory::kMaxSize32 : Memory::kMaxSize64;
    if (totalMaxPages > maxSize || totalMaxPages == 0) {
      totalMaxPages = Memory::kUnlimitedSize;
    }
    if (totalInitialPages > totalMaxPages) {
      totalInitialPages = totalMaxPages;
    }

    // Save the module and base to set on the combinedMemory
    if (isImported) {
      module = getFirstMemory().module;
      base = getFirstMemory().base;
    }
    // Ensuring only the first memory is an exported memory
    for (auto& exp : wasm->exports) {
      if (exp->kind == ExternalKind::Memory &&
          *exp->getInternalName() == getFirstMemory().name) {
        isExported = true;
      } else if (exp->kind == ExternalKind::Memory) {
        Fatal() << "MultiMemoryLowering: only the first memory can be exported";
      }
    }
    // Creating the combined memory name so we can reference the combined memory
    // in subsequent instructions before it is added to the module
    combinedMemory = Names::getValidMemoryName(*wasm, "combined_memory");
  }

  void makeOffsetGlobals() {
    auto addGlobal = [&](Name name, size_t offset) {
      auto global = Builder::makeGlobal(
        name,
        pointerType,
        Builder(*wasm).makeConst(Literal::makeFromInt64(offset, pointerType)),
        Builder::Mutable);
      wasm->addGlobal(std::move(global));
    };

    size_t offsetRunningTotal = 0;
    for (Index i = 0; i < wasm->memories.size(); i++) {
      auto& memory = wasm->memories[i];
      memoryIdxMap[memory->name] = i;
      // We don't need a page offset global for the first memory as it's always
      // 0
      if (i != 0) {
        Name name = Names::getValidGlobalName(
          *wasm, memory->name.toString() + "_byte_offset");
        offsetGlobalNames.push_back(std::move(name));
        addGlobal(name, offsetRunningTotal * Memory::kPageSize);
      }
      offsetRunningTotal += memory->initial;
    }
  }

  // TODO: Add a trap for segments that have a non-constant offset that would
  // have been out of bounds at runtime but is in bounds after multi-memory
  // lowering
  void adjustActiveDataSegmentOffsets() {
    Builder builder(*wasm);
    ModuleUtils::iterActiveDataSegments(*wasm, [&](DataSegment* dataSegment) {
      auto idx = memoryIdxMap.at(dataSegment->memory);
      dataSegment->memory = combinedMemory;
      auto* offset = dataSegment->offset->dynCast<Const>();
      assert(offset && "TODO: handle non-const segment offsets");
      size_t originalOffset = offset->value.getUnsigned();
      auto memOffset = getInitialOffset(idx);
      offset->value = Literal(int32_t(originalOffset + memOffset));
    });
  }

  void createMemorySizeFunctions() {
    for (Index i = 0; i < wasm->memories.size(); i++) {
      auto function = memorySize(i, wasm->memories[i]->name);
      memorySizeNames.push_back(function->name);
      wasm->addFunction(std::move(function));
    }
  }

  void createMemoryGrowFunctions() {
    for (Index i = 0; i < wasm->memories.size(); i++) {
      auto function = memoryGrow(i, wasm->memories[i]->name);
      memoryGrowNames.push_back(function->name);
      wasm->addFunction(std::move(function));
    }
  }

  // This function replaces memory.grow instruction calls in the wasm module.
  // Because the multiple discrete memories are lowered into a single memory,
  // we need to adjust offsets as a particular memory receives an
  // instruction to grow.
  std::unique_ptr<Function> memoryGrow(Index memIdx, Name memoryName) {
    Builder builder(*wasm);
    Name name = memoryName.toString() + "_grow";
    Name functionName = Names::getValidFunctionName(*wasm, name);
    auto function = Builder::makeFunction(
      functionName, Signature(pointerType, pointerType), {});
    function->setLocalName(0, "page_delta");
    auto pageSizeConst = [&]() {
      return builder.makeConst(Literal(Memory::kPageSize));
    };
    auto getOffsetDelta = [&]() {
      return builder.makeBinary(Abstract::getBinary(pointerType, Abstract::Mul),
                                builder.makeLocalGet(0, pointerType),
                                pageSizeConst());
    };
    auto getMoveSource = [&](Name global) {
      return builder.makeGlobalGet(global, pointerType);
    };
    Expression* functionBody;
    Index sizeLocal = -1;

    Index returnLocal =
      Builder::addVar(function.get(), "return_size", pointerType);
    functionBody = builder.blockify(builder.makeLocalSet(
      returnLocal, builder.makeCall(memorySizeNames[memIdx], {}, pointerType)));

    if (!isLastMemory(memIdx)) {
      sizeLocal = Builder::addVar(function.get(), "memory_size", pointerType);
      functionBody = builder.blockify(
        functionBody,
        builder.makeLocalSet(
          sizeLocal, builder.makeMemorySize(combinedMemory, memoryInfo)));
    }

    // Attempt to grow the combinedMemory. If -1 returns, enough memory could
    // not be allocated, so return -1.
    functionBody = builder.blockify(
      functionBody,
      builder.makeIf(
        builder.makeBinary(
          EqInt32,
          builder.makeMemoryGrow(
            builder.makeLocalGet(0, pointerType), combinedMemory, memoryInfo),
          builder.makeConst(-1)),
        builder.makeReturn(builder.makeConst(-1))));

    // If we are not growing the last memory, then we need to copy data,
    // shifting it over to accomodate the increase from page_delta
    if (!isLastMemory(memIdx)) {
      // This offset is the starting pt for copying
      auto offsetGlobalName = getOffsetGlobal(memIdx + 1);
      functionBody = builder.blockify(
        functionBody,
        builder.makeMemoryCopy(
          // destination
          builder.makeBinary(Abstract::getBinary(pointerType, Abstract::Add),
                             getMoveSource(offsetGlobalName),
                             getOffsetDelta()),
          // source
          getMoveSource(offsetGlobalName),
          // size
          builder.makeBinary(
            Abstract::getBinary(pointerType, Abstract::Sub),
            builder.makeBinary(Abstract::getBinary(pointerType, Abstract::Mul),
                               builder.makeLocalGet(sizeLocal, pointerType),
                               pageSizeConst()),
            getMoveSource(offsetGlobalName)),
          combinedMemory,
          combinedMemory));
    }

    // Adjust the offsets of the globals impacted by the memory.grow call
    for (Index i = memIdx; i < offsetGlobalNames.size(); i++) {
      auto& offsetGlobalName = offsetGlobalNames[i];
      functionBody = builder.blockify(
        functionBody,
        builder.makeGlobalSet(
          offsetGlobalName,
          builder.makeBinary(Abstract::getBinary(pointerType, Abstract::Add),
                             getMoveSource(offsetGlobalName),
                             getOffsetDelta())));
    }

    functionBody = builder.blockify(
      functionBody, builder.makeLocalGet(returnLocal, pointerType));

    function->body = functionBody;
    return function;
  }

  // This function replaces memory.size instructions with a function that can
  // return the size of each memory as if each was discrete and separate.
  std::unique_ptr<Function> memorySize(Index memIdx, Name memoryName) {
    Builder builder(*wasm);
    Name name = memoryName.toString() + "_size";
    Name functionName = Names::getValidFunctionName(*wasm, name);
    auto function = Builder::makeFunction(
      functionName, Signature(Type::none, pointerType), {});
    Expression* functionBody;
    auto pageSizeConst = [&]() {
      return builder.makeConst(Literal(Memory::kPageSize));
    };
    auto getOffsetInPageUnits = [&](Name global) {
      return builder.makeBinary(
        Abstract::getBinary(pointerType, Abstract::DivU),
        builder.makeGlobalGet(global, pointerType),
        pageSizeConst());
    };

    // offsetGlobalNames does not keep track of a global for the offset of
    // wasm->memories[0] because it's always 0. As a result, the below
    // calculations that involve offsetGlobalNames are intrinsically "offset".
    // Thus, offsetGlobalNames[0] is the offset for wasm->memories[1] and
    // the size of wasm->memories[0].
    if (memIdx == 0) {
      auto offsetGlobalName = getOffsetGlobal(1);
      functionBody = builder.blockify(
        builder.makeReturn(getOffsetInPageUnits(offsetGlobalName)));
    } else if (isLastMemory(memIdx)) {
      auto offsetGlobalName = getOffsetGlobal(memIdx);
      functionBody = builder.blockify(builder.makeReturn(
        builder.makeBinary(Abstract::getBinary(pointerType, Abstract::Sub),
                           builder.makeMemorySize(combinedMemory, memoryInfo),
                           getOffsetInPageUnits(offsetGlobalName))));
    } else {
      auto offsetGlobalName = getOffsetGlobal(memIdx);
      auto nextOffsetGlobalName = getOffsetGlobal(memIdx + 1);
      functionBody = builder.blockify(builder.makeReturn(
        builder.makeBinary(Abstract::getBinary(pointerType, Abstract::Sub),
                           getOffsetInPageUnits(nextOffsetGlobalName),
                           getOffsetInPageUnits(offsetGlobalName))));
    }

    function->body = functionBody;
    return function;
  }

  void removeExistingMemories() {
    wasm->removeMemories([&](Memory* curr) { return true; });
  }

  void addCombinedMemory() {
    auto memory = Builder::makeMemory(combinedMemory);
    memory->shared = isShared;
    memory->addressType = pointerType;
    memory->initial = totalInitialPages;
    memory->max = totalMaxPages;
    if (isImported) {
      memory->base = base;
      memory->module = module;
    }
    wasm->addMemory(std::move(memory));
  }

  void updateMemoryExports() {
    for (auto& exp : wasm->exports) {
      if (exp->kind == ExternalKind::Memory) {
        // We checked in prepCombinedMemory that any memory exports are for
        // the first memory, so setting the exports to the combinedMemory means
        // calling JS will not have to worry about offsets
        *exp->getInternalName() = combinedMemory;
      }
    }
  }
};

Pass* createMultiMemoryLoweringPass() { return new MultiMemoryLowering(false); }

Pass* createMultiMemoryLoweringWithBoundsChecksPass() {
  return new MultiMemoryLowering(true);
}

} // namespace wasm
