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

#include "asmjs/shared-constants.h"
#include "ir/element-utils.h"
#include "ir/import-utils.h"
#include "ir/literal-utils.h"
#include "ir/module-splitting.h"
#include "ir/names.h"
#include "ir/utils.h"
#include "pass.h"
#include "shared-constants.h"
#include "support/file.h"
#include "support/string.h"
#include "wasm-builder.h"
#include "wasm.h"
#include <utility>

//
// Convert a module to be compatible with JavaScript promise integration (JSPI).
// Promising exports will be wrapped with a function that will handle storing
// the suspsender that is passed in as the first param from a "promising"
// `WebAssembly.Function`. Suspending imports will also be wrapped, but they
// will take the stored suspender and pass it as the first param to the imported
// function that should be created from a "suspending" `WebAssembly.Function`.
//
// By default all imports and exports will be wrapped, but this can be
// controlled with the following options:
//
//   --pass-arg=jspi-imports@module1.base1,module2.base2,module3.base3
//
//      Wrap each import in the comma-separated list. Wildcards and a separate
//      files are supported. See `asyncify-imports` for more details.
//
//   --pass-arg=jspi-exports@function_one,function_two,function_three
//
//      Wrap each export in the comma-separated list. Similar to jspi-imports,
//      wildcards and separate files are supported.
//
//   --pass-arg=jspi-split-module
//
//      Enables integration with wasm-split. A JSPI'ed function named
//      `__load_secondary_module` will be injected that is used by wasm-split to
//      load a secondary module.
//

namespace wasm {

static std::string getFullFunctionName(Name module, Name base) {
  return std::string(module.str) + '.' + base.toString();
}

static bool canChangeState(std::string name, String::Split stateChangers) {
  // When no state changers are given default to everything changes state.
  if (stateChangers.empty()) {
    return true;
  }
  for (auto& stateChanger : stateChangers) {
    if (String::wildcardMatch(stateChanger, name)) {
      return true;
    }
  }
  return false;
}

struct JSPI : public Pass {

  Type externref = Type(HeapType::ext, Nullable);

  void run(Module* module) override {
    Builder builder(*module);

    auto& options = getPassOptions();
    // Find which imports can suspend.
    auto stateChangingImports = String::trim(read_possible_response_file(
      options.getArgumentOrDefault("jspi-imports", "")));
    String::Split listedImports(stateChangingImports, ",");

    // Find which exports should create a promise.
    auto stateChangingExports = String::trim(read_possible_response_file(
      options.getArgumentOrDefault("jspi-exports", "")));
    String::Split listedExports(stateChangingExports, ",");

    bool wasmSplit = options.hasArgument("jspi-split-module");
    if (wasmSplit) {
      // Make an import for the load secondary module function so a JSPI wrapper
      // version will be created.
      auto import =
        Builder::makeFunction(ModuleSplitting::LOAD_SECONDARY_MODULE,
                              Signature(Type::none, Type::none),
                              {});
      import->module = ENV;
      import->base = ModuleSplitting::LOAD_SECONDARY_MODULE;
      module->addFunction(std::move(import));
      listedImports.push_back(
        ENV.toString() + "." +
        ModuleSplitting::LOAD_SECONDARY_MODULE.toString());
    }

    // Create a global to store the suspender that is passed into exported
    // functions and will then need to be passed out to the imported functions.
    Name suspender = Names::getValidGlobalName(*module, "suspender");
    module->addGlobal(builder.makeGlobal(suspender,
                                         externref,
                                         builder.makeRefNull(HeapType::noext),
                                         Builder::Mutable));

    // Keep track of already wrapped functions since they can be exported
    // multiple times, but only one wrapper is needed.
    std::unordered_map<Name, Name> wrappedExports;

    // Wrap each exported function in a function that stores the suspender
    // and calls the original export.
    for (auto& ex : module->exports) {
      if (ex->kind == ExternalKind::Function &&
          canChangeState(ex->name.toString(), listedExports)) {
        auto* func = module->getFunction(ex->value);
        Name wrapperName;
        auto iter = wrappedExports.find(func->name);
        if (iter == wrappedExports.end()) {
          wrapperName = makeWrapperForExport(func, module, suspender);
          wrappedExports[func->name] = wrapperName;
        } else {
          wrapperName = iter->second;
        }
        ex->value = wrapperName;
      }
    }

    // Replace any references to the original exports that are in the elements.
    for (auto& segment : module->elementSegments) {
      if (!segment->type.isFunction()) {
        continue;
      }
      for (Index i = 0; i < segment->data.size(); i++) {
        if (auto* get = segment->data[i]->dynCast<RefFunc>()) {
          auto iter = wrappedExports.find(get->func);
          if (iter == wrappedExports.end()) {
            continue;
          }
          auto* replacementRef = builder.makeRefFunc(
            iter->second, module->getFunction(iter->second)->type);
          segment->data[i] = replacementRef;
        }
      }
    }

    // Avoid iterator invalidation later.
    std::vector<Function*> originalFunctions;
    for (auto& func : module->functions) {
      originalFunctions.push_back(func.get());
    }
    // Wrap each imported function in a function that gets the global suspender
    // and passes it on to the imported function.
    for (auto* im : originalFunctions) {
      if (im->imported() &&
          canChangeState(getFullFunctionName(im->module, im->base),
                         listedImports)) {
        makeWrapperForImport(im, module, suspender, wasmSplit);
      }
    }
  }

private:
  Name makeWrapperForExport(Function* func, Module* module, Name suspender) {
    Name wrapperName = Names::getValidFunctionName(
      *module, std::string("export$") + func->name.toString());

    Builder builder(*module);

    auto* call = module->allocator.alloc<Call>();
    call->target = func->name;
    call->type = func->getResults();

    // Add an externref param as the first argument and copy all the original
    // params to new export.
    std::vector<Type> wrapperParams;
    std::vector<NameType> namedWrapperParams;
    wrapperParams.push_back(externref);
    namedWrapperParams.emplace_back(Names::getValidLocalName(*func, "susp"),
                                    externref);
    Index i = 0;
    for (const auto& param : func->getParams()) {
      call->operands.push_back(
        builder.makeLocalGet(wrapperParams.size(), param));
      wrapperParams.push_back(param);
      namedWrapperParams.emplace_back(func->getLocalNameOrGeneric(i), param);
      i++;
    }
    auto* block = builder.makeBlock();
    block->list.push_back(
      builder.makeGlobalSet(suspender, builder.makeLocalGet(0, externref)));
    block->list.push_back(call);
    Type resultsType = func->getResults();
    if (resultsType == Type::none) {
      // A void return is not currently allowed by v8. Add an i32 return value
      // that is ignored.
      // https://bugs.chromium.org/p/v8/issues/detail?id=13231
      resultsType = Type::i32;
      block->list.push_back(builder.makeConst(0));
    }
    block->finalize();
    auto wrapperFunc =
      Builder::makeFunction(wrapperName,
                            std::move(namedWrapperParams),
                            Signature(Type(wrapperParams), resultsType),
                            {},
                            block);
    return module->addFunction(std::move(wrapperFunc))->name;
  }

