/*
 * Copyright 2019 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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.
 */

#ifndef __SIM_GUEST_ABI_DISPATCH_HH__
#define __SIM_GUEST_ABI_DISPATCH_HH__

#include <functional>
#include <sstream>
#include <type_traits>

#include "sim/guest_abi/definition.hh"
#include "sim/guest_abi/layout.hh"

class ThreadContext;

namespace GuestABI
{

/*
 * These functions will likely be common among all ABIs and implement the
 * mechanism of gathering arguments, calling the target function, and then
 * storing the result. They might need to be overridden if, for instance,
 * the location of arguments need to be determined in a different order.
 * For example, there might be an ABI which gathers arguments starting
 * from the last in the list instead of the first. This is unlikely but
 * still possible to support by redefining these functions..
 */

// With no arguments to gather, call the target function and store the
// result.
template <typename ABI, bool store_ret, typename Ret>
static typename std::enable_if_t<!std::is_void<Ret>::value && store_ret, Ret>
callFrom(ThreadContext *tc, typename ABI::State &state,
        std::function<Ret(ThreadContext *)> target)
{
    Ret ret = target(tc);
    storeResult<ABI, Ret>(tc, ret, state);
    return ret;
}

template <typename ABI, bool store_ret, typename Ret>
static typename std::enable_if_t<!std::is_void<Ret>::value && !store_ret, Ret>
callFrom(ThreadContext *tc, typename ABI::State &state,
        std::function<Ret(ThreadContext *)> target)
{
    return target(tc);
}

// With no arguments to gather and nothing to return, call the target function.
template <typename ABI>
static void
callFrom(ThreadContext *tc, typename ABI::State &state,
        std::function<void(ThreadContext *)> target)
{
    target(tc);
}

// Recursively gather arguments for target from tc until we get to the base
// case above.
template <typename ABI, bool store_ret, typename Ret,
          typename NextArg, typename ...Args>
static typename std::enable_if_t<!std::is_void<Ret>::value, Ret>
callFrom(ThreadContext *tc, typename ABI::State &state,
        std::function<Ret(ThreadContext *, NextArg, Args...)> target)
{
    // Extract the next argument from the thread context.
    NextArg next = getArgument<ABI, NextArg>(tc, state);

    // Build a partial function which adds the next argument to the call.
    std::function<Ret(ThreadContext *, Args...)> partial =
        [target,next](ThreadContext *_tc, Args... args) {
            return target(_tc, next, args...);
        };

    // Recursively handle any remaining arguments.
    return callFrom<ABI, store_ret, Ret, Args...>(tc, state, partial);
}

// Recursively gather arguments for target from tc until we get to the base
// case above. This version is for functions that don't return anything.
template <typename ABI, typename NextArg, typename ...Args>
static void
callFrom(ThreadContext *tc, typename ABI::State &state,
        std::function<void(ThreadContext *, NextArg, Args...)> target)
{
    // Extract the next argument from the thread context.
    NextArg next = getArgument<ABI, NextArg>(tc, state);

    // Build a partial function which adds the next argument to the call.
    std::function<void(ThreadContext *, Args...)> partial =
        [target,next](ThreadContext *_tc, Args... args) {
            target(_tc, next, args...);
        };

    // Recursively handle any remaining arguments.
    callFrom<ABI, Args...>(tc, state, partial);
}



/*
 * These functions are like the ones above, except they print the arguments
 * a target function would be called with instead of actually calling it.
 */

// With no arguments to print, add the closing parenthesis and return.
template <typename ABI, typename Ret>
static void
dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
             typename ABI::State &state)
{
    os << ")";
}

// Recursively gather arguments for target from tc until we get to the base
// case above, and append those arguments to the string stream being
// constructed.
template <typename ABI, typename Ret, typename NextArg, typename ...Args>
static void
dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc,
             typename ABI::State &state)
{
    // Either open the parenthesis or add a comma, depending on where we are
    // in the argument list.
    os << (count ? ", " : "(");

    // Extract the next argument from the thread context.
    NextArg next = getArgument<ABI, NextArg>(tc, state);

    // Add this argument to the list.
    os << next;

    // Recursively handle any remaining arguments.
    dumpArgsFrom<ABI, Ret, Args...>(count + 1, os, tc, state);
}

} // namespace GuestABI

#endif // __SIM_GUEST_ABI_DISPATCH_HH__
