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

//
// Convert llvm's stack pointer usage from from global.get/global.set into
// cals to external stackSave/stackRestore.
// This is needed to emscripten SIDE_MODULE code where mutable global imports
// are not yet permitted by default.
//

#include "abi/js.h"
#include "ir/import-utils.h"
#include "pass.h"
#include "support/debug.h"
#include "wasm-emscripten.h"

#define DEBUG_TYPE "replace-stack-pointer"

namespace wasm {

static Name STACK_SAVE("stackSave");
static Name STACK_RESTORE("stackRestore");

struct ReplaceStackPointer
  : public WalkerPass<PostWalker<ReplaceStackPointer>> {
  void visitGlobalGet(GlobalGet* curr) {
    if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
      needStackSave = true;
      if (!builder) {
        builder = make_unique<Builder>(*getModule());
      }
      replaceCurrent(builder->makeCall(STACK_SAVE, {}, Type::i32));
    }
  }

  void visitGlobalSet(GlobalSet* curr) {
    if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
      needStackRestore = true;
      if (!builder) {
        builder = make_unique<Builder>(*getModule());
      }
      replaceCurrent(
        builder->makeCall(STACK_RESTORE, {curr->value}, Type::none));
    }
  }

  void doWalkModule(Module* module) {
    stackPointer = getStackPointerGlobal(*module);
    if (!stackPointer) {
      BYN_DEBUG(std::cerr << "no stack pointer found\n");
      return;
    }
    BYN_DEBUG(std::cerr << "stack pointer found\n");
    super::doWalkModule(module);
    if (needStackSave) {
      ensureFunctionImport(
        module, STACK_SAVE, Signature(Type::none, Type::i32));
    }
    if (needStackRestore) {
      ensureFunctionImport(
        module, STACK_RESTORE, Signature(Type::i32, Type::none));
    }
    // Finally remove the stack pointer global itself. This avoids importing
    // a mutable global.
    module->removeGlobal(stackPointer->name);
  }

  void ensureFunctionImport(Module* module, Name name, Signature sig) {
    ImportInfo info(*module);
    if (info.getImportedFunction(ENV, name)) {
      return;
    }
    auto import = new Function;
    import->name = name;
    import->module = ENV;
    import->base = name;
    import->sig = sig;
    module->addFunction(import);
  }

private:
  std::unique_ptr<Builder> builder;
  Global* stackPointer = nullptr;
  bool needStackSave = false;
  bool needStackRestore = false;
};

Pass* createReplaceStackPointerPass() { return new ReplaceStackPointer; }

} // namespace wasm