  void makeWrapperForImport(Function* im,
                            Module* module,
                            Name suspender,
                            bool wasmSplit) {
    Builder builder(*module);
    auto wrapperIm = std::make_unique<Function>();
    wrapperIm->name = Names::getValidFunctionName(
      *module, std::string("import$") + im->name.toString());
    wrapperIm->module = im->module;
    wrapperIm->base = im->base;
    auto stub = std::make_unique<Function>();
    stub->name = Name(im->name.str);
    stub->type = im->type;

    auto* call = module->allocator.alloc<Call>();
    call->target = wrapperIm->name;

    // Add an externref as the first argument to the imported function.
    std::vector<Type> params;
    params.push_back(externref);
    call->operands.push_back(builder.makeGlobalGet(suspender, externref));
    Index i = 0;
    for (const auto& param : im->getParams()) {
      call->operands.push_back(builder.makeLocalGet(i, param));
      params.push_back(param);
      ++i;
    }
    auto* block = builder.makeBlock();
    // Store the suspender so it can be restored after the call in case it is
    // modified by another entry into a Wasm export.
    auto supsenderCopyIndex = Builder::addVar(stub.get(), externref);
    // If there's a return value we need to store it so it can be returned
    // after restoring the suspender.
    std::optional<Index> returnIndex;
    if (stub->getResults().isConcrete()) {
      returnIndex = Builder::addVar(stub.get(), stub->getResults());
    }
    block->list.push_back(builder.makeLocalSet(
      supsenderCopyIndex, builder.makeGlobalGet(suspender, externref)));
    if (returnIndex) {
      block->list.push_back(builder.makeLocalSet(*returnIndex, call));
    } else {
      block->list.push_back(call);
    }
    // Restore the suspender.
    block->list.push_back(builder.makeGlobalSet(
      suspender, builder.makeLocalGet(supsenderCopyIndex, externref)));
    if (returnIndex) {
      block->list.push_back(
        builder.makeLocalGet(*returnIndex, stub->getResults()));
    }
    block->finalize();
    call->type = im->getResults();
    stub->body = block;
    wrapperIm->type = Signature(Type(params), call->type);

    if (wasmSplit && im->name == ModuleSplitting::LOAD_SECONDARY_MODULE) {
      // In non-debug builds the name of the JSPI wrapper function for loading
      // the secondary module will be removed. Create an export of it so that
      // wasm-split can find it.
      module->addExport(
        builder.makeExport(ModuleSplitting::LOAD_SECONDARY_MODULE,
                           ModuleSplitting::LOAD_SECONDARY_MODULE,
                           ExternalKind::Function));
    }
    module->removeFunction(im->name);
    module->addFunction(std::move(stub));
    module->addFunction(std::move(wrapperIm));
  }
};

Pass* createJSPIPass() { return new JSPI(); }

} // namespace wasm
