1515#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
1616
1717#include " clang/AST/CharUnits.h"
18+ #include " clang/AST/Type.h"
1819#include " llvm/ADT/PointerIntPair.h"
1920#include " llvm/IR/Constants.h"
2021#include " llvm/Support/MathExtras.h"
2122
2223namespace clang {
2324namespace CodeGen {
2425
26+ class Address ;
27+ class CGBuilderTy ;
28+ class CodeGenFunction ;
29+ class CodeGenModule ;
30+
2531// Indicates whether a pointer is known not to be null.
2632enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };
2733
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 {
3042 llvm::PointerIntPair<llvm::Value *, 1 , bool > PointerAndKnownNonNull;
3143 llvm::Type *ElementType;
3244 CharUnits Alignment;
3345
3446protected:
35- Address (std::nullptr_t ) : ElementType(nullptr ) {}
47+ RawAddress (std::nullptr_t ) : ElementType(nullptr ) {}
3648
3749public:
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)
4052 : PointerAndKnownNonNull(Pointer, IsKnownNonNull),
4153 ElementType (ElementType), Alignment(Alignment) {
4254 assert (Pointer != nullptr && " Pointer cannot be null" );
4355 assert (ElementType != nullptr && " Element type cannot be null" );
4456 }
4557
46- static Address invalid () { return Address (nullptr ); }
58+ inline RawAddress (Address Addr);
59+
60+ static RawAddress invalid () { return RawAddress (nullptr ); }
4761 bool isValid () const {
4862 return PointerAndKnownNonNull.getPointer () != nullptr ;
4963 }
@@ -80,6 +94,133 @@ class Address {
8094 return Alignment;
8195 }
8296
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+ llvm::cast<llvm::PointerType>(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+
83224 // / Return address with different pointer, but same element type and
84225 // / alignment.
85226 Address withPointer (llvm::Value *NewPointer,
@@ -91,61 +232,59 @@ class Address {
91232 // / Return address with different alignment, but same pointer and element
92233 // / type.
93234 Address withAlignment (CharUnits NewAlignment) const {
94- return Address (getPointer (), getElementType (), NewAlignment,
235+ return Address (Pointer. getPointer (), getElementType (), NewAlignment,
95236 isKnownNonNull ());
96237 }
97238
98239 // / Return address with different element type, but same pointer and
99240 // / alignment.
100241 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 ;
242+ if (!hasOffset ())
243+ return Address (getBasePointer (), ElemTy, getAlignment (), nullptr ,
244+ isKnownNonNull ());
245+ Address A (*this );
246+ A.ElementType = ElemTy;
247+ return A;
115248 }
116249};
117250
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+
118258// / A specialization of Address that requires the address to be an
119259// / LLVM Constant.
120- class ConstantAddress : public Address {
121- ConstantAddress (std::nullptr_t ) : Address (nullptr ) {}
260+ class ConstantAddress : public RawAddress {
261+ ConstantAddress (std::nullptr_t ) : RawAddress (nullptr ) {}
122262
123263public:
124264 ConstantAddress (llvm::Constant *pointer, llvm::Type *elementType,
125265 CharUnits alignment)
126- : Address (pointer, elementType, alignment) {}
266+ : RawAddress (pointer, elementType, alignment) {}
127267
128268 static ConstantAddress invalid () {
129269 return ConstantAddress (nullptr );
130270 }
131271
132272 llvm::Constant *getPointer () const {
133- return llvm::cast<llvm::Constant>(Address ::getPointer ());
273+ return llvm::cast<llvm::Constant>(RawAddress ::getPointer ());
134274 }
135275
136276 ConstantAddress withElementType (llvm::Type *ElemTy) const {
137277 return ConstantAddress (getPointer (), ElemTy, getAlignment ());
138278 }
139279
140- static bool isaImpl (Address addr) {
280+ static bool isaImpl (RawAddress addr) {
141281 return llvm::isa<llvm::Constant>(addr.getPointer ());
142282 }
143- static ConstantAddress castImpl (Address addr) {
283+ static ConstantAddress castImpl (RawAddress addr) {
144284 return ConstantAddress (llvm::cast<llvm::Constant>(addr.getPointer ()),
145285 addr.getElementType (), addr.getAlignment ());
146286 }
147287};
148-
149288}
150289
151290// Present a minimal LLVM-like casting interface.
0 commit comments