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 14 #ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H 15 #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H 16 17 #include "CGPointerAuthInfo.h" 18 #include "clang/AST/CharUnits.h" 19 #include "clang/AST/Type.h" 20 #include "llvm/ADT/PointerIntPair.h" 21 #include "llvm/IR/Constants.h" 22 #include "llvm/Support/MathExtras.h" 23 24 namespace clang { 25 namespace CodeGen { 26 27 class Address; 28 class CGBuilderTy; 29 class CodeGenFunction; 30 class CodeGenModule; 31 32 // Indicates whether a pointer is known not to be null. 33 enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; 34 35 /// An abstract representation of an aligned address. This is designed to be an 36 /// IR-level abstraction, carrying just the information necessary to perform IR 37 /// operations on an address like loads and stores. In particular, it doesn't 38 /// carry C type information or allow the representation of things like 39 /// bit-fields; clients working at that level should generally be using 40 /// `LValue`. 41 /// The pointer contained in this class is known to be unsigned. 42 class RawAddress { 43 llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull; 44 llvm::Type *ElementType; 45 CharUnits Alignment; 46 47 protected: 48 RawAddress(std::nullptr_t) : ElementType(nullptr) {} 49 50 public: 51 RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, 52 KnownNonNull_t IsKnownNonNull = NotKnownNonNull) 53 : PointerAndKnownNonNull(Pointer, IsKnownNonNull), 54 ElementType(ElementType), Alignment(Alignment) { 55 assert(Pointer != nullptr && "Pointer cannot be null"); 56 assert(ElementType != nullptr && "Element type cannot be null"); 57 } 58 59 inline RawAddress(Address Addr); 60 61 static RawAddress invalid() { return RawAddress(nullptr); } 62 bool isValid() const { 63 return PointerAndKnownNonNull.getPointer() != nullptr; 64 } 65 66 llvm::Value *getPointer() const { 67 assert(isValid()); 68 return PointerAndKnownNonNull.getPointer(); 69 } 70 71 /// Return the type of the pointer value. 72 llvm::PointerType *getType() const { 73 return llvm::cast<llvm::PointerType>(getPointer()->getType()); 74 } 75 76 /// Return the type of the values stored in this address. 77 llvm::Type *getElementType() const { 78 assert(isValid()); 79 return ElementType; 80 } 81 82 /// Return the address space that this address resides in. 83 unsigned getAddressSpace() const { 84 return getType()->getAddressSpace(); 85 } 86 87 /// Return the IR name of the pointer value. 88 llvm::StringRef getName() const { 89 return getPointer()->getName(); 90 } 91 92 /// Return the alignment of this pointer. 93 CharUnits getAlignment() const { 94 assert(isValid()); 95 return Alignment; 96 } 97 98 /// Return address with different element type, but same pointer and 99 /// alignment. 100 RawAddress withElementType(llvm::Type *ElemTy) const { 101 return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); 102 } 103 104 KnownNonNull_t isKnownNonNull() const { 105 assert(isValid()); 106 return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); 107 } 108 }; 109 110 /// Like RawAddress, an abstract representation of an aligned address, but the 111 /// pointer contained in this class is possibly signed. 112 /// 113 /// This is designed to be an IR-level abstraction, carrying just the 114 /// information necessary to perform IR operations on an address like loads and 115 /// stores. In particular, it doesn't carry C type information or allow the 116 /// representation of things like bit-fields; clients working at that level 117 /// should generally be using `LValue`. 118 /// 119 /// An address may be either *raw*, meaning that it's an ordinary machine 120 /// pointer, or *signed*, meaning that the pointer carries an embedded 121 /// pointer-authentication signature. Representing signed pointers directly in 122 /// this abstraction allows the authentication to be delayed as long as possible 123 /// without forcing IRGen to use totally different code paths for signed and 124 /// unsigned values or to separately propagate signature information through 125 /// every API that manipulates addresses. Pointer arithmetic on signed addresses 126 /// (e.g. drilling down to a struct field) is accumulated into a separate offset 127 /// which is applied when the address is finally accessed. 128 class Address { 129 friend class CGBuilderTy; 130 131 // The boolean flag indicates whether the pointer is known to be non-null. 132 llvm::PointerIntPair<llvm::Value *, 1, bool> Pointer; 133 134 /// The expected IR type of the pointer. Carrying accurate element type 135 /// information in Address makes it more convenient to work with Address 136 /// values and allows frontend assertions to catch simple mistakes. 137 llvm::Type *ElementType = nullptr; 138 139 CharUnits Alignment; 140 141 /// The ptrauth information needed to authenticate the base pointer. 142 CGPointerAuthInfo PtrAuthInfo; 143 144 /// Offset from the base pointer. This is non-null only when the base 145 /// pointer is signed. 146 llvm::Value *Offset = nullptr; 147 148 llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; 149 150 protected: 151 Address(std::nullptr_t) : ElementType(nullptr) {} 152 153 public: 154 Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment, 155 KnownNonNull_t IsKnownNonNull = NotKnownNonNull) 156 : Pointer(pointer, IsKnownNonNull), ElementType(elementType), 157 Alignment(alignment) { 158 assert(pointer != nullptr && "Pointer cannot be null"); 159 assert(elementType != nullptr && "Element type cannot be null"); 160 assert(!alignment.isZero() && "Alignment cannot be zero"); 161 } 162 163 Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, 164 CGPointerAuthInfo PtrAuthInfo, llvm::Value *Offset, 165 KnownNonNull_t IsKnownNonNull = NotKnownNonNull) 166 : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), 167 Alignment(Alignment), PtrAuthInfo(PtrAuthInfo), Offset(Offset) {} 168 169 Address(RawAddress RawAddr) 170 : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr, 171 RawAddr.isValid() ? RawAddr.isKnownNonNull() : NotKnownNonNull), 172 ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), 173 Alignment(RawAddr.isValid() ? RawAddr.getAlignment() 174 : CharUnits::Zero()) {} 175 176 static Address invalid() { return Address(nullptr); } 177 bool isValid() const { return Pointer.getPointer() != nullptr; } 178 179 llvm::Value *getPointerIfNotSigned() const { 180 assert(isValid() && "pointer isn't valid"); 181 return !isSigned() ? Pointer.getPointer() : nullptr; 182 } 183 184 /// This function is used in situations where the caller is doing some sort of 185 /// opaque "laundering" of the pointer. 186 void replaceBasePointer(llvm::Value *P) { 187 assert(isValid() && "pointer isn't valid"); 188 assert(P->getType() == Pointer.getPointer()->getType() && 189 "Pointer's type changed"); 190 Pointer.setPointer(P); 191 assert(isValid() && "pointer is invalid after replacement"); 192 } 193 194 CharUnits getAlignment() const { return Alignment; } 195 196 void setAlignment(CharUnits Value) { Alignment = Value; } 197 198 llvm::Value *getBasePointer() const { 199 assert(isValid() && "pointer isn't valid"); 200 return Pointer.getPointer(); 201 } 202 203 /// Return the type of the pointer value. 204 llvm::PointerType *getType() const { 205 return llvm::cast<llvm::PointerType>(Pointer.getPointer()->getType()); 206 } 207 208 /// Return the type of the values stored in this address. 209 llvm::Type *getElementType() const { 210 assert(isValid()); 211 return ElementType; 212 } 213 214 /// Return the address space that this address resides in. 215 unsigned getAddressSpace() const { return getType()->getAddressSpace(); } 216 217 /// Return the IR name of the pointer value. 218 llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } 219 220 const CGPointerAuthInfo &getPointerAuthInfo() const { return PtrAuthInfo; } 221 void setPointerAuthInfo(const CGPointerAuthInfo &Info) { PtrAuthInfo = Info; } 222 223 // This function is called only in CGBuilderBaseTy::CreateElementBitCast. 224 void setElementType(llvm::Type *Ty) { 225 assert(hasOffset() && 226 "this funcion shouldn't be called when there is no offset"); 227 ElementType = Ty; 228 } 229 230 bool isSigned() const { return PtrAuthInfo.isSigned(); } 231 232 /// Whether the pointer is known not to be null. 233 KnownNonNull_t isKnownNonNull() const { 234 assert(isValid()); 235 return (KnownNonNull_t)Pointer.getInt(); 236 } 237 238 Address setKnownNonNull() { 239 assert(isValid()); 240 Pointer.setInt(KnownNonNull); 241 return *this; 242 } 243 244 bool hasOffset() const { return Offset; } 245 246 llvm::Value *getOffset() const { return Offset; } 247 248 Address getResignedAddress(const CGPointerAuthInfo &NewInfo, 249 CodeGenFunction &CGF) const; 250 251 /// Return the pointer contained in this class after authenticating it and 252 /// adding offset to it if necessary. 253 llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { 254 if (!isSigned()) 255 return getBasePointer(); 256 return emitRawPointerSlow(CGF); 257 } 258 259 /// Return address with different pointer, but same element type and 260 /// alignment. 261 Address withPointer(llvm::Value *NewPointer, 262 KnownNonNull_t IsKnownNonNull) const { 263 return Address(NewPointer, getElementType(), getAlignment(), 264 IsKnownNonNull); 265 } 266 267 /// Return address with different alignment, but same pointer and element 268 /// type. 269 Address withAlignment(CharUnits NewAlignment) const { 270 return Address(Pointer.getPointer(), getElementType(), NewAlignment, 271 isKnownNonNull()); 272 } 273 274 /// Return address with different element type, but same pointer and 275 /// alignment. 276 Address withElementType(llvm::Type *ElemTy) const { 277 if (!hasOffset()) 278 return Address(getBasePointer(), ElemTy, getAlignment(), 279 getPointerAuthInfo(), /*Offset=*/nullptr, 280 isKnownNonNull()); 281 Address A(*this); 282 A.ElementType = ElemTy; 283 return A; 284 } 285 }; 286 287 inline RawAddress::RawAddress(Address Addr) 288 : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, 289 Addr.isValid() ? Addr.isKnownNonNull() 290 : NotKnownNonNull), 291 ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), 292 Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} 293 294 /// A specialization of Address that requires the address to be an 295 /// LLVM Constant. 296 class ConstantAddress : public RawAddress { 297 ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} 298 299 public: 300 ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, 301 CharUnits alignment) 302 : RawAddress(pointer, elementType, alignment) {} 303 304 static ConstantAddress invalid() { 305 return ConstantAddress(nullptr); 306 } 307 308 llvm::Constant *getPointer() const { 309 return llvm::cast<llvm::Constant>(RawAddress::getPointer()); 310 } 311 312 ConstantAddress withElementType(llvm::Type *ElemTy) const { 313 return ConstantAddress(getPointer(), ElemTy, getAlignment()); 314 } 315 316 static bool isaImpl(RawAddress addr) { 317 return llvm::isa<llvm::Constant>(addr.getPointer()); 318 } 319 static ConstantAddress castImpl(RawAddress addr) { 320 return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()), 321 addr.getElementType(), addr.getAlignment()); 322 } 323 }; 324 } 325 326 // Present a minimal LLVM-like casting interface. 327 template <class U> inline U cast(CodeGen::Address addr) { 328 return U::castImpl(addr); 329 } 330 template <class U> inline bool isa(CodeGen::Address addr) { 331 return U::isaImpl(addr); 332 } 333 334 } 335 336 #endif 337