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