/*
 * 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 implement 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.getHeapType());
        });
    }
  }

  void visitFunction(Function* func) {
    // Generate dynCalls for invokes
    if (func->imported() && func->module == ENV &&
        func->base.startsWith("invoke_")) {
      Signature sig = func->type.getHeapType().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),
    Type(Signature(Type(params), sig.results), NonNullable, Exact),
    {},
    nullptr);
  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
