summaryrefslogtreecommitdiff
path: root/runtime/base/bit_struct.h
diff options
context:
space:
mode:
author David Sehr <sehr@google.com> 2018-03-02 12:01:51 -0800
committer David Sehr <sehr@google.com> 2018-03-05 13:58:20 -0800
commitc431b9dc4b23cc950eb313695258df5d89f53b22 (patch)
tree422273559c3ae52caff0c6b1cf1a62a8312f0e26 /runtime/base/bit_struct.h
parentf46f46cf5bd32788d5252b7107628a66594a5e98 (diff)
Move most of runtime/base to libartbase/base
Enforce the layering that code in runtime/base should not depend on runtime by separating it into libartbase. Some of the code in runtime/base depends on the Runtime class, so it cannot be moved yet. Also, some of the tests depend on CommonRuntimeTest, which itself needs to be factored (in a subsequent CL). Bug: 22322814 Test: make -j 50 checkbuild make -j 50 test-art-host Change-Id: I8b096c1e2542f829eb456b4b057c71421b77d7e2
Diffstat (limited to 'runtime/base/bit_struct.h')
-rw-r--r--runtime/base/bit_struct.h306
1 files changed, 0 insertions, 306 deletions
diff --git a/runtime/base/bit_struct.h b/runtime/base/bit_struct.h
deleted file mode 100644
index 7eb63c6b5c..0000000000
--- a/runtime/base/bit_struct.h
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_BASE_BIT_STRUCT_H_
-#define ART_RUNTIME_BASE_BIT_STRUCT_H_
-
-#include "base/bit_utils.h"
-#include "bit_struct_detail.h"
-
-//
-// Zero-cost, type-safe, well-defined "structs" of bit fields.
-//
-// ---------------------------------------------
-// Usage example:
-// ---------------------------------------------
-//
-// // 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_DEFINE_END(Example);
-//
-// Would define a bit struct with this layout:
-// <- 1 -> <-- 7 --> <- 2 ->
-// +--------+---------------+-----+
-// | i1 | i7 | u2 +
-// +--------+---------------+-----+
-// 10 9 2 0
-//
-// // Read-write just like regular values.
-// Example ex;
-// ex.u2 = 3;
-// ex.i7 = -25;
-// ex.i1 = true;
-// size_t u2 = ex.u2;
-// int i7 = ex.i7;
-// bool i1 = ex.i1;
-//
-// // It's packed down to the smallest # of machine words.
-// assert(sizeof(Example) == 2);
-// // The exact bit pattern is well-defined by the template parameters.
-// uint16_t cast = *reinterpret_cast<uint16_t*>(ex);
-// assert(cast == ((3) | (0b100111 << 2) | (true << 9);
-//
-// ---------------------------------------------
-// Why not just use C++ bitfields?
-// ---------------------------------------------
-//
-// The layout is implementation-defined.
-// We do not know whether the fields are packed left-to-right or
-// right-to-left, so it makes it useless when the memory layout needs to be
-// precisely controlled.
-//
-// ---------------------------------------------
-// More info:
-// ---------------------------------------------
-// Currently uintmax_t is the largest supported underlying storage type,
-// all (kBitOffset + kBitWidth) must fit into BitSizeOf<uintmax_t>();
-//
-// Using BitStruct[U]int will automatically select an underlying type
-// that's the smallest to fit your (offset + bitwidth).
-//
-// BitStructNumber can be used to manually select an underlying type.
-//
-// BitStructField can be used with custom standard-layout structs,
-// thus allowing for arbitrary nesting of bit structs.
-//
-namespace art {
-// Zero-cost wrapper around a struct 'T', allowing it to be stored as a bitfield
-// at offset 'kBitOffset' and width 'kBitWidth'.
-// The storage is plain unsigned int, whose size is the smallest required to fit
-// 'kBitOffset + kBitWidth'. All operations to this become BitFieldExtract/BitFieldInsert
-// operations to the underlying uint.
-//
-// Field memory representation:
-//
-// MSB <-- width --> LSB
-// +--------+------------+--------+
-// | ?????? | u bitfield | ?????? +
-// +--------+------------+--------+
-// offset 0
-//
-// Reading/writing the bitfield (un)packs it into a temporary T:
-//
-// MSB <-- width --> LSB
-// +-----------------+------------+
-// | 0.............0 | T bitfield |
-// +-----------------+------------+
-// 0
-//
-// It's the responsibility of the StorageType to ensure the bit representation
-// 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>
-struct BitStructField {
- static_assert(std::is_standard_layout<T>::value, "T must be standard layout");
-
- operator T() const {
- return Get();
- }
-
- // Exclude overload when T==StorageType.
- template <typename _ = void,
- typename = std::enable_if_t<std::is_same<T, StorageType>::value, _>>
- explicit operator StorageType() const {
- return GetStorage();
- }
-
- BitStructField& operator=(T value) {
- return Assign(*this, value);
- }
-
- static constexpr size_t BitStructSizeOf() {
- return kBitWidth;
- }
-
- BitStructField& operator=(const BitStructField& other) {
- // Warning. The default operator= will overwrite the entire storage!
- return *this = static_cast<T>(other);
- }
-
- BitStructField(const BitStructField& other) {
- Assign(*this, static_cast<T>(other));
- }
-
- BitStructField() = default;
- ~BitStructField() = default;
-
- protected:
- template <typename T2>
- T2& Assign(T2& what, T value) {
- // Since C++ doesn't allow the type of operator= to change out
- // in the subclass, reimplement operator= in each subclass
- // manually and call this helper function.
- static_assert(std::is_base_of<BitStructField, T2>::value, "T2 must inherit BitStructField");
- what.Set(value);
- return what;
- }
-
- T Get() const {
- ValueStorage vs;
- vs.pod_.val_ = GetStorage();
- return vs.value_;
- }
-
- void Set(T value) {
- ValueStorage value_as_storage;
- value_as_storage.value_ = value;
-
- storage_.pod_.val_ = BitFieldInsert(storage_.pod_.val_,
- value_as_storage.pod_.val_,
- kBitOffset,
- kBitWidth);
- }
-
- private:
- StorageType GetStorage() const {
- return BitFieldExtract(storage_.pod_.val_, kBitOffset, kBitWidth);
- }
-
- // Underlying value must be wrapped in a separate standard-layout struct.
- // See below for more details.
- struct PodWrapper {
- StorageType val_;
- };
-
- union ValueStorage {
- // Safely alias pod_ and value_ together.
- //
- // See C++ 9.5.1 [class.union]:
- // If a standard-layout union contains several standard-layout structs that share a common
- // initial sequence ... it is permitted to inspect the common initial sequence of any of
- // standard-layout struct members.
- PodWrapper pod_;
- T value_;
- } storage_;
-
- // Future work: In theory almost non-standard layout can be supported here,
- // assuming they don't rely on the address of (this).
- // We just have to use memcpy since the union-aliasing would not work.
-};
-
-// Base class for number-like BitStruct fields.
-// T is the type to store in as a bit field.
-// kBitOffset, kBitWidth define the position and length of the bitfield.
-//
-// (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;
-
- BitStructNumber& operator=(T value) {
- return BaseType::Assign(*this, value);
- }
-
- /*implicit*/ operator T() const {
- return Get();
- }
-
- explicit operator bool() const {
- return static_cast<bool>(Get());
- }
-
- BitStructNumber& operator++() {
- *this = Get() + 1u;
- return *this;
- }
-
- StorageType operator++(int) {
- return Get() + 1u;
- }
-
- BitStructNumber& operator--() {
- *this = Get() - 1u;
- return *this;
- }
-
- StorageType operator--(int) {
- return Get() - 1u;
- }
-
- private:
- using BaseType = BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T>;
- using BaseType::Get;
-};
-
-// Create a BitStruct field which uses the smallest underlying int storage type,
-// 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>
-using BitStructInt =
- BitStructNumber<typename detail::MinimumTypeHelper<int, kBitOffset + kBitWidth>::type,
- kBitOffset,
- kBitWidth>;
-
-// 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>
-using BitStructUint =
- BitStructNumber<typename detail::MinimumTypeHelper<unsigned int, kBitOffset + kBitWidth>::type,
- kBitOffset,
- kBitWidth>;
-
-// Start a definition for a bitstruct.
-// A bitstruct is defined to be a union with a common initial subsequence
-// that we call 'DefineBitStructSize<bitwidth>'.
-//
-// See top of file for usage example.
-//
-// This marker is required by the C++ standard in order to
-// have a "common initial sequence".
-//
-// See C++ 9.5.1 [class.union]:
-// If a standard-layout union contains several standard-layout structs that share a common
-// initial sequence ... it is permitted to inspect the common initial sequence of any of
-// standard-layout struct members.
-#define BITSTRUCT_DEFINE_START(name, bitwidth) \
- union name { \
- art::detail::DefineBitStructSize<(bitwidth)> _; \
- static constexpr size_t BitStructSizeOf() { return (bitwidth); } \
- name& operator=(const name& other) { _ = other._; return *this; } \
- name(const name& other) : _(other._) {} \
- name() = default; \
- ~name() = default;
-
-// End the definition of a bitstruct, and insert a sanity check
-// to ensure that the bitstruct did not exceed the specified size.
-//
-// See top of file for usage example.
-#define BITSTRUCT_DEFINE_END(name) \
- }; \
- static_assert(art::detail::ValidateBitStructSize<name>(), \
- #name "bitsize incorrect: " \
- "did you insert extra fields that weren't BitStructX, " \
- "and does the size match the sum of the field widths?")
-
-// Determine the minimal bit size for a user-defined type T.
-// Used by BitStructField to determine how small a custom type is.
-template <typename T>
-static constexpr size_t BitStructSizeOf() {
- return T::BitStructSizeOf();
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_STRUCT_H_