sim: Add a dumpSimcall mechanism to GuestABI.
This dumps a signature for a simcall as if it was going to be invoked, and can be used for debugging. Change-Id: I6262b94ad4186bac8dc5a1469e9bb3b8ae9d34e1 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23460 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Jason Lowe-Power <jason@lowepower.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
class ThreadContext;
|
||||
@@ -213,6 +214,14 @@ class VarArgs
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ...Types>
|
||||
std::ostream &
|
||||
operator << (std::ostream &os, const VarArgs<Types...> &va)
|
||||
{
|
||||
os << "...";
|
||||
return os;
|
||||
}
|
||||
|
||||
// The ABI independent hook which tells the GuestABI mechanism what to do with
|
||||
// a VarArgs argument. It constructs the underlying implementation which knows
|
||||
// about the ABI, and installs it in the VarArgs wrapper to give to the
|
||||
@@ -301,6 +310,44 @@ callFrom(ThreadContext *tc, typename ABI::Position &position,
|
||||
callFrom<ABI, Args...>(tc, position, 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::Position &position)
|
||||
{
|
||||
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::Position &position)
|
||||
{
|
||||
// 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 = Argument<ABI, NextArg>::get(tc, position);
|
||||
|
||||
// Add this argument to the list.
|
||||
os << next;
|
||||
|
||||
// Recursively handle any remaining arguments.
|
||||
dumpArgsFrom<ABI, Ret, Args...>(count + 1, os, tc, position);
|
||||
}
|
||||
|
||||
} // namespace GuestABI
|
||||
|
||||
|
||||
@@ -347,4 +394,32 @@ invokeSimcall(ThreadContext *tc, void (*target)(ThreadContext *, Args...))
|
||||
tc, std::function<void(ThreadContext *, Args...)>(target));
|
||||
}
|
||||
|
||||
|
||||
// These functions also wrap a simulator level function. Instead of running the
|
||||
// function, they return a string which shows what arguments the function would
|
||||
// be invoked with if it were called from the given context.
|
||||
|
||||
template <typename ABI, typename Ret, typename ...Args>
|
||||
std::string
|
||||
dumpSimcall(std::string name, ThreadContext *tc,
|
||||
std::function<Ret(ThreadContext *, Args...)> target=
|
||||
std::function<Ret(ThreadContext *, Args...)>())
|
||||
{
|
||||
auto position = typename ABI::Position();
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << name;
|
||||
GuestABI::dumpArgsFrom<ABI, Ret, Args...>(0, ss, tc, position);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename ABI, typename Ret, typename ...Args>
|
||||
std::string
|
||||
dumpSimcall(std::string name, ThreadContext *tc,
|
||||
Ret (*target)(ThreadContext *, Args...))
|
||||
{
|
||||
return dumpSimcall<ABI>(
|
||||
name, tc, std::function<Ret(ThreadContext *, Args...)>(target));
|
||||
}
|
||||
|
||||
#endif // __SIM_GUEST_ABI_HH__
|
||||
|
||||
@@ -275,3 +275,10 @@ TEST(GuestABI, ABI_returns)
|
||||
EXPECT_EQ(tc.floatResult, DoubleRetValue + 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GuestABI, dumpSimcall)
|
||||
{
|
||||
ThreadContext tc;
|
||||
std::string dump = dumpSimcall<TestABI_1D>("test", &tc, testIntVoid);
|
||||
EXPECT_EQ(dump, "test(0, 11, 2, 13, ...)");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user