Address.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //===-- Address.h - An aligned address -------------------------*- 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 class provides a simple wrapper for a pair of a pointer and an
  10. // alignment.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
  14. #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
  15. #include "clang/AST/CharUnits.h"
  16. #include "llvm/ADT/PointerIntPair.h"
  17. #include "llvm/IR/Constants.h"
  18. #include "llvm/Support/MathExtras.h"
  19. namespace clang {
  20. namespace CodeGen {
  21. // We try to save some space by using 6 bits over two PointerIntPairs to store
  22. // the alignment. However, some arches don't support 3 bits in a PointerIntPair
  23. // so we fallback to storing the alignment separately.
  24. template <typename T, bool = alignof(llvm::Value *) >= 8> class AddressImpl {};
  25. template <typename T> class AddressImpl<T, false> {
  26. llvm::Value *Pointer;
  27. llvm::Type *ElementType;
  28. CharUnits Alignment;
  29. public:
  30. AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType,
  31. CharUnits Alignment)
  32. : Pointer(Pointer), ElementType(ElementType), Alignment(Alignment) {}
  33. llvm::Value *getPointer() const { return Pointer; }
  34. llvm::Type *getElementType() const { return ElementType; }
  35. CharUnits getAlignment() const { return Alignment; }
  36. };
  37. template <typename T> class AddressImpl<T, true> {
  38. // Int portion stores upper 3 bits of the log of the alignment.
  39. llvm::PointerIntPair<llvm::Value *, 3, unsigned> Pointer;
  40. // Int portion stores lower 3 bits of the log of the alignment.
  41. llvm::PointerIntPair<llvm::Type *, 3, unsigned> ElementType;
  42. public:
  43. AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType,
  44. CharUnits Alignment)
  45. : Pointer(Pointer), ElementType(ElementType) {
  46. if (Alignment.isZero())
  47. return;
  48. // Currently the max supported alignment is much less than 1 << 63 and is
  49. // guaranteed to be a power of 2, so we can store the log of the alignment
  50. // into 6 bits.
  51. assert(Alignment.isPowerOfTwo() && "Alignment cannot be zero");
  52. auto AlignLog = llvm::Log2_64(Alignment.getQuantity());
  53. assert(AlignLog < (1 << 6) && "cannot fit alignment into 6 bits");
  54. this->Pointer.setInt(AlignLog >> 3);
  55. this->ElementType.setInt(AlignLog & 7);
  56. }
  57. llvm::Value *getPointer() const { return Pointer.getPointer(); }
  58. llvm::Type *getElementType() const { return ElementType.getPointer(); }
  59. CharUnits getAlignment() const {
  60. unsigned AlignLog = (Pointer.getInt() << 3) | ElementType.getInt();
  61. return CharUnits::fromQuantity(CharUnits::QuantityType(1) << AlignLog);
  62. }
  63. };
  64. /// An aligned address.
  65. class Address {
  66. AddressImpl<void> A;
  67. protected:
  68. Address(std::nullptr_t) : A(nullptr, nullptr, CharUnits::Zero()) {}
  69. public:
  70. Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment)
  71. : A(Pointer, ElementType, Alignment) {
  72. assert(Pointer != nullptr && "Pointer cannot be null");
  73. assert(ElementType != nullptr && "Element type cannot be null");
  74. assert(llvm::cast<llvm::PointerType>(Pointer->getType())
  75. ->isOpaqueOrPointeeTypeMatches(ElementType) &&
  76. "Incorrect pointer element type");
  77. }
  78. // Deprecated: Use constructor with explicit element type instead.
  79. Address(llvm::Value *Pointer, CharUnits Alignment)
  80. : Address(Pointer, Pointer->getType()->getPointerElementType(),
  81. Alignment) {}
  82. static Address invalid() { return Address(nullptr); }
  83. bool isValid() const { return A.getPointer() != nullptr; }
  84. llvm::Value *getPointer() const {
  85. assert(isValid());
  86. return A.getPointer();
  87. }
  88. /// Return the type of the pointer value.
  89. llvm::PointerType *getType() const {
  90. return llvm::cast<llvm::PointerType>(getPointer()->getType());
  91. }
  92. /// Return the type of the values stored in this address.
  93. llvm::Type *getElementType() const {
  94. assert(isValid());
  95. return A.getElementType();
  96. }
  97. /// Return the address space that this address resides in.
  98. unsigned getAddressSpace() const {
  99. return getType()->getAddressSpace();
  100. }
  101. /// Return the IR name of the pointer value.
  102. llvm::StringRef getName() const {
  103. return getPointer()->getName();
  104. }
  105. /// Return the alignment of this pointer.
  106. CharUnits getAlignment() const {
  107. assert(isValid());
  108. return A.getAlignment();
  109. }
  110. /// Return address with different pointer, but same element type and
  111. /// alignment.
  112. Address withPointer(llvm::Value *NewPointer) const {
  113. return Address(NewPointer, getElementType(), getAlignment());
  114. }
  115. /// Return address with different alignment, but same pointer and element
  116. /// type.
  117. Address withAlignment(CharUnits NewAlignment) const {
  118. return Address(getPointer(), getElementType(), NewAlignment);
  119. }
  120. };
  121. /// A specialization of Address that requires the address to be an
  122. /// LLVM Constant.
  123. class ConstantAddress : public Address {
  124. ConstantAddress(std::nullptr_t) : Address(nullptr) {}
  125. public:
  126. ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType,
  127. CharUnits alignment)
  128. : Address(pointer, elementType, alignment) {}
  129. static ConstantAddress invalid() {
  130. return ConstantAddress(nullptr);
  131. }
  132. llvm::Constant *getPointer() const {
  133. return llvm::cast<llvm::Constant>(Address::getPointer());
  134. }
  135. ConstantAddress getElementBitCast(llvm::Type *ElemTy) const {
  136. llvm::Constant *BitCast = llvm::ConstantExpr::getBitCast(
  137. getPointer(), ElemTy->getPointerTo(getAddressSpace()));
  138. return ConstantAddress(BitCast, ElemTy, getAlignment());
  139. }
  140. static bool isaImpl(Address addr) {
  141. return llvm::isa<llvm::Constant>(addr.getPointer());
  142. }
  143. static ConstantAddress castImpl(Address addr) {
  144. return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
  145. addr.getElementType(), addr.getAlignment());
  146. }
  147. };
  148. }
  149. // Present a minimal LLVM-like casting interface.
  150. template <class U> inline U cast(CodeGen::Address addr) {
  151. return U::castImpl(addr);
  152. }
  153. template <class U> inline bool isa(CodeGen::Address addr) {
  154. return U::isaImpl(addr);
  155. }
  156. }
  157. #endif