xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/CharUnits.h (revision 6966ac055c3b7a39266fb982493330df7a097997)
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