// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/backend/evaluator.h"

namespace dart {

static IntegerPtr BinaryIntegerEvaluateRaw(const Integer& left,
                                           const Integer& right,
                                           Token::Kind token_kind) {
  switch (token_kind) {
    case Token::kTRUNCDIV:
      FALL_THROUGH;
    case Token::kMOD:
      // Check right value for zero.
      if (right.AsInt64Value() == 0) {
        break;  // Will throw.
      }
      FALL_THROUGH;
    case Token::kADD:
      FALL_THROUGH;
    case Token::kSUB:
      FALL_THROUGH;
    case Token::kMUL:
      return left.ArithmeticOp(token_kind, right, Heap::kOld);
    case Token::kSHL:
      FALL_THROUGH;
    case Token::kSHR:
      FALL_THROUGH;
    case Token::kUSHR:
      if (right.AsInt64Value() >= 0) {
        return left.ShiftOp(token_kind, right, Heap::kOld);
      }
      break;
    case Token::kBIT_AND:
      FALL_THROUGH;
    case Token::kBIT_OR:
      FALL_THROUGH;
    case Token::kBIT_XOR:
      return left.BitOp(token_kind, right, Heap::kOld);
    case Token::kDIV:
      break;
    default:
      UNREACHABLE();
  }

  return Integer::null();
}

static IntegerPtr UnaryIntegerEvaluateRaw(const Integer& value,
                                          Token::Kind token_kind,
                                          Zone* zone) {
  switch (token_kind) {
    case Token::kNEGATE:
      return value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
                                Heap::kOld);
    case Token::kBIT_NOT:
      if (value.IsSmi()) {
        return Integer::New(~Smi::Cast(value).Value(), Heap::kOld);
      } else if (value.IsMint()) {
        return Integer::New(~Mint::Cast(value).value(), Heap::kOld);
      }
      break;
    default:
      UNREACHABLE();
  }
  return Integer::null();
}

static IntegerPtr BitLengthEvaluateRaw(const Integer& value, Zone* zone) {
  if (value.IsSmi()) {
    return Integer::New(Utils::BitLength(Smi::Cast(value).Value()), Heap::kOld);
  } else if (value.IsMint()) {
    return Integer::New(Utils::BitLength(Mint::Cast(value).value()),
                        Heap::kOld);
  }
  return Integer::null();
}

int64_t Evaluator::TruncateTo(int64_t v, Representation r) {
  switch (r) {
    case kTagged: {
      const intptr_t kTruncateBits =
          kBitsPerInt64 - (compiler::target::kSmiBits + 1 /*sign bit*/);
      return Utils::ShiftLeftWithTruncation(v, kTruncateBits) >> kTruncateBits;
    }
    case kUnboxedInt32:
      return Utils::ShiftLeftWithTruncation(v, kBitsPerInt32) >> kBitsPerInt32;
    case kUnboxedUint32:
      return v & kMaxUint32;
    case kUnboxedInt64:
      return v;
    default:
      UNREACHABLE();
  }
}

IntegerPtr Evaluator::BinaryIntegerEvaluate(const Object& left,
                                            const Object& right,
                                            Token::Kind token_kind,
                                            bool is_truncating,
                                            Representation representation,
                                            Thread* thread) {
  if (!left.IsInteger() || !right.IsInteger()) {
    return Integer::null();
  }
  Zone* zone = thread->zone();
  const Integer& left_int = Integer::Cast(left);
  const Integer& right_int = Integer::Cast(right);
  Integer& result = Integer::Handle(
      zone, BinaryIntegerEvaluateRaw(left_int, right_int, token_kind));

  if (!result.IsNull()) {
    if (is_truncating) {
      const int64_t truncated =
          TruncateTo(result.AsTruncatedInt64Value(), representation);
      result = Integer::New(truncated, Heap::kOld);
      ASSERT(FlowGraph::IsConstantRepresentable(
          result, representation, /*tagged_value_must_be_smi=*/true));
    } else if (!FlowGraph::IsConstantRepresentable(
                   result, representation, /*tagged_value_must_be_smi=*/true)) {
      // If this operation is not truncating it would deoptimize on overflow.
      // Check that we match this behavior and don't produce a value that is
      // larger than something this operation can produce. We could have
      // specialized instructions that use this value under this assumption.
      return Integer::null();
    }
    result ^= result.Canonicalize(thread);
  }

  return result.ptr();
}

