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

#include "MacroAssemblerCodeRef.h"

#if ENABLE(ASSEMBLER)

namespace JSC {

enum class NearCallMode : uint8_t { Regular, Tail };

template<PtrTag> class CodeLocationInstruction;
template<PtrTag> class CodeLocationLabel;
template<PtrTag> class CodeLocationJump;
template<PtrTag> class CodeLocationCall;
template<PtrTag> class CodeLocationNearCall;
template<PtrTag> class CodeLocationDataLabelCompact;
template<PtrTag> class CodeLocationDataLabel32;
template<PtrTag> class CodeLocationDataLabelPtr;
template<PtrTag> class CodeLocationConvertibleLoad;

// The CodeLocation* types are all pretty much do-nothing wrappers around
// CodePtr (or MacroAssemblerCodePtr, to give it its full name).  These
// classes only exist to provide type-safety when linking and patching code.
//
// The one new piece of functionallity introduced by these classes is the
// ability to create (or put another way, to re-discover) another CodeLocation
// at an offset from one you already know.  When patching code to optimize it
// we often want to patch a number of instructions that are short, fixed
// offsets apart.  To reduce memory overhead we will only retain a pointer to
// one of the instructions, and we will use the *AtOffset methods provided by
// CodeLocationCommon to find the other points in the code to modify.
template<PtrTag tag>
class CodeLocationCommon : public MacroAssemblerCodePtr<tag> {
    using Base = MacroAssemblerCodePtr<tag>;
public:
    template<PtrTag resultTag = tag> CodeLocationInstruction<resultTag> instructionAtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationLabel<resultTag> labelAtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationJump<resultTag> jumpAtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationCall<resultTag> callAtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationNearCall<resultTag> nearCallAtOffset(int offset, NearCallMode);
    template<PtrTag resultTag = tag> CodeLocationDataLabelPtr<resultTag> dataLabelPtrAtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationDataLabel32<resultTag> dataLabel32AtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationDataLabelCompact<resultTag> dataLabelCompactAtOffset(int offset);
    template<PtrTag resultTag = tag> CodeLocationConvertibleLoad<resultTag> convertibleLoadAtOffset(int offset);

    template<typename T = void*>
    T dataLocation() const { return Base::template dataLocation<T>(); }

    template<typename T, typename = std::enable_if_t<std::is_base_of<CodeLocationCommon<tag>, T>::value>>
    operator T()
    {
        return T(MacroAssemblerCodePtr<tag>::createFromExecutableAddress(this->executableAddress()));
    }

protected:
    CodeLocationCommon()
    {
    }

    CodeLocationCommon(MacroAssemblerCodePtr<tag> location)
        : MacroAssemblerCodePtr<tag>(location)
    {
    }
};

template<PtrTag tag>
class CodeLocationInstruction : public CodeLocationCommon<tag> {
public:
    CodeLocationInstruction() { }
    explicit CodeLocationInstruction(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationInstruction(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
};

template<PtrTag tag>
class CodeLocationLabel : public CodeLocationCommon<tag> {
public:
    CodeLocationLabel() { }
    explicit CodeLocationLabel(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationLabel(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }

    template<PtrTag newTag>
    CodeLocationLabel<newTag> retagged() { return CodeLocationLabel<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }

    template<typename T = void*>
    T untaggedExecutableAddress() const { return CodeLocationCommon<tag>::template untaggedExecutableAddress<T>(); }

    template<typename T = void*>
    T dataLocation() const { return CodeLocationCommon<tag>::template dataLocation<T>(); }
};

template<PtrTag tag>
class CodeLocationJump : public CodeLocationCommon<tag> {
public:
    CodeLocationJump() { }
    explicit CodeLocationJump(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationJump(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }

    template<PtrTag newTag>
    CodeLocationJump<newTag> retagged() { return CodeLocationJump<newTag>(MacroAssemblerCodePtr<tag>::template retagged<newTag>()); }
};

template<PtrTag tag>
class CodeLocationCall : public CodeLocationCommon<tag> {
public:
    CodeLocationCall() { }
    explicit CodeLocationCall(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationCall(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }

    template<PtrTag newTag>
    CodeLocationCall<newTag> retagged() { return CodeLocationCall<newTag>(CodeLocationCommon<tag>::template retagged<newTag>()); }
};

template<PtrTag tag>
class CodeLocationNearCall : public CodeLocationCommon<tag> {
public:
    CodeLocationNearCall() { }
    explicit CodeLocationNearCall(MacroAssemblerCodePtr<tag> location, NearCallMode callMode)
        : CodeLocationCommon<tag>(location), m_callMode(callMode) { }
    explicit CodeLocationNearCall(void* location, NearCallMode callMode)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)), m_callMode(callMode) { }
    NearCallMode callMode() { return m_callMode; }
private:
    NearCallMode m_callMode { NearCallMode::Regular };
};

template<PtrTag tag>
class CodeLocationDataLabel32 : public CodeLocationCommon<tag> {
public:
    CodeLocationDataLabel32() { }
    explicit CodeLocationDataLabel32(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationDataLabel32(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
};

template<PtrTag tag>
class CodeLocationDataLabelCompact : public CodeLocationCommon<tag> {
public:
    CodeLocationDataLabelCompact() { }
    explicit CodeLocationDataLabelCompact(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationDataLabelCompact(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
};

template<PtrTag tag>
class CodeLocationDataLabelPtr : public CodeLocationCommon<tag> {
public:
    CodeLocationDataLabelPtr() { }
    explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationDataLabelPtr(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
};

template<PtrTag tag>
class CodeLocationConvertibleLoad : public CodeLocationCommon<tag> {
public:
    CodeLocationConvertibleLoad() { }
    explicit CodeLocationConvertibleLoad(MacroAssemblerCodePtr<tag> location)
        : CodeLocationCommon<tag>(location) { }
    explicit CodeLocationConvertibleLoad(void* location)
        : CodeLocationCommon<tag>(MacroAssemblerCodePtr<tag>(location)) { }
};

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationInstruction<resultTag> CodeLocationCommon<tag>::instructionAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationInstruction<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationLabel<resultTag> CodeLocationCommon<tag>::labelAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationLabel<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationJump<resultTag> CodeLocationCommon<tag>::jumpAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationJump<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationCall<resultTag> CodeLocationCommon<tag>::callAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationNearCall<resultTag> CodeLocationCommon<tag>::nearCallAtOffset(int offset, NearCallMode callMode)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationNearCall<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset), callMode);
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationDataLabelPtr<resultTag> CodeLocationCommon<tag>::dataLabelPtrAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationDataLabelPtr<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationDataLabel32<resultTag> CodeLocationCommon<tag>::dataLabel32AtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationDataLabel32<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationDataLabelCompact<resultTag> CodeLocationCommon<tag>::dataLabelCompactAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationDataLabelCompact<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

template<PtrTag tag>
template<PtrTag resultTag>
inline CodeLocationConvertibleLoad<resultTag> CodeLocationCommon<tag>::convertibleLoadAtOffset(int offset)
{
    ASSERT_VALID_CODE_OFFSET(offset);
    return CodeLocationConvertibleLoad<resultTag>(tagCodePtr<resultTag>(dataLocation<char*>() + offset));
}

} // namespace JSC

#endif // ENABLE(ASSEMBLER)
