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
21namespace 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
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.
53      static CharUnits Zero() {
54        return CharUnits(0);
55      }
56
57      /// One - Construct a CharUnits quantity of one.
58      static CharUnits One() {
59        return CharUnits(1);
60      }
61
62      /// fromQuantity - Construct a CharUnits quantity from a raw integer type.
63      static CharUnits fromQuantity(QuantityType Quantity) {
64        return CharUnits(Quantity);
65      }
66
67      /// fromQuantity - Construct a CharUnits quantity from an llvm::Align
68      /// 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.
122      bool isZero() const     { return Quantity == 0; }
123
124      /// isOne - Test whether the quantity equals one.
125      bool isOne() const      { return Quantity == 1; }
126
127      /// isPositive - Test whether the quantity is greater than zero.
128      bool isPositive() const { return Quantity  > 0; }
129
130      /// isNegative - Test whether the quantity is less than zero.
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.
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.
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.
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.
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.
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.
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?
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.
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
225inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
226                                   const clang::CharUnits &CU) {
227  return CU * Scale;
228}
229
230namespace llvm {
231
232template<> 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