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