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

//
// Instruments all indirect calls so that they work even if a function
// pointer was cast incorrectly. For example, if you cast an int (int, float)
// to an int (int, float, int) and call it natively, on most archs it will
// happen to work, ignoring the extra param, whereas in wasm it will trap.
// When porting code that relies on such casts working (like e.g. Python),
// this pass may be useful. It sets a new "ABI" for indirect calls, in which
// they all return an i64 and they have a fixed number of i64 params, and
// the pass converts everything to go through that.
//
// This should work even with dynamic linking, however, the number of
// params must be identical, i.e., the "ABI" must match.

#include <asm_v_wasm.h>
#include <ir/literal-utils.h>
#include <pass.h>
#include <wasm-builder.h>
#include <wasm-emscripten.h>
#include <wasm.h>

namespace wasm {

// This should be enough for everybody. (As described above, we need this
// to match when dynamically linking, and also dynamic linking is why we
// can't just detect this automatically in the module we see.)
static const int NUM_PARAMS = 16;

// Converts a value to the ABI type of i64.
static Expression* toABI(Expression* value, Module* module) {
  Builder builder(*module);
  switch (value->type) {
    case i32: {
      value = builder.makeUnary(ExtendUInt32, value);
      break;
    }
    case i64: {
      // already good
      break;
    }
    case f32: {
      value = builder.makeUnary(ExtendUInt32,
                                builder.makeUnary(ReinterpretFloat32, value));
      break;
    }
    case f64: {
      value = builder.makeUnary(ReinterpretFloat64, value);
      break;
    }
    case v128: {
      assert(false && "v128 not implemented yet");
      WASM_UNREACHABLE();
    }
    case none: {
      // the value is none, but we need a value here
      value = builder.makeSequence(value, LiteralUtils::makeZero(i64, *module));
      break;
    }
    case unreachable: {
      // can leave it, the call isn't taken anyhow
      break;
    }
  }
  return value;
}

// Converts a value from the ABI type of i64 to the expected type
static Expression* fromABI(Expression* value, Type type, Module* module) {
  Builder builder(*module);
  switch (type) {
    case i32: {
      value = builder.makeUnary(WrapInt64, value);
      break;
    }
    case i64: {
      // already good
      break;
    }
    case f32: {
      value = builder.makeUnary(ReinterpretInt32,
                                builder.makeUnary(WrapInt64, value));
      break;
    }
    case f64: {
      value = builder.makeUnary(ReinterpretInt64, value);
      break;
    }
    case v128: {
      assert(false && "v128 not implemented yet");
      WASM_UNREACHABLE();
    }
    case none: {
      value = builder.makeDrop(value);
    }
    case unreachable: {
      // can leave it, the call isn't taken anyhow
      break;
    }
  }
  return value;
}

struct ParallelFuncCastEmulation
  : public WalkerPass<PostWalker<ParallelFuncCastEmulation>> {
  bool isFunctionParallel() override { return true; }

  Pass* create() override { return new ParallelFuncCastEmulation(ABIType); }

  ParallelFuncCastEmulation(Name ABIType) : ABIType(ABIType) {}

  void visitCallIndirect(CallIndirect* curr) {
    if (curr->operands.size() > NUM_PARAMS) {
      Fatal() << "FuncCastEmulation::NUM_PARAMS needs to be at least "
              << curr->operands.size();
    }
    for (Expression*& operand : curr->operands) {
      operand = toABI(operand, getModule());
    }
    // Add extra operands as needed.
    while (curr->operands.size() < NUM_PARAMS) {
      curr->operands.push_back(LiteralUtils::makeZero(i64, *getModule()));
    }
    // Set the new types
    curr->fullType = ABIType;
    auto oldType = curr->type;
    curr->type = i64;
    curr->finalize(); // may be unreachable
    // Fix up return value
    replaceCurrent(fromABI(curr, oldType, getModule()));
  }

private:
  // the name of a type for a call with the right params and return
  Name ABIType;
};

struct FuncCastEmulation : public Pass {
  void run(PassRunner* runner, Module* module) override {
    // we just need the one ABI function type for all indirect calls
    std::string sig = "j";
    for (Index i = 0; i < NUM_PARAMS; i++) {
      sig += 'j';
    }
    ABIType = ensureFunctionType(sig, module)->name;
    // Add a way for JS to call into the table (as our i64 ABI means an i64
    // is returned when there is a return value, which JS engines will fail on),
    // using dynCalls
    EmscriptenGlueGenerator generator(*module);
    generator.generateDynCallThunks();
    // Add a thunk for each function in the table, and do the call through it.
    std::unordered_map<Name, Name> funcThunks;
    for (auto& segment : module->table.segments) {
      for (auto& name : segment.data) {
        auto iter = funcThunks.find(name);
        if (iter == funcThunks.end()) {
          auto thunk = makeThunk(name, module);
          funcThunks[name] = thunk;
          name = thunk;
        } else {
          name = iter->second;
        }
      }
    }
    // update call_indirects
    PassRunner subRunner(module, runner->options);
    subRunner.setIsNested(true);
    subRunner.add<ParallelFuncCastEmulation>(ABIType);
    subRunner.run();
  }

private:
  // the name of a type for a call with the right params and return
  Name ABIType;

  // Creates a thunk for a function, casting args and return value as needed.
  Name makeThunk(Name name, Module* module) {
    Name thunk = std::string("byn$fpcast-emu$") + name.str;
    if (module->getFunctionOrNull(thunk)) {
      Fatal() << "FuncCastEmulation::makeThunk seems a thunk name already in "
                 "use. Was the pass already run on this code?";
    }
    // The item in the table may be a function or a function import.
    auto* func = module->getFunction(name);
    std::vector<Type>& params = func->params;
    Type type = func->result;
    Builder builder(*module);
    std::vector<Expression*> callOperands;
    for (Index i = 0; i < params.size(); i++) {
      callOperands.push_back(
        fromABI(builder.makeGetLocal(i, i64), params[i], module));
    }
    auto* call = builder.makeCall(name, callOperands, type);
    std::vector<Type> thunkParams;
    for (Index i = 0; i < NUM_PARAMS; i++) {
      thunkParams.push_back(i64);
    }
    auto* thunkFunc = builder.makeFunction(thunk,
                                           std::move(thunkParams),
                                           i64,
                                           {}, // no vars
                                           toABI(call, module));
    thunkFunc->type = ABIType;
    module->addFunction(thunkFunc);
    return thunk;
  }
};

Pass* createFuncCastEmulationPass() { return new FuncCastEmulation(); }

} // namespace wasm
