diff options
author | 2020-01-24 14:42:03 +0000 | |
---|---|---|
committer | 2020-01-31 09:20:45 +0000 | |
commit | e4207a7bf5b008df97b76b6df7a9930524c4c1cb (patch) | |
tree | e8ebf130a1ced48fd228d8e9f80ceb1e137fd9e0 /libartbase/base/bit_struct.h | |
parent | 299141a330adc3bff3fdfaa54baf9e6d681507aa (diff) |
Use consistent storage type in bit structs.
Propagate the storage type from the enclosing union to each
individual field when it is defined by provided macros.
Test: m test-art-host-gtest
Bug: 148125232
Change-Id: I6976c4e7668d62f500ee1a413a30e02bc8b68cea
Diffstat (limited to 'libartbase/base/bit_struct.h')
-rw-r--r-- | libartbase/base/bit_struct.h | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/libartbase/base/bit_struct.h b/libartbase/base/bit_struct.h index 277e4b52e3..eca8780568 100644 --- a/libartbase/base/bit_struct.h +++ b/libartbase/base/bit_struct.h @@ -32,9 +32,9 @@ // // // Definition for type 'Example' // BITSTRUCT_DEFINE_START(Example, 10) -// BitStructUint<0, 2> u2; // Every field must be a BitStruct[*]. -// BitStructInt<2, 7> i7; -// BitStructUint<9, 1> i1; +// BITSTRUCT_UINT(0, 2) u2; // Every field must be a BitStruct[*] with the same StorageType, +// BITSTRUCT_INT(2, 7) i7; // preferably using BITSTRUCT_{FIELD,UINT,INT} +// BITSTRUCT_UINT(9, 1) i1; // to fill in the StorageType parameter. // BITSTRUCT_DEFINE_END(Example); // // Would define a bit struct with this layout: @@ -109,8 +109,8 @@ namespace art { // of T can be represented by kBitWidth. template <typename T, size_t kBitOffset, - size_t kBitWidth = BitStructSizeOf<T>(), - typename StorageType = typename detail::MinimumTypeUnsignedHelper<kBitOffset + kBitWidth>::type> + size_t kBitWidth, + typename StorageType> struct BitStructField { static_assert(std::is_standard_layout<T>::value, "T must be standard layout"); @@ -186,10 +186,8 @@ struct BitStructField { // // (Common usage should be BitStructInt, BitStructUint -- this // intermediate template allows a user-defined integer to be used.) -template <typename T, size_t kBitOffset, size_t kBitWidth> -struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T> { - using StorageType = T; - +template <typename T, size_t kBitOffset, size_t kBitWidth, typename StorageType> +struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, StorageType> { BitStructNumber& operator=(T value) { return BaseType::Assign(*this, value); } @@ -221,7 +219,7 @@ struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, /*Stora } private: - using BaseType = BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T>; + using BaseType = BitStructField<T, kBitOffset, kBitWidth, StorageType>; using BaseType::Get; }; @@ -229,21 +227,23 @@ struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, /*Stora // in order to be large enough to fit (kBitOffset + kBitWidth). // // Values are sign-extended when they are read out. -template <size_t kBitOffset, size_t kBitWidth> +template <size_t kBitOffset, size_t kBitWidth, typename StorageType> using BitStructInt = BitStructNumber<typename detail::MinimumTypeHelper<int, kBitOffset + kBitWidth>::type, kBitOffset, - kBitWidth>; + kBitWidth, + StorageType>; // Create a BitStruct field which uses the smallest underlying uint storage type, // in order to be large enough to fit (kBitOffset + kBitWidth). // // Values are zero-extended when they are read out. -template <size_t kBitOffset, size_t kBitWidth> +template <size_t kBitOffset, size_t kBitWidth, typename StorageType> using BitStructUint = BitStructNumber<typename detail::MinimumTypeHelper<unsigned int, kBitOffset + kBitWidth>::type, kBitOffset, - kBitWidth>; + kBitWidth, + StorageType>; // Start a definition for a bitstruct. // A bitstruct is defined to be a union with a common initial subsequence @@ -260,6 +260,8 @@ using BitStructUint = // standard-layout struct members. #define BITSTRUCT_DEFINE_START(name, bitwidth) \ union name { /* NOLINT */ \ + using StorageType = \ + typename detail::MinimumTypeUnsignedHelper<(bitwidth)>::type; \ art::detail::DefineBitStructSize<(bitwidth)> _; \ static constexpr size_t BitStructSizeOf() { return (bitwidth); } \ name& operator=(const name& other) { _ = other._; return *this; } /* NOLINT */ \ @@ -267,6 +269,14 @@ using BitStructUint = name() = default; \ ~name() = default; +// Define a field. See top of file for usage example. +#define BITSTRUCT_FIELD(type, bit_offset, bit_width) \ + BitStructField<type, (bit_offset), (bit_width), StorageType> +#define BITSTRUCT_INT(bit_offset, bit_width) \ + BitStructInt<(bit_offset), (bit_width), StorageType> +#define BITSTRUCT_UINT(bit_offset, bit_width) \ + BitStructUint<(bit_offset), (bit_width), StorageType> + // End the definition of a bitstruct, and insert a sanity check // to ensure that the bitstruct did not exceed the specified size. // |