/*
 * 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);

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

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

    bool wasmSplit = 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,
        Type(Signature(Type::none, Type::none), NonNullable, Inexact),
        {});
      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* name = ex->getInternalName();
        auto* func = module->getFunction(*name);
        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;
        }
        *name = 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);
          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),
      Type(Signature(Type(wrapperParams), resultsType), NonNullable, Exact),
      {},
      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.with(Exact);

    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 =
      Type(Signature(Type(params), call->type), NonNullable, Inexact);

    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
