sim: Make it possible for a GuestABI to init its Position based on a TC.
It may be necessary to initialize the GuestABI Position type based on the current state of the thread, for instance by reading the current stack pointer. This change makes it possible (but not mandantory) for an ABI to supply a constructor for Position which accepts a ThreadContext * which it can use to intiialize itself. Change-Id: I5609b185f746368c5f9eb2a04074dcafa088f925 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23749 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -61,6 +61,32 @@ namespace GuestABI
|
||||
* std::enable_if style conditional specializations.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Position may need to be initialized based on the ThreadContext, for instance
|
||||
* to find out where the stack pointer is initially.
|
||||
*/
|
||||
template <typename ABI, typename Enabled=void>
|
||||
struct PositionInitializer
|
||||
{
|
||||
static typename ABI::Position
|
||||
init(const ThreadContext *tc)
|
||||
{
|
||||
return typename ABI::Position();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ABI>
|
||||
struct PositionInitializer<ABI, typename std::enable_if<
|
||||
std::is_constructible<typename ABI::Position, const ThreadContext *>::value
|
||||
>::type>
|
||||
{
|
||||
static typename ABI::Position
|
||||
init(const ThreadContext *tc)
|
||||
{
|
||||
return typename ABI::Position(tc);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ABI, typename Ret, typename Enabled=void>
|
||||
struct Result
|
||||
{
|
||||
@@ -407,7 +433,7 @@ invokeSimcall(ThreadContext *tc,
|
||||
{
|
||||
// Default construct a Position to track consumed resources. Built in
|
||||
// types will be zero initialized.
|
||||
auto position = typename ABI::Position();
|
||||
auto position = GuestABI::PositionInitializer<ABI>::init(tc);
|
||||
GuestABI::ResultAllocator<ABI, Ret>::allocate(tc, position);
|
||||
return GuestABI::callFrom<ABI, Ret, Args...>(tc, position, target);
|
||||
}
|
||||
@@ -427,7 +453,7 @@ invokeSimcall(ThreadContext *tc,
|
||||
{
|
||||
// Default construct a Position to track consumed resources. Built in
|
||||
// types will be zero initialized.
|
||||
auto position = typename ABI::Position();
|
||||
auto position = GuestABI::PositionInitializer<ABI>::init(tc);
|
||||
GuestABI::callFrom<ABI, Args...>(tc, position, target);
|
||||
}
|
||||
|
||||
@@ -450,7 +476,7 @@ dumpSimcall(std::string name, ThreadContext *tc,
|
||||
std::function<Ret(ThreadContext *, Args...)> target=
|
||||
std::function<Ret(ThreadContext *, Args...)>())
|
||||
{
|
||||
auto position = typename ABI::Position();
|
||||
auto position = GuestABI::PositionInitializer<ABI>::init(tc);
|
||||
std::ostringstream ss;
|
||||
|
||||
GuestABI::ResultAllocator<ABI, Ret>::allocate(tc, position);
|
||||
|
||||
@@ -46,6 +46,8 @@ class ThreadContext
|
||||
|
||||
int intResult = DefaultIntResult;
|
||||
double floatResult = DefaultFloatResult;
|
||||
|
||||
int intOffset = 0;
|
||||
};
|
||||
|
||||
const int ThreadContext::ints[] = {
|
||||
@@ -80,6 +82,15 @@ struct TestABI_2D
|
||||
using Position = std::pair<int, int>;
|
||||
};
|
||||
|
||||
struct TestABI_TcInit
|
||||
{
|
||||
struct Position
|
||||
{
|
||||
int pos;
|
||||
Position(const ThreadContext *tc) : pos(tc->intOffset) {}
|
||||
};
|
||||
};
|
||||
|
||||
namespace GuestABI
|
||||
{
|
||||
|
||||
@@ -188,6 +199,17 @@ struct Result<TestABI_2D, Ret,
|
||||
}
|
||||
};
|
||||
|
||||
// Hooks for the TcInit ABI arguments.
|
||||
template <>
|
||||
struct Argument<TestABI_TcInit, int>
|
||||
{
|
||||
static int
|
||||
get(ThreadContext *tc, TestABI_TcInit::Position &position)
|
||||
{
|
||||
return tc->ints[position.pos++];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace GuestABI
|
||||
|
||||
// Test function which verifies that its arguments reflect the 1D ABI and
|
||||
@@ -237,6 +259,13 @@ test2DVoid(ThreadContext *tc, int a, float b, int c, double d,
|
||||
EXPECT_EQ(varargs.get<double>(), tc->floats[3]);
|
||||
}
|
||||
|
||||
void
|
||||
testTcInit(ThreadContext *tc, int a)
|
||||
{
|
||||
EXPECT_EQ(tc->intOffset, 2);
|
||||
EXPECT_EQ(a, tc->ints[2]);
|
||||
}
|
||||
|
||||
// Test functions which returns various types of values.
|
||||
const int IntRetValue = 50;
|
||||
const float FloatRetValue = 3.14;
|
||||
@@ -271,6 +300,13 @@ TEST(GuestABI, ABI_2D_args)
|
||||
EXPECT_EQ(tc.floatResult, tc.DefaultFloatResult);
|
||||
}
|
||||
|
||||
TEST(GuestABI, ABI_TC_init)
|
||||
{
|
||||
ThreadContext tc;
|
||||
tc.intOffset = 2;
|
||||
invokeSimcall<TestABI_TcInit>(&tc, testTcInit);
|
||||
}
|
||||
|
||||
TEST(GuestABI, ABI_returns)
|
||||
{
|
||||
// 1D returns.
|
||||
|
||||
Reference in New Issue
Block a user