diff --git a/src/sim/guest_abi.hh b/src/sim/guest_abi.hh index ea3325f6a2..75c4e00268 100644 --- a/src/sim/guest_abi.hh +++ b/src/sim/guest_abi.hh @@ -51,7 +51,7 @@ invokeSimcall(ThreadContext *tc, // types will be zero initialized. auto state = GuestABI::initializeState(tc); GuestABI::prepareForFunction(tc, state); - return GuestABI::callFrom(tc, state, target); + return GuestABI::callFrom(tc, state, target); } template @@ -86,7 +86,7 @@ invokeSimcall(ThreadContext *tc, // types will be zero initialized. auto state = GuestABI::initializeState(tc); GuestABI::prepareForArguments(tc, state); - GuestABI::callFrom(tc, state, target); + GuestABI::callFrom(tc, state, target); } template @@ -113,7 +113,7 @@ dumpSimcall(std::string name, ThreadContext *tc, GuestABI::prepareForFunction(tc, state); ss << name; - GuestABI::dumpArgsFrom(0, ss, tc, state); + GuestABI::dumpArgsFrom(ss, tc, state); return ss.str(); } diff --git a/src/sim/guest_abi/dispatch.hh b/src/sim/guest_abi/dispatch.hh index bc365b9796..8f3a4ac036 100644 --- a/src/sim/guest_abi/dispatch.hh +++ b/src/sim/guest_abi/dispatch.hh @@ -30,8 +30,11 @@ #include #include +#include #include +#include +#include "base/compiler.hh" #include "sim/guest_abi/definition.hh" #include "sim/guest_abi/layout.hh" @@ -50,114 +53,60 @@ namespace GuestABI * still possible to support by redefining these functions.. */ -// With no arguments to gather, call the target function and store the -// result. -template -static typename std::enable_if_t::value && store_ret, Ret> -callFrom(ThreadContext *tc, typename ABI::State &state, - std::function target) +template +static inline typename std::enable_if_t +callFromHelper(Target &target, ThreadContext *tc, State &state, Args &&args, + std::index_sequence) { - Ret ret = target(tc); + return target(tc, std::get(args)...); +} + +template +static inline typename std::enable_if_t +callFromHelper(Target &target, ThreadContext *tc, State &state, Args &&args, + std::index_sequence) +{ + Ret ret = target(tc, std::get(args)...); storeResult(tc, ret, state); return ret; } -template -static typename std::enable_if_t::value && !store_ret, Ret> +template +static inline Ret callFrom(ThreadContext *tc, typename ABI::State &state, - std::function target) + std::function target) { - return target(tc); + // Extract all the arguments from the thread context. Braced initializers + // are evaluated from left to right. + auto args = std::tuple{getArgument(tc, state)...}; + + // Call the wrapper which will call target. + return callFromHelper( + target, tc, state, std::move(args), + std::make_index_sequence{}); } -// With no arguments to gather and nothing to return, call the target function. -template -static void -callFrom(ThreadContext *tc, typename ABI::State &state, - std::function target) -{ - target(tc); -} - -// Recursively gather arguments for target from tc until we get to the base -// case above. -template -static typename std::enable_if_t::value, Ret> -callFrom(ThreadContext *tc, typename ABI::State &state, - std::function target) -{ - // Extract the next argument from the thread context. - NextArg next = getArgument(tc, state); - - // Build a partial function which adds the next argument to the call. - std::function partial = - [target,next](ThreadContext *_tc, Args... args) { - return target(_tc, next, args...); - }; - - // Recursively handle any remaining arguments. - return callFrom(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 -static void -callFrom(ThreadContext *tc, typename ABI::State &state, - std::function target) -{ - // Extract the next argument from the thread context. - NextArg next = getArgument(tc, state); - - // Build a partial function which adds the next argument to the call. - std::function partial = - [target,next](ThreadContext *_tc, Args... args) { - target(_tc, next, args...); - }; - - // Recursively handle any remaining arguments. - callFrom(tc, state, partial); -} - - /* - * These functions are like the ones above, except they print the arguments + * This function is like the ones above, except it prints 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 +template static void -dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc, - typename ABI::State &state) +dumpArgsFrom(std::ostream &os, M5_VAR_USED ThreadContext *tc, + typename ABI::State &state) { + int count = 0; + // Extract all the arguments from the thread context and print them, + // prefixed with either a ( or a , as appropriate. + M5_FOR_EACH_IN_PACK(os << (count++ ? ", " : "("), + os << getArgument(tc, 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 -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(tc, state); - - // Add this argument to the list. - os << next; - - // Recursively handle any remaining arguments. - dumpArgsFrom(count + 1, os, tc, state); -} - } // namespace GuestABI #endif // __SIM_GUEST_ABI_DISPATCH_HH__ diff --git a/src/sim/guest_abi/layout.hh b/src/sim/guest_abi/layout.hh index bb46d62070..6de04703e8 100644 --- a/src/sim/guest_abi/layout.hh +++ b/src/sim/guest_abi/layout.hh @@ -30,6 +30,7 @@ #include +#include "base/compiler.hh" #include "sim/guest_abi/definition.hh" class ThreadContext; @@ -100,29 +101,21 @@ struct Preparer::prepare)> }; template -static void +static inline void prepareForResult(ThreadContext *tc, typename ABI::State &state) { Preparer::prepare(tc, state); } -template -static void -prepareForArguments(ThreadContext *tc, typename ABI::State &state) +template +static inline void +prepareForArguments(M5_VAR_USED ThreadContext *tc, typename ABI::State &state) { - return; -} - -template -static void -prepareForArguments(ThreadContext *tc, typename ABI::State &state) -{ - Preparer::prepare(tc, state); - prepareForArguments(tc, state); + M5_FOR_EACH_IN_PACK(Preparer::prepare(tc, state)); } template -static void +static inline void prepareForFunction(ThreadContext *tc, typename ABI::State &state) { prepareForResult(tc, state); @@ -144,12 +137,6 @@ struct ResultStorer } }; -template -std::true_type foo(void (*)(ThreadContext *, const Ret &ret, State &state)); - -template -std::false_type foo(void (*)(ThreadContext *, const Ret &ret)); - template struct ResultStorer