Address.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. static Address invalid() { return Address(nullptr); }
  79. bool isValid() const { return A.getPointer() != nullptr; }
  80. llvm::Value *getPointer() const {
  81. assert(isValid());
  82. return A.getPointer();
  83. }
  84. /// Return the type of the pointer value.
  85. llvm::PointerType *getType() const {
  86. return llvm::cast<llvm::PointerType>(getPointer()->getType());
  87. }
  88. /// Return the type of the values stored in this address.
  89. llvm::Type *getElementType() const {
  90. assert(isValid());
  91. return A.getElementType();
  92. }
  93. /// Return the address space that this address resides in.
  94. unsigned getAddressSpace() const {
  95. return getType()->getAddressSpace();
  96. }
  97. /// Return the IR name of the pointer value.
  98. llvm::StringRef getName() const {
  99. return getPointer()->getName();
  100. }
  101. /// Return the alignment of this pointer.
  102. CharUnits getAlignment() const {
  103. assert(isValid());
  104. return A.getAlignment();
  105. }
  106. /// Return address with different pointer, but same element type and
  107. /// alignment.
  108. Address withPointer(llvm::Value *NewPointer) const {
  109. return Address(NewPointer, getElementType(), getAlignment());
  110. }
  111. /// Return address with different alignment, but same pointer and element
  112. /// type.
  113. Address withAlignment(CharUnits NewAlignment) const {
  114. return Address(getPointer(), getElementType(), NewAlignment);
  115. }
  116. };
  117. /// A specialization of Address that requires the address to be an
  118. /// LLVM Constant.
  119. class ConstantAddress : public Address {
  120. ConstantAddress(std::nullptr_t) : Address(nullptr) {}
  121. public:
  122. ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType,
  123. CharUnits alignment)
  124. : Address(pointer, elementType, alignment) {}
  125. static ConstantAddress invalid() {
  126. return ConstantAddress(nullptr);
  127. }
  128. llvm::Constant *getPointer() const {
  129. return llvm::cast<llvm::Constant>(Address::getPointer());
  130. }
  131. ConstantAddress getElementBitCast(llvm::Type *ElemTy) const {
  132. llvm::Constant *BitCast = llvm::ConstantExpr::getBitCast(
  133. getPointer(), ElemTy->getPointerTo(getAddressSpace()));
  134. return ConstantAddress(BitCast, ElemTy, getAlignment());
  135. }
  136. static bool isaImpl(Address addr) {
  137. return llvm::isa<llvm::Constant>(addr.getPointer());
  138. }
  139. static ConstantAddress castImpl(Address addr) {
  140. return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
  141. addr.getElementType(), addr.getAlignment());
  142. }
  143. };
  144. }
  145. // Present a minimal LLVM-like casting interface.
  146. template <class U> inline U cast(CodeGen::Address addr) {
  147. return U::castImpl(addr);
  148. }
  149. template <class U> inline bool isa(CodeGen::Address addr) {
  150. return U::isaImpl(addr);
  151. }
  152. }
  153. #endif