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>(Val: 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 | /// This function is used in situations where the caller is doing some sort of |
180 | /// opaque "laundering" of the pointer. |
181 | void replaceBasePointer(llvm::Value *P) { |
182 | assert(isValid() && "pointer isn't valid" ); |
183 | assert(P->getType() == Pointer.getPointer()->getType() && |
184 | "Pointer's type changed" ); |
185 | Pointer.setPointer(P); |
186 | assert(isValid() && "pointer is invalid after replacement" ); |
187 | } |
188 | |
189 | CharUnits getAlignment() const { return Alignment; } |
190 | |
191 | void setAlignment(CharUnits Value) { Alignment = Value; } |
192 | |
193 | llvm::Value *getBasePointer() const { |
194 | assert(isValid() && "pointer isn't valid" ); |
195 | return Pointer.getPointer(); |
196 | } |
197 | |
198 | /// Return the type of the pointer value. |
199 | llvm::PointerType *getType() const { |
200 | return llvm::PointerType::get( |
201 | ElementType, |
202 | AddressSpace: llvm::cast<llvm::PointerType>(Val: Pointer.getPointer()->getType()) |
203 | ->getAddressSpace()); |
204 | } |
205 | |
206 | /// Return the type of the values stored in this address. |
207 | llvm::Type *getElementType() const { |
208 | assert(isValid()); |
209 | return ElementType; |
210 | } |
211 | |
212 | /// Return the address space that this address resides in. |
213 | unsigned getAddressSpace() const { return getType()->getAddressSpace(); } |
214 | |
215 | /// Return the IR name of the pointer value. |
216 | llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } |
217 | |
218 | const CGPointerAuthInfo &getPointerAuthInfo() const { return PtrAuthInfo; } |
219 | void setPointerAuthInfo(const CGPointerAuthInfo &Info) { PtrAuthInfo = Info; } |
220 | |
221 | // This function is called only in CGBuilderBaseTy::CreateElementBitCast. |
222 | void setElementType(llvm::Type *Ty) { |
223 | assert(hasOffset() && |
224 | "this funcion shouldn't be called when there is no offset" ); |
225 | ElementType = Ty; |
226 | } |
227 | |
228 | bool isSigned() const { return PtrAuthInfo.isSigned(); } |
229 | |
230 | /// Whether the pointer is known not to be null. |
231 | KnownNonNull_t isKnownNonNull() const { |
232 | assert(isValid()); |
233 | return (KnownNonNull_t)Pointer.getInt(); |
234 | } |
235 | |
236 | Address setKnownNonNull() { |
237 | assert(isValid()); |
238 | Pointer.setInt(KnownNonNull); |
239 | return *this; |
240 | } |
241 | |
242 | bool hasOffset() const { return Offset; } |
243 | |
244 | llvm::Value *getOffset() const { return Offset; } |
245 | |
246 | Address getResignedAddress(const CGPointerAuthInfo &NewInfo, |
247 | CodeGenFunction &CGF) const; |
248 | |
249 | /// Return the pointer contained in this class after authenticating it and |
250 | /// adding offset to it if necessary. |
251 | llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { |
252 | if (!isSigned()) |
253 | return getBasePointer(); |
254 | return emitRawPointerSlow(CGF); |
255 | } |
256 | |
257 | /// Return address with different pointer, but same element type and |
258 | /// alignment. |
259 | Address withPointer(llvm::Value *NewPointer, |
260 | KnownNonNull_t IsKnownNonNull) const { |
261 | return Address(NewPointer, getElementType(), getAlignment(), |
262 | IsKnownNonNull); |
263 | } |
264 | |
265 | /// Return address with different alignment, but same pointer and element |
266 | /// type. |
267 | Address withAlignment(CharUnits NewAlignment) const { |
268 | return Address(Pointer.getPointer(), getElementType(), NewAlignment, |
269 | isKnownNonNull()); |
270 | } |
271 | |
272 | /// Return address with different element type, but same pointer and |
273 | /// alignment. |
274 | Address withElementType(llvm::Type *ElemTy) const { |
275 | if (!hasOffset()) |
276 | return Address(getBasePointer(), ElemTy, getAlignment(), |
277 | getPointerAuthInfo(), /*Offset=*/nullptr, |
278 | isKnownNonNull()); |
279 | Address A(*this); |
280 | A.ElementType = ElemTy; |
281 | return A; |
282 | } |
283 | }; |
284 | |
285 | inline RawAddress::RawAddress(Address Addr) |
286 | : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, |
287 | Addr.isValid() ? Addr.isKnownNonNull() |
288 | : NotKnownNonNull), |
289 | ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), |
290 | Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} |
291 | |
292 | /// A specialization of Address that requires the address to be an |
293 | /// LLVM Constant. |
294 | class ConstantAddress : public RawAddress { |
295 | ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} |
296 | |
297 | public: |
298 | ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, |
299 | CharUnits alignment) |
300 | : RawAddress(pointer, elementType, alignment) {} |
301 | |
302 | static ConstantAddress invalid() { |
303 | return ConstantAddress(nullptr); |
304 | } |
305 | |
306 | llvm::Constant *getPointer() const { |
307 | return llvm::cast<llvm::Constant>(Val: RawAddress::getPointer()); |
308 | } |
309 | |
310 | ConstantAddress withElementType(llvm::Type *ElemTy) const { |
311 | return ConstantAddress(getPointer(), ElemTy, getAlignment()); |
312 | } |
313 | |
314 | static bool isaImpl(RawAddress addr) { |
315 | return llvm::isa<llvm::Constant>(Val: addr.getPointer()); |
316 | } |
317 | static ConstantAddress castImpl(RawAddress addr) { |
318 | return ConstantAddress(llvm::cast<llvm::Constant>(Val: addr.getPointer()), |
319 | addr.getElementType(), addr.getAlignment()); |
320 | } |
321 | }; |
322 | } |
323 | |
324 | // Present a minimal LLVM-like casting interface. |
325 | template <class U> inline U cast(CodeGen::Address addr) { |
326 | return U::castImpl(addr); |
327 | } |
328 | template <class U> inline bool isa(CodeGen::Address addr) { |
329 | return U::isaImpl(addr); |
330 | } |
331 | |
332 | } |
333 | |
334 | #endif |
335 | |