/*
 * Copyright (C) 2014 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#pragma once

#if ENABLE(DFG_JIT)

namespace JSC {

class CallFrame;
using ExecState = CallFrame;
using EncodedJSValue = int64_t;

namespace DFG {

// Arith::Mode describes the mode of an arithmetic operation that speculates integer.
// Note that not all modes are valid for all operations.
namespace Arith {
enum Mode {
    NotSet, // Arithmetic mode is either not relevant because we're using doubles anyway or we are at a phase in compilation where we don't know what we're doing, yet. Should never see this after FixupPhase except for nodes that take doubles as inputs already.
    Unchecked, // Don't check anything and just do the direct hardware operation.
    CheckOverflow, // Check for overflow but don't bother with negative zero.
    CheckOverflowAndNegativeZero, // Check for both overflow and negative zero.
    DoOverflow // Up-convert to the smallest type that soundly represents all possible results after input type speculation.
};

// Define the type of operation the rounding operation will perform.
enum class RoundingMode {
    Int32, // The round operation produces a integer and -0 is considered as 0.
    Int32WithNegativeZeroCheck, // The round operation produces a integer and checks for -0.
    Double // The round operation produce a double. The result can be -0, NaN or (+/-)Infinity.
};


// This macro defines a set of information about all known arith unary generic node.
#define FOR_EACH_DFG_ARITH_UNARY_OP(macro) \
    macro(Sin, sin) \
    macro(Sinh, sinh) \
    macro(Cos, cos) \
    macro(Cosh, cosh) \
    macro(Tan, tan) \
    macro(Tanh, tanh) \
    macro(ASin, asin) \
    macro(ASinh, asinh) \
    macro(ACos, acos) \
    macro(ACosh, acosh) \
    macro(ATan, atan) \
    macro(ATanh, atanh) \
    macro(Log, log) \
    macro(Log10, log10) \
    macro(Log1p, log1p) \
    macro(Log2, log2) \
    macro(Cbrt, cbrt) \
    macro(Exp, exp) \
    macro(Expm1, expm1) \

enum class UnaryType : uint32_t {
#define DFG_ARITH_UNARY_ENUM(capitalizedName, lowerName) capitalizedName,
    FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY_ENUM)
#undef DFG_ARITH_UNARY_ENUM
};

typedef double (*UnaryFunction)(double);
typedef double (*UnaryOperation)(ExecState*, EncodedJSValue);

} // namespace Arith

inline bool doesOverflow(Arith::Mode mode)
{
    switch (mode) {
    case Arith::NotSet:
        ASSERT_NOT_REACHED();
#if ASSERT_DISABLED
        FALLTHROUGH;
#endif
    case Arith::Unchecked:
    case Arith::CheckOverflow:
    case Arith::CheckOverflowAndNegativeZero:
        return false;
    case Arith::DoOverflow:
        return true;
    }
    ASSERT_NOT_REACHED();
    return true;
}

// It's only valid to call this once you've determined that you don't need to *do*
// overflow. For most nodes, that's implicit.
inline bool shouldCheckOverflow(Arith::Mode mode)
{
    switch (mode) {
    case Arith::NotSet:
    case Arith::DoOverflow:
        ASSERT_NOT_REACHED();
        return true;
    case Arith::Unchecked:
        return false;
    case Arith::CheckOverflow:
    case Arith::CheckOverflowAndNegativeZero:
        return true;
    }
    ASSERT_NOT_REACHED();
    return true;
}

inline bool shouldCheckNegativeZero(Arith::Mode mode)
{
    switch (mode) {
    case Arith::NotSet:
    case Arith::DoOverflow:
        ASSERT_NOT_REACHED();
        return true;
    case Arith::Unchecked:
    case Arith::CheckOverflow:
        return false;
    case Arith::CheckOverflowAndNegativeZero:
        return true;
    }
    ASSERT_NOT_REACHED();
    return true;
}

inline bool subsumes(Arith::Mode earlier, Arith::Mode later)
{
    switch (earlier) {
    case Arith::CheckOverflow:
        switch (later) {
        case Arith::Unchecked:
        case Arith::CheckOverflow:
            return true;
        default:
            return false;
        }
    case Arith::CheckOverflowAndNegativeZero:
        switch (later) {
        case Arith::Unchecked:
        case Arith::CheckOverflow:
        case Arith::CheckOverflowAndNegativeZero:
            return true;
        default:
            return false;
        }
    default:
        return earlier == later;
    }
}

inline bool producesInteger(Arith::RoundingMode mode)
{
    return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck || mode == Arith::RoundingMode::Int32;
}

inline bool shouldCheckNegativeZero(Arith::RoundingMode mode)
{
    return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck;
}

Arith::UnaryFunction arithUnaryFunction(Arith::UnaryType);
Arith::UnaryOperation arithUnaryOperation(Arith::UnaryType);

} } // namespace JSC::DFG

namespace WTF {

class PrintStream;
void printInternal(PrintStream&, JSC::DFG::Arith::Mode);
void printInternal(PrintStream&, JSC::DFG::Arith::RoundingMode);
void printInternal(PrintStream&, JSC::DFG::Arith::UnaryType);

} // namespace WTF

#endif // ENABLE(DFG_JIT)
