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       // Compound assignment.
68       CharUnits& operator+= (const CharUnits &Other) {
69         Quantity += Other.Quantity;
70         return *this;
71       }
72       CharUnits& operator++ () {
73         ++Quantity;
74         return *this;
75       }
76       CharUnits operator++ (int) {
77         return CharUnits(Quantity++);
78       }
79       CharUnits& operator-= (const CharUnits &Other) {
80         Quantity -= Other.Quantity;
81         return *this;
82       }
83       CharUnits& operator-- () {
84         --Quantity;
85         return *this;
86       }
87       CharUnits operator-- (int) {
88         return CharUnits(Quantity--);
89       }
90 
91       // Comparison operators.
92       bool operator== (const CharUnits &Other) const {
93         return Quantity == Other.Quantity;
94       }
95       bool operator!= (const CharUnits &Other) const {
96         return Quantity != Other.Quantity;
97       }
98 
99       // Relational operators.
100       bool operator<  (const CharUnits &Other) const {
101         return Quantity <  Other.Quantity;
102       }
103       bool operator<= (const CharUnits &Other) const {
104         return Quantity <= Other.Quantity;
105       }
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 
113       // Other predicates.
114 
115       /// isZero - Test whether the quantity equals zero.
isZero()116       bool isZero() const     { return Quantity == 0; }
117 
118       /// isOne - Test whether the quantity equals one.
isOne()119       bool isOne() const      { return Quantity == 1; }
120 
121       /// isPositive - Test whether the quantity is greater than zero.
isPositive()122       bool isPositive() const { return Quantity  > 0; }
123 
124       /// isNegative - Test whether the quantity is less than zero.
isNegative()125       bool isNegative() const { return Quantity  < 0; }
126 
127       /// isPowerOfTwo - Test whether the quantity is a power of two.
128       /// Zero is not a power of two.
isPowerOfTwo()129       bool isPowerOfTwo() const {
130         return (Quantity & -Quantity) == Quantity;
131       }
132 
133       /// Test whether this is a multiple of the other value.
134       ///
135       /// Among other things, this promises that
136       /// self.alignTo(N) will just return self.
isMultipleOf(CharUnits N)137       bool isMultipleOf(CharUnits N) const {
138         return (*this % N) == 0;
139       }
140 
141       // Arithmetic operators.
142       CharUnits operator* (QuantityType N) const {
143         return CharUnits(Quantity * N);
144       }
145       CharUnits &operator*= (QuantityType N) {
146         Quantity *= N;
147         return *this;
148       }
149       CharUnits operator/ (QuantityType N) const {
150         return CharUnits(Quantity / N);
151       }
152       CharUnits &operator/= (QuantityType N) {
153         Quantity /= N;
154         return *this;
155       }
156       QuantityType operator/ (const CharUnits &Other) const {
157         return Quantity / Other.Quantity;
158       }
159       CharUnits operator% (QuantityType N) const {
160         return CharUnits(Quantity % N);
161       }
162       QuantityType operator% (const CharUnits &Other) const {
163         return Quantity % Other.Quantity;
164       }
165       CharUnits operator+ (const CharUnits &Other) const {
166         return CharUnits(Quantity + Other.Quantity);
167       }
168       CharUnits operator- (const CharUnits &Other) const {
169         return CharUnits(Quantity - Other.Quantity);
170       }
171       CharUnits operator- () const {
172         return CharUnits(-Quantity);
173       }
174 
175 
176       // Conversions.
177 
178       /// getQuantity - Get the raw integer representation of this quantity.
getQuantity()179       QuantityType getQuantity() const { return Quantity; }
180 
181       /// getAsAlign - Returns Quantity as a valid llvm::Align,
182       /// Beware llvm::Align assumes power of two 8-bit bytes.
getAsAlign()183       llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
184 
185       /// alignTo - Returns the next integer (mod 2**64) that is
186       /// greater than or equal to this quantity and is a multiple of \p Align.
187       /// Align must be non-zero.
alignTo(const CharUnits & Align)188       CharUnits alignTo(const CharUnits &Align) const {
189         return CharUnits(llvm::alignTo(Quantity, Align.Quantity));
190       }
191 
192       /// Given that this is a non-zero alignment value, what is the
193       /// alignment at the given offset?
alignmentAtOffset(CharUnits offset)194       CharUnits alignmentAtOffset(CharUnits offset) const {
195         assert(Quantity != 0 && "offsetting from unknown alignment?");
196         return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
197       }
198 
199       /// Given that this is the alignment of the first element of an
200       /// array, return the minimum alignment of any element in the array.
alignmentOfArrayElement(CharUnits elementSize)201       CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
202         // Since we don't track offsetted alignments, the alignment of
203         // the second element (or any odd element) will be minimally
204         // aligned.
205         return alignmentAtOffset(elementSize);
206       }
207 
208 
209   }; // class CharUnit
210 } // namespace clang
211 
212 inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
213                                    const clang::CharUnits &CU) {
214   return CU * Scale;
215 }
216 
217 namespace llvm {
218 
219 template<> struct DenseMapInfo<clang::CharUnits> {
220   static clang::CharUnits getEmptyKey() {
221     clang::CharUnits::QuantityType Quantity =
222       DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
223 
224     return clang::CharUnits::fromQuantity(Quantity);
225   }
226 
227   static clang::CharUnits getTombstoneKey() {
228     clang::CharUnits::QuantityType Quantity =
229       DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
230 
231     return clang::CharUnits::fromQuantity(Quantity);
232   }
233 
234   static unsigned getHashValue(const clang::CharUnits &CU) {
235     clang::CharUnits::QuantityType Quantity = CU.getQuantity();
236     return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
237   }
238 
239   static bool isEqual(const clang::CharUnits &LHS,
240                       const clang::CharUnits &RHS) {
241     return LHS == RHS;
242   }
243 };
244 
245 } // end namespace llvm
246 
247 #endif // LLVM_CLANG_AST_CHARUNITS_H
248