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