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
23namespace clang {
24namespace CodeGen {
25
26class Address;
27class CGBuilderTy;
28class CodeGenFunction;
29class CodeGenModule;
30
31// Indicates whether a pointer is known not to be null.
32enum 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.
41class RawAddress {
42 llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull;
43 llvm::Type *ElementType;
44 CharUnits Alignment;
45
46protected:
47 RawAddress(std::nullptr_t) : ElementType(nullptr) {}
48
49public:
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.
111class 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
129protected:
130 Address(std::nullptr_t) : ElementType(nullptr) {}
131
132public:
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
251inline 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.
260class ConstantAddress : public RawAddress {
261 ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {}
262
263public:
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.
291template <class U> inline U cast(CodeGen::Address addr) {
292 return U::castImpl(addr);
293}
294template <class U> inline bool isa(CodeGen::Address addr) {
295 return U::isaImpl(addr);
296}
297
298}
299
300#endif
301

source code of clang/lib/CodeGen/Address.h