1 //===--- CharUnits.h - Character units for sizes and offsets ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the CharUnits class 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_CHARUNITS_H 14 #define LLVM_CLANG_AST_CHARUNITS_H 15 16 #include "llvm/ADT/DenseMapInfo.h" 17 #include "llvm/Support/DataTypes.h" 18 #include "llvm/Support/MathExtras.h" 19 20 namespace clang { 21 22 /// CharUnits - This is an opaque type for sizes expressed in character units. 23 /// Instances of this type represent a quantity as a multiple of the size 24 /// of the standard C type, char, on the target architecture. As an opaque 25 /// type, CharUnits protects you from accidentally combining operations on 26 /// quantities in bit units and character units. 27 /// 28 /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned 29 /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to 30 /// the same quantity of storage. However, we use the term 'character unit' 31 /// rather than 'byte' to avoid an implication that a character unit is 32 /// exactly 8 bits. 33 /// 34 /// For portability, never assume that a target character is 8 bits wide. Use 35 /// CharUnit values wherever you calculate sizes, offsets, or alignments 36 /// in character units. 37 class CharUnits { 38 public: 39 typedef int64_t QuantityType; 40 41 private: 42 QuantityType Quantity = 0; 43 44 explicit CharUnits(QuantityType C) : Quantity(C) {} 45 46 public: 47 48 /// CharUnits - A default constructor. 49 CharUnits() = default; 50 51 /// Zero - Construct a CharUnits quantity of zero. 52 static CharUnits Zero() { 53 return CharUnits(0); 54 } 55 56 /// One - Construct a CharUnits quantity of one. 57 static CharUnits One() { 58 return CharUnits(1); 59 } 60 61 /// fromQuantity - Construct a CharUnits quantity from a raw integer type. 62 static CharUnits fromQuantity(QuantityType Quantity) { 63 return CharUnits(Quantity); 64 } 65 66 // Compound assignment. 67 CharUnits& operator+= (const CharUnits &Other) { 68 Quantity += Other.Quantity; 69 return *this; 70 } 71 CharUnits& operator++ () { 72 ++Quantity; 73 return *this; 74 } 75 CharUnits operator++ (int) { 76 return CharUnits(Quantity++); 77 } 78 CharUnits& operator-= (const CharUnits &Other) { 79 Quantity -= Other.Quantity; 80 return *this; 81 } 82 CharUnits& operator-- () { 83 --Quantity; 84 return *this; 85 } 86 CharUnits operator-- (int) { 87 return CharUnits(Quantity--); 88 } 89 90 // Comparison operators. 91 bool operator== (const CharUnits &Other) const { 92 return Quantity == Other.Quantity; 93 } 94 bool operator!= (const CharUnits &Other) const { 95 return Quantity != Other.Quantity; 96 } 97 98 // Relational operators. 99 bool operator< (const CharUnits &Other) const { 100 return Quantity < Other.Quantity; 101 } 102 bool operator<= (const CharUnits &Other) const { 103 return Quantity <= Other.Quantity; 104 } 105 bool operator> (const CharUnits &Other) const { 106 return Quantity > Other.Quantity; 107 } 108 bool operator>= (const CharUnits &Other) const { 109 return Quantity >= Other.Quantity; 110 } 111 112 // Other predicates. 113 114 /// isZero - Test whether the quantity equals zero. 115 bool isZero() const { return Quantity == 0; } 116 117 /// isOne - Test whether the quantity equals one. 118 bool isOne() const { return Quantity == 1; } 119 120 /// isPositive - Test whether the quantity is greater than zero. 121 bool isPositive() const { return Quantity > 0; } 122 123 /// isNegative - Test whether the quantity is less than zero. 124 bool isNegative() const { return Quantity < 0; } 125 126 /// isPowerOfTwo - Test whether the quantity is a power of two. 127 /// Zero is not a power of two. 128 bool isPowerOfTwo() const { 129 return (Quantity & -Quantity) == Quantity; 130 } 131 132 /// Test whether this is a multiple of the other value. 133 /// 134 /// Among other things, this promises that 135 /// self.alignTo(N) will just return self. 136 bool isMultipleOf(CharUnits N) const { 137 return (*this % N) == 0; 138 } 139 140 // Arithmetic operators. 141 CharUnits operator* (QuantityType N) const { 142 return CharUnits(Quantity * N); 143 } 144 CharUnits &operator*= (QuantityType N) { 145 Quantity *= N; 146 return *this; 147 } 148 CharUnits operator/ (QuantityType N) const { 149 return CharUnits(Quantity / N); 150 } 151 CharUnits &operator/= (QuantityType N) { 152 Quantity /= N; 153 return *this; 154 } 155 QuantityType operator/ (const CharUnits &Other) const { 156 return Quantity / Other.Quantity; 157 } 158 CharUnits operator% (QuantityType N) const { 159 return CharUnits(Quantity % N); 160 } 161 QuantityType operator% (const CharUnits &Other) const { 162 return Quantity % Other.Quantity; 163 } 164 CharUnits operator+ (const CharUnits &Other) const { 165 return CharUnits(Quantity + Other.Quantity); 166 } 167 CharUnits operator- (const CharUnits &Other) const { 168 return CharUnits(Quantity - Other.Quantity); 169 } 170 CharUnits operator- () const { 171 return CharUnits(-Quantity); 172 } 173 174 175 // Conversions. 176 177 /// getQuantity - Get the raw integer representation of this quantity. 178 QuantityType getQuantity() const { return Quantity; } 179 180 /// alignTo - Returns the next integer (mod 2**64) that is 181 /// greater than or equal to this quantity and is a multiple of \p Align. 182 /// Align must be non-zero. 183 CharUnits alignTo(const CharUnits &Align) const { 184 return CharUnits(llvm::alignTo(Quantity, Align.Quantity)); 185 } 186 187 /// Given that this is a non-zero alignment value, what is the 188 /// alignment at the given offset? 189 CharUnits alignmentAtOffset(CharUnits offset) const { 190 assert(Quantity != 0 && "offsetting from unknown alignment?"); 191 return CharUnits(llvm::MinAlign(Quantity, offset.Quantity)); 192 } 193 194 /// Given that this is the alignment of the first element of an 195 /// array, return the minimum alignment of any element in the array. 196 CharUnits alignmentOfArrayElement(CharUnits elementSize) const { 197 // Since we don't track offsetted alignments, the alignment of 198 // the second element (or any odd element) will be minimally 199 // aligned. 200 return alignmentAtOffset(elementSize); 201 } 202 203 204 }; // class CharUnit 205 } // namespace clang 206 207 inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale, 208 const clang::CharUnits &CU) { 209 return CU * Scale; 210 } 211 212 namespace llvm { 213 214 template<> struct DenseMapInfo<clang::CharUnits> { 215 static clang::CharUnits getEmptyKey() { 216 clang::CharUnits::QuantityType Quantity = 217 DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey(); 218 219 return clang::CharUnits::fromQuantity(Quantity); 220 } 221 222 static clang::CharUnits getTombstoneKey() { 223 clang::CharUnits::QuantityType Quantity = 224 DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey(); 225 226 return clang::CharUnits::fromQuantity(Quantity); 227 } 228 229 static unsigned getHashValue(const clang::CharUnits &CU) { 230 clang::CharUnits::QuantityType Quantity = CU.getQuantity(); 231 return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity); 232 } 233 234 static bool isEqual(const clang::CharUnits &LHS, 235 const clang::CharUnits &RHS) { 236 return LHS == RHS; 237 } 238 }; 239 240 } // end namespace llvm 241 242 #endif // LLVM_CLANG_AST_CHARUNITS_H 243