diff --git a/src/sim/guest_abi.hh b/src/sim/guest_abi.hh index 704155b4e5..ea3325f6a2 100644 --- a/src/sim/guest_abi.hh +++ b/src/sim/guest_abi.hh @@ -42,7 +42,7 @@ class ThreadContext; // and write a result (if any) back to. For convenience, the wrapper also // returns the result of the wrapped function. -template +template Ret invokeSimcall(ThreadContext *tc, std::function target) @@ -51,15 +51,30 @@ 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 +Ret +invokeSimcall(ThreadContext *tc, + std::function target) +{ + return invokeSimcall(tc, target); +} + +template +Ret +invokeSimcall(ThreadContext *tc, Ret (*target)(ThreadContext *, Args...)) +{ + return invokeSimcall( + tc, std::function(target)); } template Ret invokeSimcall(ThreadContext *tc, Ret (*target)(ThreadContext *, Args...)) { - return invokeSimcall( - tc, std::function(target)); + return invokeSimcall(tc, target); } template diff --git a/src/sim/guest_abi.test.cc b/src/sim/guest_abi.test.cc index 6b5d0607bd..8edf5d35ac 100644 --- a/src/sim/guest_abi.test.cc +++ b/src/sim/guest_abi.test.cc @@ -345,6 +345,15 @@ TEST(GuestABI, ABI_returns) EXPECT_EQ(tc.intResult, tc.DefaultIntResult); EXPECT_EQ(tc.floatResult, DoubleRetValue + 1.0); } + { + // Disable storing the return value in the ThreadContext. + ThreadContext tc; + int ret = invokeSimcall(&tc, testIntRet); + EXPECT_EQ(ret, IntRetValue); + EXPECT_EQ(tc.intResult, tc.DefaultIntResult); + EXPECT_EQ(tc.floatResult, tc.DefaultFloatResult); + } + // 2D returns. { diff --git a/src/sim/guest_abi/dispatch.hh b/src/sim/guest_abi/dispatch.hh index 62cbf291d2..794fd6280b 100644 --- a/src/sim/guest_abi/dispatch.hh +++ b/src/sim/guest_abi/dispatch.hh @@ -52,8 +52,9 @@ namespace GuestABI // With no arguments to gather, call the target function and store the // result. -template -static typename std::enable_if::value, Ret>::type +template +static typename std::enable_if::value && store_ret, + Ret>::type callFrom(ThreadContext *tc, typename ABI::State &state, std::function target) { @@ -62,6 +63,15 @@ callFrom(ThreadContext *tc, typename ABI::State &state, return ret; } +template +static typename std::enable_if::value && !store_ret, + Ret>::type +callFrom(ThreadContext *tc, typename ABI::State &state, + std::function target) +{ + return target(tc); +} + // With no arguments to gather and nothing to return, call the target function. template static void @@ -73,7 +83,8 @@ callFrom(ThreadContext *tc, typename ABI::State &state, // Recursively gather arguments for target from tc until we get to the base // case above. -template +template static typename std::enable_if::value, Ret>::type callFrom(ThreadContext *tc, typename ABI::State &state, std::function target) @@ -88,7 +99,7 @@ callFrom(ThreadContext *tc, typename ABI::State &state, }; // Recursively handle any remaining arguments. - return callFrom(tc, state, partial); + return callFrom(tc, state, partial); } // Recursively gather arguments for target from tc until we get to the base