xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Address.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- Address.h - An aligned address -------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class provides a simple wrapper for a pair of a pointer and an
100b57cec5SDimitry Andric // alignment.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
150b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
160b57cec5SDimitry Andric 
17*0fca6ea1SDimitry Andric #include "CGPointerAuthInfo.h"
180b57cec5SDimitry Andric #include "clang/AST/CharUnits.h"
19*0fca6ea1SDimitry Andric #include "clang/AST/Type.h"
2004eeddc0SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
2104eeddc0SDimitry Andric #include "llvm/IR/Constants.h"
2204eeddc0SDimitry Andric #include "llvm/Support/MathExtras.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace clang {
250b57cec5SDimitry Andric namespace CodeGen {
260b57cec5SDimitry Andric 
27*0fca6ea1SDimitry Andric class Address;
28*0fca6ea1SDimitry Andric class CGBuilderTy;
29*0fca6ea1SDimitry Andric class CodeGenFunction;
30*0fca6ea1SDimitry Andric class CodeGenModule;
31*0fca6ea1SDimitry Andric 
3206c3fb27SDimitry Andric // Indicates whether a pointer is known not to be null.
3306c3fb27SDimitry Andric enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };
3404eeddc0SDimitry Andric 
35*0fca6ea1SDimitry Andric /// An abstract representation of an aligned address. This is designed to be an
36*0fca6ea1SDimitry Andric /// IR-level abstraction, carrying just the information necessary to perform IR
37*0fca6ea1SDimitry Andric /// operations on an address like loads and stores.  In particular, it doesn't
38*0fca6ea1SDimitry Andric /// carry C type information or allow the representation of things like
39*0fca6ea1SDimitry Andric /// bit-fields; clients working at that level should generally be using
40*0fca6ea1SDimitry Andric /// `LValue`.
41*0fca6ea1SDimitry Andric /// The pointer contained in this class is known to be unsigned.
42*0fca6ea1SDimitry Andric class RawAddress {
4306c3fb27SDimitry Andric   llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull;
4406c3fb27SDimitry Andric   llvm::Type *ElementType;
4506c3fb27SDimitry Andric   CharUnits Alignment;
4604eeddc0SDimitry Andric 
4704eeddc0SDimitry Andric protected:
48*0fca6ea1SDimitry Andric   RawAddress(std::nullptr_t) : ElementType(nullptr) {}
4904eeddc0SDimitry Andric 
5004eeddc0SDimitry Andric public:
51*0fca6ea1SDimitry Andric   RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,
5206c3fb27SDimitry Andric              KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
5306c3fb27SDimitry Andric       : PointerAndKnownNonNull(Pointer, IsKnownNonNull),
5406c3fb27SDimitry Andric         ElementType(ElementType), Alignment(Alignment) {
5504eeddc0SDimitry Andric     assert(Pointer != nullptr && "Pointer cannot be null");
5604eeddc0SDimitry Andric     assert(ElementType != nullptr && "Element type cannot be null");
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric 
59*0fca6ea1SDimitry Andric   inline RawAddress(Address Addr);
60*0fca6ea1SDimitry Andric 
61*0fca6ea1SDimitry Andric   static RawAddress invalid() { return RawAddress(nullptr); }
6206c3fb27SDimitry Andric   bool isValid() const {
6306c3fb27SDimitry Andric     return PointerAndKnownNonNull.getPointer() != nullptr;
6406c3fb27SDimitry Andric   }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   llvm::Value *getPointer() const {
670b57cec5SDimitry Andric     assert(isValid());
6806c3fb27SDimitry Andric     return PointerAndKnownNonNull.getPointer();
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   /// Return the type of the pointer value.
720b57cec5SDimitry Andric   llvm::PointerType *getType() const {
730b57cec5SDimitry Andric     return llvm::cast<llvm::PointerType>(getPointer()->getType());
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   /// Return the type of the values stored in this address.
770b57cec5SDimitry Andric   llvm::Type *getElementType() const {
780eae32dcSDimitry Andric     assert(isValid());
7906c3fb27SDimitry Andric     return ElementType;
800b57cec5SDimitry Andric   }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   /// Return the address space that this address resides in.
830b57cec5SDimitry Andric   unsigned getAddressSpace() const {
840b57cec5SDimitry Andric     return getType()->getAddressSpace();
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// Return the IR name of the pointer value.
880b57cec5SDimitry Andric   llvm::StringRef getName() const {
890b57cec5SDimitry Andric     return getPointer()->getName();
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   /// Return the alignment of this pointer.
930b57cec5SDimitry Andric   CharUnits getAlignment() const {
940b57cec5SDimitry Andric     assert(isValid());
9506c3fb27SDimitry Andric     return Alignment;
960b57cec5SDimitry Andric   }
970eae32dcSDimitry Andric 
98*0fca6ea1SDimitry Andric   /// Return address with different element type, but same pointer and
99*0fca6ea1SDimitry Andric   /// alignment.
100*0fca6ea1SDimitry Andric   RawAddress withElementType(llvm::Type *ElemTy) const {
101*0fca6ea1SDimitry Andric     return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull());
102*0fca6ea1SDimitry Andric   }
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric   KnownNonNull_t isKnownNonNull() const {
105*0fca6ea1SDimitry Andric     assert(isValid());
106*0fca6ea1SDimitry Andric     return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
107*0fca6ea1SDimitry Andric   }
108*0fca6ea1SDimitry Andric };
109*0fca6ea1SDimitry Andric 
110*0fca6ea1SDimitry Andric /// Like RawAddress, an abstract representation of an aligned address, but the
111*0fca6ea1SDimitry Andric /// pointer contained in this class is possibly signed.
112*0fca6ea1SDimitry Andric ///
113*0fca6ea1SDimitry Andric /// This is designed to be an IR-level abstraction, carrying just the
114*0fca6ea1SDimitry Andric /// information necessary to perform IR operations on an address like loads and
115*0fca6ea1SDimitry Andric /// stores.  In particular, it doesn't carry C type information or allow the
116*0fca6ea1SDimitry Andric /// representation of things like bit-fields; clients working at that level
117*0fca6ea1SDimitry Andric /// should generally be using `LValue`.
118*0fca6ea1SDimitry Andric ///
119*0fca6ea1SDimitry Andric /// An address may be either *raw*, meaning that it's an ordinary machine
120*0fca6ea1SDimitry Andric /// pointer, or *signed*, meaning that the pointer carries an embedded
121*0fca6ea1SDimitry Andric /// pointer-authentication signature. Representing signed pointers directly in
122*0fca6ea1SDimitry Andric /// this abstraction allows the authentication to be delayed as long as possible
123*0fca6ea1SDimitry Andric /// without forcing IRGen to use totally different code paths for signed and
124*0fca6ea1SDimitry Andric /// unsigned values or to separately propagate signature information through
125*0fca6ea1SDimitry Andric /// every API that manipulates addresses. Pointer arithmetic on signed addresses
126*0fca6ea1SDimitry Andric /// (e.g. drilling down to a struct field) is accumulated into a separate offset
127*0fca6ea1SDimitry Andric /// which is applied when the address is finally accessed.
128*0fca6ea1SDimitry Andric class Address {
129*0fca6ea1SDimitry Andric   friend class CGBuilderTy;
130*0fca6ea1SDimitry Andric 
131*0fca6ea1SDimitry Andric   // The boolean flag indicates whether the pointer is known to be non-null.
132*0fca6ea1SDimitry Andric   llvm::PointerIntPair<llvm::Value *, 1, bool> Pointer;
133*0fca6ea1SDimitry Andric 
134*0fca6ea1SDimitry Andric   /// The expected IR type of the pointer. Carrying accurate element type
135*0fca6ea1SDimitry Andric   /// information in Address makes it more convenient to work with Address
136*0fca6ea1SDimitry Andric   /// values and allows frontend assertions to catch simple mistakes.
137*0fca6ea1SDimitry Andric   llvm::Type *ElementType = nullptr;
138*0fca6ea1SDimitry Andric 
139*0fca6ea1SDimitry Andric   CharUnits Alignment;
140*0fca6ea1SDimitry Andric 
141*0fca6ea1SDimitry Andric   /// The ptrauth information needed to authenticate the base pointer.
142*0fca6ea1SDimitry Andric   CGPointerAuthInfo PtrAuthInfo;
143*0fca6ea1SDimitry Andric 
144*0fca6ea1SDimitry Andric   /// Offset from the base pointer. This is non-null only when the base
145*0fca6ea1SDimitry Andric   /// pointer is signed.
146*0fca6ea1SDimitry Andric   llvm::Value *Offset = nullptr;
147*0fca6ea1SDimitry Andric 
148*0fca6ea1SDimitry Andric   llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const;
149*0fca6ea1SDimitry Andric 
150*0fca6ea1SDimitry Andric protected:
151*0fca6ea1SDimitry Andric   Address(std::nullptr_t) : ElementType(nullptr) {}
152*0fca6ea1SDimitry Andric 
153*0fca6ea1SDimitry Andric public:
154*0fca6ea1SDimitry Andric   Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment,
155*0fca6ea1SDimitry Andric           KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
156*0fca6ea1SDimitry Andric       : Pointer(pointer, IsKnownNonNull), ElementType(elementType),
157*0fca6ea1SDimitry Andric         Alignment(alignment) {
158*0fca6ea1SDimitry Andric     assert(pointer != nullptr && "Pointer cannot be null");
159*0fca6ea1SDimitry Andric     assert(elementType != nullptr && "Element type cannot be null");
160*0fca6ea1SDimitry Andric     assert(!alignment.isZero() && "Alignment cannot be zero");
161*0fca6ea1SDimitry Andric   }
162*0fca6ea1SDimitry Andric 
163*0fca6ea1SDimitry Andric   Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment,
164*0fca6ea1SDimitry Andric           CGPointerAuthInfo PtrAuthInfo, llvm::Value *Offset,
165*0fca6ea1SDimitry Andric           KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
166*0fca6ea1SDimitry Andric       : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType),
167*0fca6ea1SDimitry Andric         Alignment(Alignment), PtrAuthInfo(PtrAuthInfo), Offset(Offset) {}
168*0fca6ea1SDimitry Andric 
169*0fca6ea1SDimitry Andric   Address(RawAddress RawAddr)
170*0fca6ea1SDimitry Andric       : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr,
171*0fca6ea1SDimitry Andric                 RawAddr.isValid() ? RawAddr.isKnownNonNull() : NotKnownNonNull),
172*0fca6ea1SDimitry Andric         ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr),
173*0fca6ea1SDimitry Andric         Alignment(RawAddr.isValid() ? RawAddr.getAlignment()
174*0fca6ea1SDimitry Andric                                     : CharUnits::Zero()) {}
175*0fca6ea1SDimitry Andric 
176*0fca6ea1SDimitry Andric   static Address invalid() { return Address(nullptr); }
177*0fca6ea1SDimitry Andric   bool isValid() const { return Pointer.getPointer() != nullptr; }
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric   /// This function is used in situations where the caller is doing some sort of
180*0fca6ea1SDimitry Andric   /// opaque "laundering" of the pointer.
181*0fca6ea1SDimitry Andric   void replaceBasePointer(llvm::Value *P) {
182*0fca6ea1SDimitry Andric     assert(isValid() && "pointer isn't valid");
183*0fca6ea1SDimitry Andric     assert(P->getType() == Pointer.getPointer()->getType() &&
184*0fca6ea1SDimitry Andric            "Pointer's type changed");
185*0fca6ea1SDimitry Andric     Pointer.setPointer(P);
186*0fca6ea1SDimitry Andric     assert(isValid() && "pointer is invalid after replacement");
187*0fca6ea1SDimitry Andric   }
188*0fca6ea1SDimitry Andric 
189*0fca6ea1SDimitry Andric   CharUnits getAlignment() const { return Alignment; }
190*0fca6ea1SDimitry Andric 
191*0fca6ea1SDimitry Andric   void setAlignment(CharUnits Value) { Alignment = Value; }
192*0fca6ea1SDimitry Andric 
193*0fca6ea1SDimitry Andric   llvm::Value *getBasePointer() const {
194*0fca6ea1SDimitry Andric     assert(isValid() && "pointer isn't valid");
195*0fca6ea1SDimitry Andric     return Pointer.getPointer();
196*0fca6ea1SDimitry Andric   }
197*0fca6ea1SDimitry Andric 
198*0fca6ea1SDimitry Andric   /// Return the type of the pointer value.
199*0fca6ea1SDimitry Andric   llvm::PointerType *getType() const {
200*0fca6ea1SDimitry Andric     return llvm::PointerType::get(
201*0fca6ea1SDimitry Andric         ElementType,
202*0fca6ea1SDimitry Andric         llvm::cast<llvm::PointerType>(Pointer.getPointer()->getType())
203*0fca6ea1SDimitry Andric             ->getAddressSpace());
204*0fca6ea1SDimitry Andric   }
205*0fca6ea1SDimitry Andric 
206*0fca6ea1SDimitry Andric   /// Return the type of the values stored in this address.
207*0fca6ea1SDimitry Andric   llvm::Type *getElementType() const {
208*0fca6ea1SDimitry Andric     assert(isValid());
209*0fca6ea1SDimitry Andric     return ElementType;
210*0fca6ea1SDimitry Andric   }
211*0fca6ea1SDimitry Andric 
212*0fca6ea1SDimitry Andric   /// Return the address space that this address resides in.
213*0fca6ea1SDimitry Andric   unsigned getAddressSpace() const { return getType()->getAddressSpace(); }
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric   /// Return the IR name of the pointer value.
216*0fca6ea1SDimitry Andric   llvm::StringRef getName() const { return Pointer.getPointer()->getName(); }
217*0fca6ea1SDimitry Andric 
218*0fca6ea1SDimitry Andric   const CGPointerAuthInfo &getPointerAuthInfo() const { return PtrAuthInfo; }
219*0fca6ea1SDimitry Andric   void setPointerAuthInfo(const CGPointerAuthInfo &Info) { PtrAuthInfo = Info; }
220*0fca6ea1SDimitry Andric 
221*0fca6ea1SDimitry Andric   // This function is called only in CGBuilderBaseTy::CreateElementBitCast.
222*0fca6ea1SDimitry Andric   void setElementType(llvm::Type *Ty) {
223*0fca6ea1SDimitry Andric     assert(hasOffset() &&
224*0fca6ea1SDimitry Andric            "this funcion shouldn't be called when there is no offset");
225*0fca6ea1SDimitry Andric     ElementType = Ty;
226*0fca6ea1SDimitry Andric   }
227*0fca6ea1SDimitry Andric 
228*0fca6ea1SDimitry Andric   bool isSigned() const { return PtrAuthInfo.isSigned(); }
229*0fca6ea1SDimitry Andric 
230*0fca6ea1SDimitry Andric   /// Whether the pointer is known not to be null.
231*0fca6ea1SDimitry Andric   KnownNonNull_t isKnownNonNull() const {
232*0fca6ea1SDimitry Andric     assert(isValid());
233*0fca6ea1SDimitry Andric     return (KnownNonNull_t)Pointer.getInt();
234*0fca6ea1SDimitry Andric   }
235*0fca6ea1SDimitry Andric 
236*0fca6ea1SDimitry Andric   Address setKnownNonNull() {
237*0fca6ea1SDimitry Andric     assert(isValid());
238*0fca6ea1SDimitry Andric     Pointer.setInt(KnownNonNull);
239*0fca6ea1SDimitry Andric     return *this;
240*0fca6ea1SDimitry Andric   }
241*0fca6ea1SDimitry Andric 
242*0fca6ea1SDimitry Andric   bool hasOffset() const { return Offset; }
243*0fca6ea1SDimitry Andric 
244*0fca6ea1SDimitry Andric   llvm::Value *getOffset() const { return Offset; }
245*0fca6ea1SDimitry Andric 
246*0fca6ea1SDimitry Andric   Address getResignedAddress(const CGPointerAuthInfo &NewInfo,
247*0fca6ea1SDimitry Andric                              CodeGenFunction &CGF) const;
248*0fca6ea1SDimitry Andric 
249*0fca6ea1SDimitry Andric   /// Return the pointer contained in this class after authenticating it and
250*0fca6ea1SDimitry Andric   /// adding offset to it if necessary.
251*0fca6ea1SDimitry Andric   llvm::Value *emitRawPointer(CodeGenFunction &CGF) const {
252*0fca6ea1SDimitry Andric     if (!isSigned())
253*0fca6ea1SDimitry Andric       return getBasePointer();
254*0fca6ea1SDimitry Andric     return emitRawPointerSlow(CGF);
255*0fca6ea1SDimitry Andric   }
256*0fca6ea1SDimitry Andric 
2570eae32dcSDimitry Andric   /// Return address with different pointer, but same element type and
2580eae32dcSDimitry Andric   /// alignment.
25906c3fb27SDimitry Andric   Address withPointer(llvm::Value *NewPointer,
26006c3fb27SDimitry Andric                       KnownNonNull_t IsKnownNonNull) const {
26106c3fb27SDimitry Andric     return Address(NewPointer, getElementType(), getAlignment(),
26206c3fb27SDimitry Andric                    IsKnownNonNull);
2630eae32dcSDimitry Andric   }
2640eae32dcSDimitry Andric 
2650eae32dcSDimitry Andric   /// Return address with different alignment, but same pointer and element
2660eae32dcSDimitry Andric   /// type.
2670eae32dcSDimitry Andric   Address withAlignment(CharUnits NewAlignment) const {
268*0fca6ea1SDimitry Andric     return Address(Pointer.getPointer(), getElementType(), NewAlignment,
26906c3fb27SDimitry Andric                    isKnownNonNull());
27006c3fb27SDimitry Andric   }
27106c3fb27SDimitry Andric 
27206c3fb27SDimitry Andric   /// Return address with different element type, but same pointer and
27306c3fb27SDimitry Andric   /// alignment.
27406c3fb27SDimitry Andric   Address withElementType(llvm::Type *ElemTy) const {
275*0fca6ea1SDimitry Andric     if (!hasOffset())
276*0fca6ea1SDimitry Andric       return Address(getBasePointer(), ElemTy, getAlignment(),
277*0fca6ea1SDimitry Andric                      getPointerAuthInfo(), /*Offset=*/nullptr,
278*0fca6ea1SDimitry Andric                      isKnownNonNull());
279*0fca6ea1SDimitry Andric     Address A(*this);
280*0fca6ea1SDimitry Andric     A.ElementType = ElemTy;
281*0fca6ea1SDimitry Andric     return A;
2820eae32dcSDimitry Andric   }
2830b57cec5SDimitry Andric };
2840b57cec5SDimitry Andric 
285*0fca6ea1SDimitry Andric inline RawAddress::RawAddress(Address Addr)
286*0fca6ea1SDimitry Andric     : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr,
287*0fca6ea1SDimitry Andric                              Addr.isValid() ? Addr.isKnownNonNull()
288*0fca6ea1SDimitry Andric                                             : NotKnownNonNull),
289*0fca6ea1SDimitry Andric       ElementType(Addr.isValid() ? Addr.getElementType() : nullptr),
290*0fca6ea1SDimitry Andric       Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}
291*0fca6ea1SDimitry Andric 
2920b57cec5SDimitry Andric /// A specialization of Address that requires the address to be an
2930b57cec5SDimitry Andric /// LLVM Constant.
294*0fca6ea1SDimitry Andric class ConstantAddress : public RawAddress {
295*0fca6ea1SDimitry Andric   ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {}
2960eae32dcSDimitry Andric 
2970b57cec5SDimitry Andric public:
2980eae32dcSDimitry Andric   ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType,
2990eae32dcSDimitry Andric                   CharUnits alignment)
300*0fca6ea1SDimitry Andric       : RawAddress(pointer, elementType, alignment) {}
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   static ConstantAddress invalid() {
3030eae32dcSDimitry Andric     return ConstantAddress(nullptr);
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   llvm::Constant *getPointer() const {
307*0fca6ea1SDimitry Andric     return llvm::cast<llvm::Constant>(RawAddress::getPointer());
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric 
31006c3fb27SDimitry Andric   ConstantAddress withElementType(llvm::Type *ElemTy) const {
31106c3fb27SDimitry Andric     return ConstantAddress(getPointer(), ElemTy, getAlignment());
3120b57cec5SDimitry Andric   }
3130b57cec5SDimitry Andric 
314*0fca6ea1SDimitry Andric   static bool isaImpl(RawAddress addr) {
3150b57cec5SDimitry Andric     return llvm::isa<llvm::Constant>(addr.getPointer());
3160b57cec5SDimitry Andric   }
317*0fca6ea1SDimitry Andric   static ConstantAddress castImpl(RawAddress addr) {
3180b57cec5SDimitry Andric     return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
3190eae32dcSDimitry Andric                            addr.getElementType(), addr.getAlignment());
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric };
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric // Present a minimal LLVM-like casting interface.
3250b57cec5SDimitry Andric template <class U> inline U cast(CodeGen::Address addr) {
3260b57cec5SDimitry Andric   return U::castImpl(addr);
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric template <class U> inline bool isa(CodeGen::Address addr) {
3290b57cec5SDimitry Andric   return U::isaImpl(addr);
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric #endif
335