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

//
// Pass that supports potentially-trapping wasm operations.
// For example, integer division traps when dividing by zero, so this pass
// generates a check and replaces the result with zero in that case.
//

#include "asmjs/shared-constants.h"
#include "ir/trapping.h"
#include "pass.h"
#include "support/mixed_arena.h"
#include "support/name.h"
#include "wasm-builder.h"
#include "wasm-type.h"
#include "wasm.h"

namespace wasm {

Name I64S_REM("i64s-rem");
Name I64U_REM("i64u-rem");
Name I64S_DIV("i64s-div");
Name I64U_DIV("i64u-div");

static Expression* ensureDouble(Expression* expr, MixedArena& allocator) {
  if (expr->type == Type::f32) {
    auto conv = allocator.alloc<Unary>();
    conv->op = PromoteFloat32;
    conv->value = expr;
    conv->type = Type::f64;
    return conv;
  }
  assert(expr->type == Type::f64);
  return expr;
}

Name getBinaryFuncName(Binary* curr) {
  switch (curr->op) {
    case RemSInt32:
      return I32S_REM;
    case RemUInt32:
      return I32U_REM;
    case DivSInt32:
      return I32S_DIV;
    case DivUInt32:
      return I32U_DIV;
    case RemSInt64:
      return I64S_REM;
    case RemUInt64:
      return I64U_REM;
    case DivSInt64:
      return I64S_DIV;
    case DivUInt64:
      return I64U_DIV;
    default:
      return Name();
  }
}

Name getUnaryFuncName(Unary* curr) {
  switch (curr->op) {
    case TruncSFloat32ToInt32:
      return F32_TO_INT;
    case TruncUFloat32ToInt32:
      return F32_TO_UINT;
    case TruncSFloat32ToInt64:
      return F32_TO_INT64;
    case TruncUFloat32ToInt64:
      return F32_TO_UINT64;
    case TruncSFloat64ToInt32:
      return F64_TO_INT;
    case TruncUFloat64ToInt32:
      return F64_TO_UINT;
    case TruncSFloat64ToInt64:
      return F64_TO_INT64;
    case TruncUFloat64ToInt64:
      return F64_TO_UINT64;
    default:
      return Name();
  }
}

bool isTruncOpSigned(UnaryOp op) {
  switch (op) {
    case TruncUFloat32ToInt32:
    case TruncUFloat32ToInt64:
    case TruncUFloat64ToInt32:
    case TruncUFloat64ToInt64:
      return false;
    default:
      return true;
  }
}

Function* generateBinaryFunc(Module& wasm, Binary* curr) {
  BinaryOp op = curr->op;
  Type type = curr->type;
  bool isI64 = type == Type::i64;
  Builder builder(wasm);
  Expression* result = builder.makeBinary(
    op, builder.makeLocalGet(0, type), builder.makeLocalGet(1, type));
  BinaryOp divSIntOp = isI64 ? DivSInt64 : DivSInt32;
  UnaryOp eqZOp = isI64 ? EqZInt64 : EqZInt32;
  Literal minLit = isI64 ? Literal(std::numeric_limits<int64_t>::min())
                         : Literal(std::numeric_limits<int32_t>::min());
  Literal zeroLit = isI64 ? Literal(static_cast<int64_t>(0)) : Literal(static_cast<int32_t>(0));
  if (op == divSIntOp) {
    // guard against signed division overflow
    BinaryOp eqOp = isI64 ? EqInt64 : EqInt32;
    Literal negLit = isI64 ? Literal(static_cast<int64_t>(-1)) : Literal(static_cast<int32_t>(-1));
    result = builder.makeIf(
      builder.makeBinary(
        AndInt32,
        builder.makeBinary(
          eqOp, builder.makeLocalGet(0, type), builder.makeConst(minLit)),
        builder.makeBinary(
          eqOp, builder.makeLocalGet(1, type), builder.makeConst(negLit))),
      builder.makeConst(zeroLit),
      result);
  }
  auto funcSig = Signature({type, type}, type);
  auto func = Builder::makeFunction(
    getBinaryFuncName(curr), Type(funcSig, NonNullable, Exact), {});
  func->body =
    builder.makeIf(builder.makeUnary(eqZOp, builder.makeLocalGet(1, type)),
                   builder.makeConst(zeroLit),
                   result);
  // TODO: use unique_ptr properly and do not release ownership.
  return func.release();
}

template<typename IntType, typename FloatType>
void makeClampLimitLiterals(Literal& iMin, Literal& fMin, Literal& fMax) {
  IntType minVal = std::numeric_limits<IntType>::min();
  IntType maxVal = std::numeric_limits<IntType>::max();
  iMin = Literal(minVal);
  fMin = Literal(FloatType(minVal) - 1);
  fMax = Literal(FloatType(maxVal) + 1);
}

Function* generateUnaryFunc(Module& wasm, Unary* curr) {
  Type type = curr->value->type;
  Type retType = curr->type;
  UnaryOp truncOp = curr->op;
  bool isF64 = type == Type::f64;

  Builder builder(wasm);

  BinaryOp leOp = isF64 ? LeFloat64 : LeFloat32;
  BinaryOp geOp = isF64 ? GeFloat64 : GeFloat32;
  BinaryOp neOp = isF64 ? NeFloat64 : NeFloat32;

  Literal iMin, fMin, fMax;
  switch (truncOp) {
    case TruncSFloat32ToInt32:
      makeClampLimitLiterals<int32_t, float>(iMin, fMin, fMax);
      break;
    case TruncUFloat32ToInt32:
      makeClampLimitLiterals<uint32_t, float>(iMin, fMin, fMax);
      break;
    case TruncSFloat32ToInt64:
      makeClampLimitLiterals<int64_t, float>(iMin, fMin, fMax);
      break;
    case TruncUFloat32ToInt64:
      makeClampLimitLiterals<uint64_t, float>(iMin, fMin, fMax);
      break;
    case TruncSFloat64ToInt32:
      makeClampLimitLiterals<int32_t, double>(iMin, fMin, fMax);
      break;
    case TruncUFloat64ToInt32:
      makeClampLimitLiterals<uint32_t, double>(iMin, fMin, fMax);
      break;
    case TruncSFloat64ToInt64:
      makeClampLimitLiterals<int64_t, double>(iMin, fMin, fMax);
      break;
    case TruncUFloat64ToInt64:
      makeClampLimitLiterals<uint64_t, double>(iMin, fMin, fMax);
      break;
    default:
      WASM_UNREACHABLE("unexpected op");
  }

  auto func =
    Builder::makeFunction(getUnaryFuncName(curr),
                          Type(Signature(type, retType), NonNullable, Exact),
                          {});
  func->body = builder.makeUnary(truncOp, builder.makeLocalGet(0, type));
  // too small XXX this is different than asm.js, which does frem. here we
  // clamp, which is much simpler/faster, and similar to native builds
  func->body = builder.makeIf(builder.makeBinary(leOp,
                                                 builder.makeLocalGet(0, type),
                                                 builder.makeConst(fMin)),
                              builder.makeConst(iMin),
                              func->body);
  // too big XXX see above
  func->body = builder.makeIf(
    builder.makeBinary(
      geOp, builder.makeLocalGet(0, type), builder.makeConst(fMax)),
    // NB: min here as well. anything out of range => to the min
    builder.makeConst(iMin),
    func->body);
  // nan
  func->body = builder.makeIf(
    builder.makeBinary(
      neOp, builder.makeLocalGet(0, type), builder.makeLocalGet(0, type)),
    // NB: min here as well. anything invalid => to the min
    builder.makeConst(iMin),
    func->body);
  // TODO: use unique_ptr properly and do not release ownership.
  return func.release();
}

void ensureBinaryFunc(Binary* curr,
                      Module& wasm,
                      TrappingFunctionContainer& trappingFunctions) {
  Name name = getBinaryFuncName(curr);
  if (trappingFunctions.hasFunction(name)) {
    return;
  }
  trappingFunctions.addFunction(generateBinaryFunc(wasm, curr));
}

void ensureUnaryFunc(Unary* curr,
                     Module& wasm,
                     TrappingFunctionContainer& trappingFunctions) {
  Name name = getUnaryFuncName(curr);
  if (trappingFunctions.hasFunction(name)) {
    return;
  }
  trappingFunctions.addFunction(generateUnaryFunc(wasm, curr));
}

void ensureF64ToI64JSImport(TrappingFunctionContainer& trappingFunctions) {
  if (trappingFunctions.hasImport(F64_TO_INT)) {
    return;
  }

  // f64-to-int = asm2wasm.f64-to-int;
  auto import = new Function;
  import->name = F64_TO_INT;
  import->module = ASM2WASM;
  import->base = F64_TO_INT;
  import->type = Type(Signature(Type::f64, Type::i32), NonNullable, Inexact);
  trappingFunctions.addImport(import);
}

Expression* makeTrappingBinary(Binary* curr,
                               TrappingFunctionContainer& trappingFunctions) {
  Name name = getBinaryFuncName(curr);
  if (!name.is() || trappingFunctions.getMode() == TrapMode::Allow) {
    return curr;
  }

  // the wasm operation might trap if done over 0, so generate a safe call
  Type type = curr->type;
  Module& wasm = trappingFunctions.getModule();
  Builder builder(wasm);
  ensureBinaryFunc(curr, wasm, trappingFunctions);
  return builder.makeCall(name, {curr->left, curr->right}, type);
}

Expression* makeTrappingUnary(Unary* curr,
                              TrappingFunctionContainer& trappingFunctions) {
  Name name = getUnaryFuncName(curr);
  TrapMode mode = trappingFunctions.getMode();
  if (!name.is() || mode == TrapMode::Allow) {
    return curr;
  }

  Module& wasm = trappingFunctions.getModule();
  Builder builder(wasm);
  // WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we
  // must do something We can handle this in one of two ways: clamping, which is
  // fast, or JS, which is precisely like JS but in order to do that we do a
  // slow ffi If i64, there is no "JS" way to handle this, as no i64s in JS, so
  // always clamp if we don't allow traps asm.js doesn't have unsigned
  // f64-to-int, so just use the signed one.
  if (curr->type != Type::i64 && mode == TrapMode::JS) {
    // WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we
    // must emulate that
    ensureF64ToI64JSImport(trappingFunctions);
    Expression* f64Value = ensureDouble(curr->value, wasm.allocator);
    return builder.makeCall(F64_TO_INT, {f64Value}, Type::i32);
  }

  ensureUnaryFunc(curr, wasm, trappingFunctions);
  return builder.makeCall(name, {curr->value}, curr->type);
}

struct TrapModePass : public WalkerPass<PostWalker<TrapModePass>> {
public:
  // Needs to be non-parallel so that visitModule gets called after visiting
  // each node in the module, so we can add the functions that we created.
  bool isFunctionParallel() override { return false; }

  TrapModePass(TrapMode mode) : mode(mode) { assert(mode != TrapMode::Allow); }

  std::unique_ptr<Pass> create() override {
    return std::make_unique<TrapModePass>(mode);
  }

  void visitUnary(Unary* curr) {
    replaceCurrent(makeTrappingUnary(curr, *trappingFunctions));
  }

  void visitBinary(Binary* curr) {
    replaceCurrent(makeTrappingBinary(curr, *trappingFunctions));
  }

  void visitModule(Module* curr) { trappingFunctions->addToModule(); }

  void doWalkModule(Module* module) {
    trappingFunctions =
      std::make_unique<TrappingFunctionContainer>(mode, *module);
    Super::doWalkModule(module);
  }

private:
  TrapMode mode;
  // Need to defer adding generated functions because adding functions while
  // iterating over existing functions causes problems.
  std::unique_ptr<TrappingFunctionContainer> trappingFunctions;
};

Pass* createTrapModeClamp() { return new TrapModePass(TrapMode::Clamp); }

Pass* createTrapModeJS() { return new TrapModePass(TrapMode::JS); }

} // namespace wasm
