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

//
// Create `dynCall` helper functions used by emscripten.  These allow JavaScript
// to call back into WebAssembly given a function pointer (table index). These
// are used primarily to implement the `invoke` functions which in turn are used
// to implment exceptions handling and setjmp/longjmp.  Creates one for each
// signature in the indirect function table.
//

#include "abi/js.h"
#include "asm_v_wasm.h"
#include "ir/element-utils.h"
#include "ir/import-utils.h"
#include "pass.h"
#include "support/debug.h"
#include "support/insert_ordered.h"
#include "wasm-builder.h"

#define DEBUG_TYPE "generate-dyncalls"

namespace wasm {

struct GenerateDynCalls : public WalkerPass<PostWalker<GenerateDynCalls>> {
  GenerateDynCalls(bool onlyI64) : onlyI64(onlyI64) {}

  void doWalkModule(Module* wasm) {
    PostWalker<GenerateDynCalls>::doWalkModule(wasm);
    for (auto& type : invokeTypes) {
      generateDynCallThunk(type);
    }
  }

  void visitTable(Table* table) {
    // Generate dynCalls for functions in the table
    Module* wasm = getModule();
    auto& segments = wasm->elementSegments;

    // Find a single elem segment for the table. We only care about one, since
    // wasm-ld emits only one table with a single segment.
    auto it = std::find_if(segments.begin(),
                           segments.end(),
                           [&](std::unique_ptr<ElementSegment>& segment) {
                             return segment->table == table->name;
                           });
    if (it != segments.end()) {
      std::vector<Name> tableSegmentData;
      ElementUtils::iterElementSegmentFunctionNames(
        it->get(), [&](Name name, Index) {
          generateDynCallThunk(wasm->getFunction(name)->type);
        });
    }
  }

  void visitFunction(Function* func) {
    // Generate dynCalls for invokes
    if (func->imported() && func->module == ENV &&
        func->base.startsWith("invoke_")) {
      Signature sig = func->type.getSignature();
      // The first parameter is a pointer to the original function that's called
      // by the invoke, so skip it
      std::vector<Type> newParams(sig.params.begin() + 1, sig.params.end());
      invokeTypes.insert(Signature(Type(newParams), sig.results));
    }
  }

  void generateDynCallThunk(HeapType funcType);

  bool onlyI64;
  // The set of all invokes' signature types.
  InsertOrderedSet<HeapType> invokeTypes;
};

static bool hasI64(Signature sig) {
  // We only generate dynCall functions for signatures that contain i64. This is
  // because any other function can be called directly from JavaScript using the
  // wasm table.
  for (auto t : sig.results) {
    if (t.getID() == Type::i64) {
      return true;
    }
  }
  for (auto t : sig.params) {
    if (t.getID() == Type::i64) {
      return true;
    }
  }
  return false;
}

static void exportFunction(Module& wasm, Name name, bool must_export) {
  if (!wasm.getFunctionOrNull(name)) {
    assert(!must_export);
    return;
  }
  if (wasm.getExportOrNull(name)) {
    return; // Already exported
  }
  wasm.addExport(new Export(name, ExternalKind::Function, name));
}

void GenerateDynCalls::generateDynCallThunk(HeapType funcType) {
  Signature sig = funcType.getSignature();

  if (sig.results.isTuple()) {
    // Emscripten output is assumed to be MVP, and not to have multiple return
    // values. In particular, signatures in Emscripten all look like "abcd"
    // where "a" is the single return value, and "bcd" are the (in this case
    // three) parameters.
    Fatal() << "GenerateDynCalls: Cannot operate on multiple return values:"
            << sig.results;
  }

  if (onlyI64 && !hasI64(sig)) {
    return;
  }

  Module* wasm = getModule();
  Builder builder(*wasm);
  Name name = std::string("dynCall_") + getSig(sig.results, sig.params);
  if (wasm->getFunctionOrNull(name) || wasm->getExportOrNull(name)) {
    return; // module already contains this dyncall
  }
  std::vector<NameType> namedParams;
  std::vector<Type> params;
  if (wasm->tables.empty()) {
    // Add an imported table in exactly the same manner as the LLVM wasm backend
    // would add one.
    auto* table = wasm->addTable(Builder::makeTable(Name::fromInt(0)));
    table->module = ENV;
    table->base = "__indirect_function_table";
    table->addressType = wasm->memories[0]->addressType;
  }
  auto& table = wasm->tables[0];
  namedParams.emplace_back("fptr",
                           table->addressType); // function pointer param
  params.push_back(table->addressType);
  int p = 0;
  for (const auto& param : sig.params) {
    namedParams.emplace_back(std::to_string(p++), param);
    params.push_back(param);
  }
  auto f = builder.makeFunction(
    name, std::move(namedParams), Signature(Type(params), sig.results), {});
  f->hasExplicitName = true;
  Expression* fptr = builder.makeLocalGet(0, table->addressType);
  std::vector<Expression*> args;
  Index i = 0;
  for (const auto& param : sig.params) {
    args.push_back(builder.makeLocalGet(++i, param));
  }
  f->body = builder.makeCallIndirect(table->name, fptr, args, funcType);

  wasm->addFunction(std::move(f));
  exportFunction(*wasm, name, true);
}

Pass* createGenerateDynCallsPass() { return new GenerateDynCalls(false); }
Pass* createGenerateI64DynCallsPass() { return new GenerateDynCalls(true); }

} // namespace wasm
