Home | History | Annotate | Line # | Download | only in AST
      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 
     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       // 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.
    116       bool isZero() const     { return Quantity == 0; }
    117 
    118       /// isOne - Test whether the quantity equals one.
    119       bool isOne() const      { return Quantity == 1; }
    120 
    121       /// isPositive - Test whether the quantity is greater than zero.
    122       bool isPositive() const { return Quantity  > 0; }
    123 
    124       /// isNegative - Test whether the quantity is less than zero.
    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.
    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.
    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.
    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.
    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.
    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?
    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.
    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