sim: Use type_traits to steer swap_bytes.

Rather than have a function with a if which checks against each
supported size of a type T which calls the right version of
swap_bytesNN, this change uses SFINAE and type traits to select the
function, and adds the requirement that the type being swapped is
actually convertible to the unsigned integer type of the appropriate
size.

This has the nice benefit of also avoiding hard coding which sizes can
be supported by the base swap_bytes, although that's probably not much a
limit in practice, avoids forcing all types to be convertible to all
sizes of uint*_ts for unused branches of the if, and removes a
dependence on base/logging.hh for the panic.

Change-Id: I2267f69a2868fcba2318c7562a49d27fef785395
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45286
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-05-10 05:29:49 -07:00
parent 00caced648
commit eef05e8821

View File

@@ -33,7 +33,6 @@
#ifndef __SIM_BYTE_SWAP_HH__
#define __SIM_BYTE_SWAP_HH__
#include "base/logging.hh"
#include "base/types.hh"
#include "enums/ByteOrder.hh"
@@ -54,8 +53,10 @@
#include <libkern/OSByteOrder.h>
#endif
//These functions actually perform the swapping for parameters
//of various bit lengths
#include <type_traits>
// These functions actually perform the swapping for parameters of various bit
// lengths.
inline uint64_t
swap_byte64(uint64_t x)
{
@@ -102,22 +103,36 @@ swap_byte16(uint16_t x)
#endif
}
// This function lets the compiler figure out how to call the
// swap_byte functions above for different data types. Since the
// sizeof() values are known at compile time, it should inline to a
// direct call to the right swap_byteNN() function.
template <typename T>
inline T swap_byte(T x) {
if (sizeof(T) == 8)
return swap_byte64((uint64_t)x);
else if (sizeof(T) == 4)
return swap_byte32((uint32_t)x);
else if (sizeof(T) == 2)
return swap_byte16((uint16_t)x);
else if (sizeof(T) == 1)
return x;
else
panic("Can't byte-swap values larger than 64 bits");
inline std::enable_if_t<
sizeof(T) == 8 && std::is_convertible<T, uint64_t>::value, T>
swap_byte(T x)
{
return swap_byte64((uint64_t)x);
}
template <typename T>
inline std::enable_if_t<
sizeof(T) == 4 && std::is_convertible<T, uint32_t>::value, T>
swap_byte(T x)
{
return swap_byte32((uint32_t)x);
}
template <typename T>
inline std::enable_if_t<
sizeof(T) == 2 && std::is_convertible<T, uint16_t>::value, T>
swap_byte(T x)
{
return swap_byte16((uint16_t)x);
}
template <typename T>
inline std::enable_if_t<
sizeof(T) == 1 && std::is_convertible<T, uint8_t>::value, T>
swap_byte(T x)
{
return x;
}
template <typename T, size_t N>