/*
 * 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 "CCallHelpers.h"
#include "RegisterSet.h"
#include <wtf/SharedTask.h>

namespace JSC { 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)
