From e4207a7bf5b008df97b76b6df7a9930524c4c1cb Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Fri, 24 Jan 2020 14:42:03 +0000 Subject: 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 --- libartbase/base/bit_struct.h | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'libartbase/base/bit_struct.h') 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 StorageType = typename detail::MinimumTypeUnsignedHelper::type> + size_t kBitWidth, + typename StorageType> struct BitStructField { static_assert(std::is_standard_layout::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 -struct BitStructNumber : public BitStructField { - using StorageType = T; - +template +struct BitStructNumber : public BitStructField { BitStructNumber& operator=(T value) { return BaseType::Assign(*this, value); } @@ -221,7 +219,7 @@ struct BitStructNumber : public BitStructField; + using BaseType = BitStructField; using BaseType::Get; }; @@ -229,21 +227,23 @@ struct BitStructNumber : public BitStructField +template using BitStructInt = BitStructNumber::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 +template using BitStructUint = BitStructNumber::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 +#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. // -- cgit v1.2.3-59-g8ed1b