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
20namespace 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
207inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
208 const clang::CharUnits &CU) {
209 return CU * Scale;
210}
211
212namespace llvm {
213
214template<> 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