/*
 * Copyright (C) 2011-2016 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

#include "DFGCompilationMode.h"

#if ENABLE(DFG_JIT)

#include "Options.h"
#include <limits.h>
#include <wtf/text/StringImpl.h>

namespace JSC { namespace DFG {

struct Node;

typedef uint32_t BlockIndex;
static const BlockIndex NoBlock = UINT_MAX;

// Use RefChildren if the child ref counts haven't already been adjusted using
// other means and either of the following is true:
// - The node you're creating is MustGenerate.
// - The place where you're inserting a reference to the node you're creating
//   will not also do RefChildren.
enum RefChildrenMode {
    RefChildren,
    DontRefChildren
};

// Use RefNode if you know that the node will be used from another node, and you
// will not already be ref'ing the node to account for that use.
enum RefNodeMode {
    RefNode,
    DontRefNode
};

enum SwitchKind {
    SwitchImm,
    SwitchChar,
    SwitchString,
    SwitchCell
};

inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode)
{
    return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) && Options::verboseFTLCompilation());
}

inline bool logCompilationChanges(CompilationMode mode = DFGMode)
{
    return verboseCompilationEnabled(mode) || Options::logCompilationChanges();
}

inline bool shouldDumpGraphAtEachPhase(CompilationMode mode)
{
    if (isFTL(mode))
        return Options::dumpGraphAtEachPhase() || Options::dumpDFGFTLGraphAtEachPhase();
    return Options::dumpGraphAtEachPhase() || Options::dumpDFGGraphAtEachPhase();
}

inline bool validationEnabled()
{
#if !ASSERT_DISABLED
    return true;
#else
    return Options::validateGraph() || Options::validateGraphAtEachPhase();
#endif
}

inline bool enableInt52()
{
#if USE(JSVALUE64)
    return true;
#else
    return false;
#endif
}

// The prediction propagator effectively does four passes, with the last pass
// being done by the separate FixuPhase.
enum PredictionPass {
    // We're converging in a straight-forward forward flow fixpoint. This is the
    // most conventional part of the propagator - it makes only monotonic decisions
    // based on value profiles and rare case profiles. It ignores baseline JIT rare
    // case profiles. The goal here is to develop a good guess of which variables
    // are likely to be purely numerical, which generally doesn't require knowing
    // the rare case profiles.
    PrimaryPass,
    
    // At this point we know what is numerical and what isn't. Non-numerical inputs
    // to arithmetic operations will not have useful information in the Baseline JIT
    // rare case profiles because Baseline may take slow path on non-numerical
    // inputs even if the DFG could handle the input on the fast path. Boolean
    // inputs are the most obvious example. This pass of prediction propagation will
    // use Baseline rare case profiles for purely numerical operations and it will
    // ignore them for everything else. The point of this pass is to develop a good
    // guess of which variables are likely to be doubles.
    //
    // This pass is intentionally weird and goes against what is considered good
    // form when writing a static analysis: a new data flow of booleans will cause
    // us to ignore rare case profiles except that by then, we will have already
    // propagated double types based on our prior assumption that we shouldn't
    // ignore rare cases. This probably won't happen because the PrimaryPass is
    // almost certainly going to establish what is and isn't numerical. But it's
    // conceivable that during this pass we will discover a new boolean data flow.
    // This ends up being sound because the prediction propagator could literally
    // make any guesses it wants and still be sound (worst case, we OSR exit more
    // often or use too general of types are run a bit slower). This will converge
    // because we force monotonicity on the types of nodes and variables. So, the
    // worst thing that can happen is that we violate basic laws of theoretical
    // decency.
    RareCasePass,
    
    // At this point we know what is numerical and what isn't, and we also know what
    // is a double and what isn't. So, we start forcing variables to be double.
    // Doing so may have a cascading effect so this is a fixpoint. It's monotonic
    // in the sense that once a variable is forced double, it cannot be forced in
    // the other direction.
    DoubleVotingPass,
    
    // This pass occurs once we have converged. At this point we are just installing
    // type checks based on the conclusions we have already reached. It's important
    // for this pass to reach the same conclusions that DoubleVotingPass reached.
    FixupPass
};

enum StructureRegistrationState { HaveNotStartedRegistering, AllStructuresAreRegistered };

enum StructureRegistrationResult { StructureRegisteredNormally, StructureRegisteredAndWatched };

enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };

// Describes the form you can expect the entire graph to be in.
enum GraphForm {
    // LoadStore form means that basic blocks may freely use GetLocal, SetLocal,
    // and Flush for accessing local variables and indicating where their live
    // ranges ought to be. Data flow between local accesses is implicit. Liveness
    // is only explicit at block heads (variablesAtHead). This is only used by
    // the DFG simplifier and is only preserved by same.
    //
    // For example, LoadStore form gives no easy way to determine which SetLocal's
    // flow into a GetLocal. As well, LoadStore form implies no restrictions on
    // redundancy: you can freely emit multiple GetLocals, or multiple SetLocals
    // (or any combination thereof) to the same local in the same block. LoadStore
    // form does not require basic blocks to declare how they affect or use locals,
    // other than implicitly by using the local ops and by preserving
    // variablesAtHead. Finally, LoadStore allows flexibility in how liveness of
    // locals is extended; for example you can replace a GetLocal with a Phantom
    // and so long as the Phantom retains the GetLocal's children (i.e. the Phi
    // most likely) then it implies that the local is still live but that it need
    // not be stored to the stack necessarily. This implies that Phantom can
    // reference nodes that have no result, as long as those nodes are valid
    // GetLocal children (i.e. Phi, SetLocal, SetArgument).
    //
    // LoadStore form also implies that Phis need not have children. By default,
    // they end up having no children if you enter LoadStore using the canonical
    // way (call Graph::dethread).
    //
    // LoadStore form is suitable for CFG transformations, as well as strength
    // reduction, folding, and CSE.
    LoadStore,
    
    // ThreadedCPS form means that basic blocks list up-front which locals they
    // expect to be live at the head, and which locals they make available at the
    // tail. ThreadedCPS form also implies that:
    //
    // - GetLocals and SetLocals are not redundant within a basic block.
    //
    // - All GetLocals and Flushes are linked directly to the last access point
    //   of the variable, which must not be another GetLocal.
    //
    // - Phantom(Phi) is not legal, but PhantomLocal is.
    //
    // ThreadedCPS form is suitable for data flow analysis (CFA, prediction
    // propagation), register allocation, and code generation.
    ThreadedCPS,
    
    // SSA form. See DFGSSAConversionPhase.h for a description.
    SSA
};

// Describes the state of the UnionFind structure of VariableAccessData's.
enum UnificationState {
    // BasicBlock-local accesses to variables are appropriately unified with each other.
    LocallyUnified,
    
    // Unification has been performed globally.
    GloballyUnified
};

// Describes how reference counts in the graph behave.
enum RefCountState {
    // Everything has refCount() == 1.
    EverythingIsLive,

    // Set after DCE has run.
    ExactRefCount
};

enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation };

enum ProofStatus { NeedsCheck, IsProved };

inline bool isProved(ProofStatus proofStatus)
{
    ASSERT(proofStatus == IsProved || proofStatus == NeedsCheck);
    return proofStatus == IsProved;
}

inline ProofStatus proofStatusForIsProved(bool isProved)
{
    return isProved ? IsProved : NeedsCheck;
}

enum KillStatus { DoesNotKill, DoesKill };

inline bool doesKill(KillStatus killStatus)
{
    ASSERT(killStatus == DoesNotKill || killStatus == DoesKill);
    return killStatus == DoesKill;
}

inline KillStatus killStatusForDoesKill(bool doesKill)
{
    return doesKill ? DoesKill : DoesNotKill;
}

enum class PlanStage {
    Initial,
    AfterFixup
};

// If possible, this will acquire a lock to make sure that if multiple threads
// start crashing at the same time, you get coherent dump output. Use this only
// when you're forcing a crash with diagnostics.
void startCrashing();

JS_EXPORT_PRIVATE bool isCrashing();

struct NodeAndIndex {
    NodeAndIndex()
        : node(nullptr)
        , index(UINT_MAX)
    {
    }
    
    NodeAndIndex(Node* node, unsigned index)
        : node(node)
        , index(index)
    {
        ASSERT(!node == (index == UINT_MAX));
    }
    
    bool operator!() const
    {
        return !node;
    }
    
    Node* node;
    unsigned index;
};

// A less-than operator for strings that is useful for generating string switches. Sorts by <
// relation on characters. Ensures that if a is a prefix of b, then a < b.
bool stringLessThan(StringImpl& a, StringImpl& b);

} } // namespace JSC::DFG

namespace WTF {

void printInternal(PrintStream&, JSC::DFG::OptimizationFixpointState);
void printInternal(PrintStream&, JSC::DFG::GraphForm);
void printInternal(PrintStream&, JSC::DFG::UnificationState);
void printInternal(PrintStream&, JSC::DFG::RefCountState);
void printInternal(PrintStream&, JSC::DFG::ProofStatus);

} // namespace WTF

#endif // ENABLE(DFG_JIT)

namespace JSC { namespace DFG {

// Put things here that must be defined even if ENABLE(DFG_JIT) is false.

enum CapabilityLevel {
    CannotCompile,
    CanCompile,
    CanCompileAndInline,
    CapabilityLevelNotSet
};

inline bool canCompile(CapabilityLevel level)
{
    switch (level) {
    case CanCompile:
    case CanCompileAndInline:
        return true;
    default:
        return false;
    }
}

inline bool canInline(CapabilityLevel level)
{
    switch (level) {
    case CanCompileAndInline:
        return true;
    default:
        return false;
    }
}

inline CapabilityLevel leastUpperBound(CapabilityLevel a, CapabilityLevel b)
{
    switch (a) {
    case CannotCompile:
        return CannotCompile;
    case CanCompile:
        switch (b) {
        case CanCompile:
        case CanCompileAndInline:
            return CanCompile;
        default:
            return CannotCompile;
        }
    case CanCompileAndInline:
        return b;
    case CapabilityLevelNotSet:
        ASSERT_NOT_REACHED();
        return CannotCompile;
    }
    ASSERT_NOT_REACHED();
    return CannotCompile;
}

// Unconditionally disable DFG disassembly support if the DFG is not compiled in.
inline bool shouldDumpDisassembly(CompilationMode mode = DFGMode)
{
#if ENABLE(DFG_JIT)
    return Options::dumpDisassembly() || Options::dumpDFGDisassembly() || (isFTL(mode) && Options::dumpFTLDisassembly());
#else
    UNUSED_PARAM(mode);
    return false;
#endif
}

} } // namespace JSC::DFG

namespace WTF {

void printInternal(PrintStream&, JSC::DFG::CapabilityLevel);

} // namespace WTF
