arch,sim: Add a UintPtr type to the ABI types for GuestABI.
This type is primarily used to determine the size of a pointer when using that ABI, similar to the uintptr_t type, but also less directly to determine the "native" size of the ABI. For instance, for 32 bit ARM ABIs, it should be defined as uint32_t since that's both the size of a uintptr_t, and, less directly, the size of a 32 bit ARM register and "naturally" sized types in that ABI. This type can be used by the VPtr template to retrieve its actual value from a simcall's parameters. In general, when accepting or returning a pointer or address in a simcall, the VPtr template should be used so that it's managed correctly by GuestABI. Addr will be treated as a uint64_t allways which will be incorrect for 32 bit ABIs. Change-Id: I3af046917387541d6faff96a21a1f1dbf7317e06 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40496 Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
This commit is contained in:
@@ -44,6 +44,8 @@ class ThreadContext;
|
||||
|
||||
struct Aapcs64
|
||||
{
|
||||
using UintPtr = uint64_t;
|
||||
|
||||
struct State
|
||||
{
|
||||
int ngrn=0; // Next general purpose register number.
|
||||
|
||||
@@ -133,6 +133,8 @@ class ArmSemihosting : public SimObject
|
||||
|
||||
struct Abi64 : public AbiBase
|
||||
{
|
||||
using UintPtr = uint64_t;
|
||||
|
||||
class State : public StateBase<uint64_t>
|
||||
{
|
||||
public:
|
||||
@@ -145,6 +147,8 @@ class ArmSemihosting : public SimObject
|
||||
|
||||
struct Abi32 : public AbiBase
|
||||
{
|
||||
using UintPtr = uint32_t;
|
||||
|
||||
class State : public StateBase<uint64_t>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -338,7 +338,8 @@ struct Argument<ABI, ProxyPtr<T, Proxy>>
|
||||
static ProxyPtr<T, Proxy>
|
||||
get(ThreadContext *tc, typename ABI::State &state)
|
||||
{
|
||||
return ProxyPtr<T, Proxy>(Argument<ABI, Addr>::get(tc, state), tc);
|
||||
return ProxyPtr<T, Proxy>(
|
||||
Argument<ABI, typename ABI::UintPtr>::get(tc, state), tc);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -349,7 +350,7 @@ struct Argument<ABI, ConstProxyPtr<T, Proxy>>
|
||||
get(ThreadContext *tc, typename ABI::State &state)
|
||||
{
|
||||
return ConstProxyPtr<T, Proxy>(
|
||||
Argument<ABI, Addr>::get(tc, state), tc);
|
||||
Argument<ABI, typename ABI::UintPtr>::get(tc, state), tc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -465,6 +465,7 @@ TEST(ProxyPtr, NonConstOperators)
|
||||
|
||||
struct TestABI
|
||||
{
|
||||
using UintPtr = uint64_t;
|
||||
using State = int;
|
||||
};
|
||||
|
||||
|
||||
@@ -54,10 +54,14 @@ struct GenericSyscallABI
|
||||
};
|
||||
|
||||
struct GenericSyscallABI64 : public GenericSyscallABI
|
||||
{};
|
||||
{
|
||||
using UintPtr = uint64_t;
|
||||
};
|
||||
|
||||
struct GenericSyscallABI32 : public GenericSyscallABI
|
||||
{
|
||||
using UintPtr = uint32_t;
|
||||
|
||||
// Is this argument too big for a single register?
|
||||
template <typename T, typename Enabled=void>
|
||||
struct IsWide;
|
||||
@@ -65,7 +69,7 @@ struct GenericSyscallABI32 : public GenericSyscallABI
|
||||
template <typename T>
|
||||
struct IsWide<T, typename std::enable_if_t<
|
||||
std::is_integral<T>::value &&
|
||||
(sizeof(T) < sizeof(uint64_t) ||
|
||||
(sizeof(T) <= sizeof(UintPtr) ||
|
||||
GuestABI::IsConforming<T>::value)>>
|
||||
{
|
||||
static const bool value = false;
|
||||
@@ -74,7 +78,7 @@ struct GenericSyscallABI32 : public GenericSyscallABI
|
||||
template <typename T>
|
||||
struct IsWide<T, typename std::enable_if_t<
|
||||
std::is_integral<T>::value &&
|
||||
sizeof(T) == sizeof(uint64_t) &&
|
||||
(sizeof(T) > sizeof(UintPtr)) &&
|
||||
!GuestABI::IsConforming<T>::value>>
|
||||
{
|
||||
static const bool value = true;
|
||||
|
||||
Reference in New Issue
Block a user