sim: Rename allocate in GuestABI to prepare.
This method can be used for allocating resources for registers and/or arguments, but it can also be used for generic preparation for them as well. For instance, it can be used to detect some sort of property of the function signature as a whole (if it's variadic for instance) which can be stored in position and used to change ABI behavior. Change-Id: I8a090be65dc4987e35cd115562114cd1b748155f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24106 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -50,7 +50,7 @@ invokeSimcall(ThreadContext *tc,
|
||||
// Default construct a Position to track consumed resources. Built in
|
||||
// types will be zero initialized.
|
||||
auto position = GuestABI::initializePosition<ABI>(tc);
|
||||
GuestABI::allocateSignature<ABI, Ret, Args...>(tc, position);
|
||||
GuestABI::prepareForFunction<ABI, Ret, Args...>(tc, position);
|
||||
return GuestABI::callFrom<ABI, Ret, Args...>(tc, position, target);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ invokeSimcall(ThreadContext *tc,
|
||||
// Default construct a Position to track consumed resources. Built in
|
||||
// types will be zero initialized.
|
||||
auto position = GuestABI::initializePosition<ABI>(tc);
|
||||
GuestABI::allocateArguments<ABI, Args...>(tc, position);
|
||||
GuestABI::prepareForArguments<ABI, Args...>(tc, position);
|
||||
GuestABI::callFrom<ABI, Args...>(tc, position, target);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ dumpSimcall(std::string name, ThreadContext *tc,
|
||||
auto position = GuestABI::initializePosition<ABI>(tc);
|
||||
std::ostringstream ss;
|
||||
|
||||
GuestABI::allocateSignature<ABI, Ret, Args...>(tc, position);
|
||||
GuestABI::prepareForFunction<ABI, Ret, Args...>(tc, position);
|
||||
ss << name;
|
||||
GuestABI::dumpArgsFrom<ABI, Ret, Args...>(0, ss, tc, position);
|
||||
return ss.str();
|
||||
|
||||
@@ -66,8 +66,8 @@ struct TestABI_1D
|
||||
using Position = int;
|
||||
};
|
||||
|
||||
// ABI anchor for an ABI which uses the allocate() hook.
|
||||
struct TestABI_Allocate
|
||||
// ABI anchor for an ABI which uses the prepare() hook.
|
||||
struct TestABI_Prepare
|
||||
{
|
||||
using Position = int;
|
||||
};
|
||||
@@ -136,31 +136,31 @@ struct Result<TestABI_1D, Ret,
|
||||
}
|
||||
};
|
||||
|
||||
// Hooks for the ABI which uses allocate(). It uses the same rules as the
|
||||
// Hooks for the ABI which uses prepare(). It uses the same rules as the
|
||||
// 1D ABI for arguments, but allocates space for and discards return values
|
||||
// and returns integer arguments in reverse order.
|
||||
template <>
|
||||
struct Argument<TestABI_Allocate, int>
|
||||
struct Argument<TestABI_Prepare, int>
|
||||
{
|
||||
static int
|
||||
get(ThreadContext *tc, TestABI_Allocate::Position &position)
|
||||
get(ThreadContext *tc, TestABI_Prepare::Position &position)
|
||||
{
|
||||
return tc->ints[--position];
|
||||
}
|
||||
|
||||
static void
|
||||
allocate(ThreadContext *tc, TestABI_Allocate::Position &position)
|
||||
prepare(ThreadContext *tc, TestABI_Prepare::Position &position)
|
||||
{
|
||||
position++;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Ret>
|
||||
struct Result<TestABI_Allocate, Ret>
|
||||
struct Result<TestABI_Prepare, Ret>
|
||||
{
|
||||
static void store(ThreadContext *tc, const Ret &ret) {}
|
||||
static void
|
||||
allocate(ThreadContext *tc, TestABI_Allocate::Position &position)
|
||||
prepare(ThreadContext *tc, TestABI_Prepare::Position &position)
|
||||
{
|
||||
position++;
|
||||
}
|
||||
@@ -243,14 +243,14 @@ testIntVoid(ThreadContext *tc, int a, float b, int c, double d,
|
||||
// Test functions which verify that the return allocating ABI allocates space
|
||||
// for its return value successfully.
|
||||
void
|
||||
testAllocateVoid(ThreadContext *tc, int a, int b)
|
||||
testPrepareVoid(ThreadContext *tc, int a, int b)
|
||||
{
|
||||
EXPECT_EQ(a, tc->ints[1]);
|
||||
EXPECT_EQ(b, tc->ints[0]);
|
||||
}
|
||||
|
||||
int
|
||||
testAllocateInt(ThreadContext *tc, int a, int b)
|
||||
testPrepareInt(ThreadContext *tc, int a, int b)
|
||||
{
|
||||
EXPECT_EQ(a, tc->ints[2]);
|
||||
EXPECT_EQ(b, tc->ints[1]);
|
||||
@@ -299,11 +299,11 @@ TEST(GuestABI, ABI_1D_args)
|
||||
EXPECT_EQ(tc.floatResult, tc.DefaultFloatResult);
|
||||
}
|
||||
|
||||
TEST(GuestABI, ABI_Allocate)
|
||||
TEST(GuestABI, ABI_Prepare)
|
||||
{
|
||||
ThreadContext tc;
|
||||
invokeSimcall<TestABI_Allocate>(&tc, testAllocateVoid);
|
||||
invokeSimcall<TestABI_Allocate>(&tc, testAllocateInt);
|
||||
invokeSimcall<TestABI_Prepare>(&tc, testPrepareVoid);
|
||||
invokeSimcall<TestABI_Prepare>(&tc, testPrepareInt);
|
||||
}
|
||||
|
||||
TEST(GuestABI, ABI_2D_args)
|
||||
|
||||
@@ -72,11 +72,12 @@ struct Result
|
||||
typename ABI::Position &position);
|
||||
|
||||
/*
|
||||
* Adjust the position of arguments based on the return type, if necessary.
|
||||
* Prepare for a result of type Ret. This might mean, for instance,
|
||||
* allocating an argument register for a result pointer.
|
||||
*
|
||||
* This method can be excluded if no adjustment is necessary.
|
||||
* This method can be excluded if no preparation is necessary.
|
||||
*/
|
||||
static void allocate(ThreadContext *tc, typename ABI::Position &position);
|
||||
static void prepare(ThreadContext *tc, typename ABI::Position &position);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -101,10 +102,10 @@ struct Argument
|
||||
static Arg get(ThreadContext *tc, typename ABI::Position &position);
|
||||
|
||||
/*
|
||||
* Adjust the position of arguments based on the argument type, if
|
||||
* necessary.
|
||||
* Prepare for an argument of type Arg. This might mean, for instance,
|
||||
* allocating an argument register for a result pointer.
|
||||
*
|
||||
* This method can be excluded if no adjustment is necessary.
|
||||
* This method can be excluded if no preparation is necessary.
|
||||
*/
|
||||
static void allocate(ThreadContext *tc, typename ABI::Position &position);
|
||||
};
|
||||
|
||||
@@ -71,63 +71,63 @@ initializePosition(const ThreadContext *tc)
|
||||
}
|
||||
|
||||
/*
|
||||
* This struct template provides a default allocate() method in case the
|
||||
* This struct template provides a default prepare() method in case the
|
||||
* Result or Argument template doesn't provide one. This is the default in
|
||||
* cases where the return or argument type doesn't affect where things are
|
||||
* stored.
|
||||
*/
|
||||
template <typename ABI, template <class ...> class Role,
|
||||
typename Type, typename Enabled=void>
|
||||
struct Allocator
|
||||
struct Preparer
|
||||
{
|
||||
static void
|
||||
allocate(ThreadContext *tc, typename ABI::Position &position)
|
||||
prepare(ThreadContext *tc, typename ABI::Position &position)
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* If the return or argument type isn't void and does affect where things
|
||||
* are stored, the ABI can implement an allocate() method for the various
|
||||
* are stored, the ABI can implement a prepare() method for the various
|
||||
* argument and/or return types, and this specialization will call into it.
|
||||
*/
|
||||
template <typename ABI, template <class ...> class Role, typename Type>
|
||||
struct Allocator<ABI, Role, Type, decltype((void)&Role<ABI, Type>::allocate)>
|
||||
struct Preparer<ABI, Role, Type, decltype((void)&Role<ABI, Type>::prepare)>
|
||||
{
|
||||
static void
|
||||
allocate(ThreadContext *tc, typename ABI::Position &position)
|
||||
prepare(ThreadContext *tc, typename ABI::Position &position)
|
||||
{
|
||||
Role<ABI, Type>::allocate(tc, position);
|
||||
Role<ABI, Type>::prepare(tc, position);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ABI, typename Ret, typename Enabled=void>
|
||||
static void
|
||||
allocateResult(ThreadContext *tc, typename ABI::Position &position)
|
||||
prepareForResult(ThreadContext *tc, typename ABI::Position &position)
|
||||
{
|
||||
Allocator<ABI, Result, Ret>::allocate(tc, position);
|
||||
Preparer<ABI, Result, Ret>::prepare(tc, position);
|
||||
}
|
||||
|
||||
template <typename ABI>
|
||||
static void
|
||||
allocateArguments(ThreadContext *tc, typename ABI::Position &position)
|
||||
prepareForArguments(ThreadContext *tc, typename ABI::Position &position)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename ABI, typename NextArg, typename ...Args>
|
||||
static void
|
||||
allocateArguments(ThreadContext *tc, typename ABI::Position &position)
|
||||
prepareForArguments(ThreadContext *tc, typename ABI::Position &position)
|
||||
{
|
||||
Allocator<ABI, Argument, NextArg>::allocate(tc, position);
|
||||
allocateArguments<ABI, Args...>(tc, position);
|
||||
Preparer<ABI, Argument, NextArg>::prepare(tc, position);
|
||||
prepareForArguments<ABI, Args...>(tc, position);
|
||||
}
|
||||
|
||||
template <typename ABI, typename Ret, typename ...Args>
|
||||
static void
|
||||
allocateSignature(ThreadContext *tc, typename ABI::Position &position)
|
||||
prepareForFunction(ThreadContext *tc, typename ABI::Position &position)
|
||||
{
|
||||
allocateResult<ABI, Ret>(tc, position);
|
||||
allocateArguments<ABI, Args...>(tc, position);
|
||||
prepareForResult<ABI, Ret>(tc, position);
|
||||
prepareForArguments<ABI, Args...>(tc, position);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user