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:
Gabe Black
2021-02-02 20:17:36 -08:00
parent 1055e187cc
commit c1ec1c2aba
5 changed files with 17 additions and 5 deletions

View File

@@ -44,6 +44,8 @@ class ThreadContext;
struct Aapcs64
{
using UintPtr = uint64_t;
struct State
{
int ngrn=0; // Next general purpose register number.

View File

@@ -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:

View File

@@ -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);
}
};

View File

@@ -465,6 +465,7 @@ TEST(ProxyPtr, NonConstOperators)
struct TestABI
{
using UintPtr = uint64_t;
using State = int;
};

View File

@@ -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;