/*
 * Copyright (C) 2015-2018 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(B3_JIT)

#include "B3ConstrainedValue.h"
#include "B3Value.h"
#include "B3ValueRep.h"
#include "RegisterSet.h"
#include <wtf/SharedTask.h>

namespace JSC {

class CCallHelpers;

namespace B3 {

class StackmapGenerationParams;

typedef void StackmapGeneratorFunction(CCallHelpers&, const StackmapGenerationParams&);
typedef SharedTask<StackmapGeneratorFunction> StackmapGenerator;

class JS_EXPORT_PRIVATE StackmapValue : public Value {
public:
    static bool accepts(Kind kind)
    {
        // This needs to include opcodes of all subclasses.
        switch (kind.opcode()) {
        case CheckAdd:
        case CheckSub:
        case CheckMul:
        case Check:
        case Patchpoint:
            return true;
        default:
            return false;
        }
    }

    ~StackmapValue();

    // Use this to add children.
    void append(const ConstrainedValue& value)
    {
        ASSERT(value.value()->type().isNumeric());
        append(value.value(), value.rep());
    }

    void append(Value*, const ValueRep&);

    template<typename VectorType>
    void appendVector(const VectorType& vector)
    {
        for (const auto& value : vector)
            append(value);
    }

    // Helper for appending a bunch of values with some ValueRep.
    template<typename VectorType>
    void appendVectorWithRep(const VectorType& vector, const ValueRep& rep)
    {
        for (Value* value : vector)
            append(value, rep);
    }

    // Helper for appending cold any's. This often used by clients to implement OSR.
    template<typename VectorType>
    void appendColdAnys(const VectorType& vector)
    {
        appendVectorWithRep(vector, ValueRep::ColdAny);
    }
    template<typename VectorType>
    void appendLateColdAnys(const VectorType& vector)
    {
        appendVectorWithRep(vector, ValueRep::LateColdAny);
    }

    // This is a helper for something you might do a lot of: append a value that should be constrained
    // to SomeRegister.
    void appendSomeRegister(Value*);
    void appendSomeRegisterWithClobber(Value*);
    
    const Vector<ValueRep>& reps() const { return m_reps; }

    // Stackmaps allow you to specify that the operation may clobber some registers. Clobbering a register
    // means that the operation appears to store a value into the register, but the compiler doesn't
    // assume to know anything about what kind of value might have been stored. In B3's model of
    // execution, registers are read or written at instruction boundaries rather than inside the
    // instructions themselves. A register could be read or written immediately before the instruction
    // executes, or immediately after. Note that at a boundary between instruction A and instruction B we
    // simultaneously look at what A does after it executes and what B does before it executes. This is
    // because when the compiler considers what happens to registers, it views the boundary between two
    // instructions as a kind of atomic point where the late effects of A happen at the same time as the
    // early effects of B.
    //
    // The compiler views a stackmap as a single instruction, even though of course the stackmap may be
    // composed of any number of instructions (if it's a Patchpoint). You can claim that a stackmap value
    // clobbers a set of registers before the stackmap's instruction or after. Clobbering before is called
    // early clobber, while clobbering after is called late clobber.
    //
    // This is quite flexible but it has its limitations. Any register listed as an early clobber will
    // interfere with all uses of the stackmap. Any register listed as a late clobber will interfere with
    // all defs of the stackmap (i.e. the result). This means that it's currently not possible to claim
    // to clobber a register while still allowing that register to be used for both an input and an output
    // of the instruction. It just so happens that B3's sole client (the FTL) currently never wants to
    // convey such a constraint, but it will want it eventually (FIXME:
    // https://bugs.webkit.org/show_bug.cgi?id=151823).
    //
    // Note that a common use case of early clobber sets is to indicate that this is the set of registers
    // that shall not be used for inputs to the value. But B3 supports two different ways of specifying
    // this, the other being LateUse in combination with late clobber (not yet available to stackmaps
    // directly, FIXME: https://bugs.webkit.org/show_bug.cgi?id=151335). A late use makes the use of that
    // value appear to happen after the instruction. This means that a late use cannot use the same
    // register as the result and it cannot use the same register as either early or late clobbered
    // registers. Late uses are usually a better way of saying that a clobbered register cannot be used
    // for an input. Early clobber means that some register(s) interfere with *all* inputs, while LateUse
    // means that some value interferes with whatever is live after the instruction. Below is a list of
    // examples of how the FTL can handle its various kinds of scenarios using a combination of early
    // clobber, late clobber, and late use. These examples are for X86_64, w.l.o.g.
    //
    // Basic ById patchpoint: Early and late clobber of r11. Early clobber prevents any inputs from using
    // r11 since that would mess with the MacroAssembler's assumptions when we
    // AllowMacroScratchRegisterUsage. Late clobber tells B3 that the patchpoint may overwrite r11.
    //
    // ById patchpoint in a try block with some live state: This might throw an exception after already
    // assigning to the result. So, this should LateUse all stackmap values to ensure that the stackmap
    // values don't interfere with the result. Note that we do not LateUse the non-OSR inputs of the ById
    // since LateUse implies that the use is cold: the register allocator will assume that the use is not
    // important for the critical path. Also, early and late clobber of r11.
    //
    // Basic ByIdFlush patchpoint: We could do Flush the same way we did it with LLVM: ignore it and let
    // PolymorphicAccess figure it out. Or, we could add internal clobber support (FIXME:
    // https://bugs.webkit.org/show_bug.cgi?id=151823). Or, we could do it by early clobbering r11, late
    // clobbering all volatile registers, and constraining the result to some register. Or, we could do
    // that but leave the result constrained to SomeRegister, which will cause it to use a callee-save
    // register. Internal clobber support would allow us to use SomeRegister while getting the result into
    // a volatile register.
    //
    // ByIdFlush patchpoint in a try block with some live state: LateUse all for-OSR stackmap values,
    // early clobber of r11 to prevent the other inputs from using r11, and late clobber of all volatile
    // registers to make way for the call. To handle the result, we could do any of what is listed in the
    // previous paragraph.
    //
    // Basic JS call: Force all non-OSR inputs into specific locations (register, stack, whatever).
    // All volatile registers are late-clobbered. The output is constrained to a register as well.
    //
    // JS call in a try block with some live state: LateUse all for-OSR stackmap values, fully constrain
    // all non-OSR inputs and the result, and late clobber all volatile registers.
    //
    // JS tail call: Pass all inputs as a warm variant of Any (FIXME:
    // https://bugs.webkit.org/show_bug.cgi?id=151811).
    //
    // Note that we cannot yet do all of these things because although Air already supports all of these
    // various forms of uses (LateUse and warm unconstrained use), B3 doesn't yet expose all of it. The
    // bugs are:
    // https://bugs.webkit.org/show_bug.cgi?id=151335 (LateUse)
    // https://bugs.webkit.org/show_bug.cgi?id=151811 (warm Any)
    void clobberEarly(const RegisterSet& set)
    {
        m_earlyClobbered.merge(set);
    }

    void clobberLate(const RegisterSet& set)
    {
        m_lateClobbered.merge(set);
    }

    void clobber(const RegisterSet& set)
    {
        clobberEarly(set);
        clobberLate(set);
    }

    RegisterSet& earlyClobbered() { return m_earlyClobbered; }
    RegisterSet& lateClobbered() { return m_lateClobbered; }
    const RegisterSet& earlyClobbered() const { return m_earlyClobbered; }
    const RegisterSet& lateClobbered() const { return m_lateClobbered; }

    void setGenerator(RefPtr<StackmapGenerator> generator)
    {
        m_generator = generator;
    }

    template<typename Functor>
    void setGenerator(const Functor& functor)
    {
        m_generator = createSharedTask<StackmapGeneratorFunction>(functor);
    }

    RefPtr<StackmapGenerator> generator() const { return m_generator; }

    ConstrainedValue constrainedChild(unsigned index) const
    {
        return ConstrainedValue(child(index), index < m_reps.size() ? m_reps[index] : ValueRep::ColdAny);
    }

    void setConstrainedChild(unsigned index, const ConstrainedValue&);
    
    void setConstraint(unsigned index, const ValueRep&);

    class ConstrainedValueCollection {
    public:

        ConstrainedValueCollection(const StackmapValue& value)
            : m_value(value)
        {
        }

        unsigned size() const { return m_value.numChildren(); }
        
        ConstrainedValue at(unsigned index) const { return m_value.constrainedChild(index); }

        ConstrainedValue operator[](unsigned index) const { return at(index); }

        class iterator {
        public:
            using iterator_category = std::forward_iterator_tag;
            using value_type = ConstrainedValue;
            using difference_type = int;
            using pointer = void;
            using reference = ConstrainedValue;

            iterator()
                : m_collection(nullptr)
                , m_index(0)
            {
            }

            iterator(const ConstrainedValueCollection& collection, unsigned index)
                : m_collection(&collection)
                , m_index(index)
            {
            }

            ConstrainedValue operator*() const
            {
                return m_collection->at(m_index);
            }

            iterator& operator++()
            {
                m_index++;
                return *this;
            }

            bool operator==(const iterator& other) const
            {
                ASSERT(m_collection == other.m_collection);
                return m_index == other.m_index;
            }

            bool operator!=(const iterator& other) const
            {
                return !(*this == other);
            }
            
        private:
            const ConstrainedValueCollection* m_collection;
            unsigned m_index;
        };

        iterator begin() const { return iterator(*this, 0); }
        iterator end() const { return iterator(*this, size()); }

    private:
        const StackmapValue& m_value;
    };

    ConstrainedValueCollection constrainedChildren() const
    {
        return ConstrainedValueCollection(*this);
    }

    B3_SPECIALIZE_VALUE_FOR_VARARGS_CHILDREN

protected:
    void dumpChildren(CommaPrinter&, PrintStream&) const override;
    void dumpMeta(CommaPrinter&, PrintStream&) const override;

    StackmapValue(CheckedOpcodeTag, Kind, Type, Origin);

private:
    friend class CheckSpecial;
    friend class PatchpointSpecial;
    friend class StackmapGenerationParams;
    friend class StackmapSpecial;
    
    Vector<ValueRep> m_reps;
    RefPtr<StackmapGenerator> m_generator;
    RegisterSet m_earlyClobbered;
    RegisterSet m_lateClobbered;
    RegisterSet m_usedRegisters; // Stackmaps could be further duplicated by Air, but that's unlikely, so we just merge the used registers sets if that were to happen.
};

} } // namespace JSC::B3

#endif // ENABLE(B3_JIT)
