From 24be0cc1ce4422dc457648fcb17fa2d609b39752 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 16 Dec 2019 21:28:40 -0800 Subject: [PATCH] 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 Maintainer: Gabe Black Tested-by: kokoro --- src/sim/guest_abi.hh | 32 +++++++++++++++++++++++++++++--- src/sim/guest_abi.test.cc | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/sim/guest_abi.hh b/src/sim/guest_abi.hh index 2dd27c424..5432af3f9 100644 --- a/src/sim/guest_abi.hh +++ b/src/sim/guest_abi.hh @@ -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 +struct PositionInitializer +{ + static typename ABI::Position + init(const ThreadContext *tc) + { + return typename ABI::Position(); + } +}; + +template +struct PositionInitializer::value + >::type> +{ + static typename ABI::Position + init(const ThreadContext *tc) + { + return typename ABI::Position(tc); + } +}; + template 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::init(tc); GuestABI::ResultAllocator::allocate(tc, position); return GuestABI::callFrom(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::init(tc); GuestABI::callFrom(tc, position, target); } @@ -450,7 +476,7 @@ dumpSimcall(std::string name, ThreadContext *tc, std::function target= std::function()) { - auto position = typename ABI::Position(); + auto position = GuestABI::PositionInitializer::init(tc); std::ostringstream ss; GuestABI::ResultAllocator::allocate(tc, position); diff --git a/src/sim/guest_abi.test.cc b/src/sim/guest_abi.test.cc index 2f896f9b3..506163ee6 100644 --- a/src/sim/guest_abi.test.cc +++ b/src/sim/guest_abi.test.cc @@ -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; }; +struct TestABI_TcInit +{ + struct Position + { + int pos; + Position(const ThreadContext *tc) : pos(tc->intOffset) {} + }; +}; + namespace GuestABI { @@ -188,6 +199,17 @@ struct Result +struct Argument +{ + 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(), 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(&tc, testTcInit); +} + TEST(GuestABI, ABI_returns) { // 1D returns. -- 2.30.2