IntegerPtr Evaluator::UnaryIntegerEvaluate(const Object& value,
                                           Token::Kind token_kind,
                                           Representation representation,
                                           Thread* thread) {
  if (!value.IsInteger()) {
    return Integer::null();
  }
  Zone* zone = thread->zone();
  const Integer& value_int = Integer::Cast(value);
  Integer& result = Integer::Handle(
      zone, UnaryIntegerEvaluateRaw(value_int, token_kind, zone));

  if (!result.IsNull()) {
    if (!FlowGraph::IsConstantRepresentable(
            result, representation,
            /*tagged_value_must_be_smi=*/true)) {
      // If this operation is not truncating it would deoptimize on overflow.
      // Check that we match this behavior and don't produce a value that is
      // larger than something this operation can produce. We could have
      // specialized instructions that use this value under this assumption.
      return Integer::null();
    }

    result ^= result.Canonicalize(thread);
  }

  return result.ptr();
}

IntegerPtr Evaluator::BitLengthEvaluate(const Object& value,
                                        Representation representation,
                                        Thread* thread) {
  if (!value.IsInteger()) {
    return Integer::null();
  }
  Zone* zone = thread->zone();
  const Integer& value_int = Integer::Cast(value);
  Integer& result =
      Integer::Handle(zone, BitLengthEvaluateRaw(value_int, zone));

  if (!result.IsNull()) {
    if (!FlowGraph::IsConstantRepresentable(
            result, representation,
            /*tagged_value_must_be_smi=*/true)) {
      // If this operation is not truncating it would deoptimize on overflow.
      // Check that we match this behavior and don't produce a value that is
      // larger than something this operation can produce. We could have
      // specialized instructions that use this value under this assumption.
      return Integer::null();
    }

    result ^= result.Canonicalize(thread);
  }

  return result.ptr();
}

double Evaluator::EvaluateDoubleOp(const double left,
                                   const double right,
                                   Token::Kind token_kind) {
  switch (token_kind) {
    case Token::kADD:
      return left + right;
    case Token::kSUB:
      return left - right;
    case Token::kMUL:
      return left * right;
    case Token::kDIV:
      return left / right;
    default:
      UNREACHABLE();
  }
}

bool Evaluator::ToIntegerConstant(Value* value, int64_t* result) {
  if (!value->BindsToConstant()) {
    UnboxInstr* unbox = value->definition()->AsUnbox();
    if (unbox != nullptr) {
      switch (unbox->representation()) {
        case kUnboxedDouble:
        case kUnboxedInt64:
          return ToIntegerConstant(unbox->value(), result);
        case kUnboxedUint32:
          if (ToIntegerConstant(unbox->value(), result)) {
            *result = Evaluator::TruncateTo(*result, kUnboxedUint32);
            return true;
          }
          break;
          // No need to handle Unbox<Int32>(Constant(C)) because it gets
          // canonicalized to UnboxedConstant<Int32>(C).
        case kUnboxedInt32:
        default:
          break;
      }
    }
    return false;
  }
  const Object& constant = value->BoundConstant();
  if (constant.IsDouble()) {
    const Double& double_constant = Double::Cast(constant);
    *result = Utils::SafeDoubleToInt<int64_t>(double_constant.value());
    return (static_cast<double>(*result) == double_constant.value());
  } else if (constant.IsSmi()) {
    *result = Smi::Cast(constant).Value();
    return true;
  } else if (constant.IsMint()) {
    *result = Mint::Cast(constant).value();
    return true;
  }
  return false;
}

}  // namespace dart
