xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/CGPointerAuth.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===--- CGPointerAuth.cpp - IR generation for pointer authentication -----===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file contains common routines relating to the emission of
10*0fca6ea1SDimitry Andric // pointer authentication operations.
11*0fca6ea1SDimitry Andric //
12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
13*0fca6ea1SDimitry Andric 
14*0fca6ea1SDimitry Andric #include "CodeGenFunction.h"
15*0fca6ea1SDimitry Andric #include "CodeGenModule.h"
16*0fca6ea1SDimitry Andric #include "clang/CodeGen/CodeGenABITypes.h"
17*0fca6ea1SDimitry Andric #include "clang/CodeGen/ConstantInitBuilder.h"
18*0fca6ea1SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
19*0fca6ea1SDimitry Andric #include "llvm/Support/SipHash.h"
20*0fca6ea1SDimitry Andric 
21*0fca6ea1SDimitry Andric using namespace clang;
22*0fca6ea1SDimitry Andric using namespace CodeGen;
23*0fca6ea1SDimitry Andric 
24*0fca6ea1SDimitry Andric /// Given a pointer-authentication schema, return a concrete "other"
25*0fca6ea1SDimitry Andric /// discriminator for it.
26*0fca6ea1SDimitry Andric llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator(
27*0fca6ea1SDimitry Andric     const PointerAuthSchema &Schema, GlobalDecl Decl, QualType Type) {
28*0fca6ea1SDimitry Andric   switch (Schema.getOtherDiscrimination()) {
29*0fca6ea1SDimitry Andric   case PointerAuthSchema::Discrimination::None:
30*0fca6ea1SDimitry Andric     return nullptr;
31*0fca6ea1SDimitry Andric 
32*0fca6ea1SDimitry Andric   case PointerAuthSchema::Discrimination::Type:
33*0fca6ea1SDimitry Andric     assert(!Type.isNull() && "type not provided for type-discriminated schema");
34*0fca6ea1SDimitry Andric     return llvm::ConstantInt::get(
35*0fca6ea1SDimitry Andric         IntPtrTy, getContext().getPointerAuthTypeDiscriminator(Type));
36*0fca6ea1SDimitry Andric 
37*0fca6ea1SDimitry Andric   case PointerAuthSchema::Discrimination::Decl:
38*0fca6ea1SDimitry Andric     assert(Decl.getDecl() &&
39*0fca6ea1SDimitry Andric            "declaration not provided for decl-discriminated schema");
40*0fca6ea1SDimitry Andric     return llvm::ConstantInt::get(IntPtrTy,
41*0fca6ea1SDimitry Andric                                   getPointerAuthDeclDiscriminator(Decl));
42*0fca6ea1SDimitry Andric 
43*0fca6ea1SDimitry Andric   case PointerAuthSchema::Discrimination::Constant:
44*0fca6ea1SDimitry Andric     return llvm::ConstantInt::get(IntPtrTy, Schema.getConstantDiscrimination());
45*0fca6ea1SDimitry Andric   }
46*0fca6ea1SDimitry Andric   llvm_unreachable("bad discrimination kind");
47*0fca6ea1SDimitry Andric }
48*0fca6ea1SDimitry Andric 
49*0fca6ea1SDimitry Andric uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
50*0fca6ea1SDimitry Andric                                                   QualType FunctionType) {
51*0fca6ea1SDimitry Andric   return CGM.getContext().getPointerAuthTypeDiscriminator(FunctionType);
52*0fca6ea1SDimitry Andric }
53*0fca6ea1SDimitry Andric 
54*0fca6ea1SDimitry Andric uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule &CGM,
55*0fca6ea1SDimitry Andric                                                   GlobalDecl Declaration) {
56*0fca6ea1SDimitry Andric   return CGM.getPointerAuthDeclDiscriminator(Declaration);
57*0fca6ea1SDimitry Andric }
58*0fca6ea1SDimitry Andric 
59*0fca6ea1SDimitry Andric /// Return the "other" decl-specific discriminator for the given decl.
60*0fca6ea1SDimitry Andric uint16_t
61*0fca6ea1SDimitry Andric CodeGenModule::getPointerAuthDeclDiscriminator(GlobalDecl Declaration) {
62*0fca6ea1SDimitry Andric   uint16_t &EntityHash = PtrAuthDiscriminatorHashes[Declaration];
63*0fca6ea1SDimitry Andric 
64*0fca6ea1SDimitry Andric   if (EntityHash == 0) {
65*0fca6ea1SDimitry Andric     StringRef Name = getMangledName(Declaration);
66*0fca6ea1SDimitry Andric     EntityHash = llvm::getPointerAuthStableSipHash(Name);
67*0fca6ea1SDimitry Andric   }
68*0fca6ea1SDimitry Andric 
69*0fca6ea1SDimitry Andric   return EntityHash;
70*0fca6ea1SDimitry Andric }
71*0fca6ea1SDimitry Andric 
72*0fca6ea1SDimitry Andric /// Return the abstract pointer authentication schema for a pointer to the given
73*0fca6ea1SDimitry Andric /// function type.
74*0fca6ea1SDimitry Andric CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
75*0fca6ea1SDimitry Andric   const auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
76*0fca6ea1SDimitry Andric   if (!Schema)
77*0fca6ea1SDimitry Andric     return CGPointerAuthInfo();
78*0fca6ea1SDimitry Andric 
79*0fca6ea1SDimitry Andric   assert(!Schema.isAddressDiscriminated() &&
80*0fca6ea1SDimitry Andric          "function pointers cannot use address-specific discrimination");
81*0fca6ea1SDimitry Andric 
82*0fca6ea1SDimitry Andric   llvm::Constant *Discriminator = nullptr;
83*0fca6ea1SDimitry Andric   if (T->isFunctionPointerType() || T->isFunctionReferenceType())
84*0fca6ea1SDimitry Andric     T = T->getPointeeType();
85*0fca6ea1SDimitry Andric   if (T->isFunctionType())
86*0fca6ea1SDimitry Andric     Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T);
87*0fca6ea1SDimitry Andric 
88*0fca6ea1SDimitry Andric   return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
89*0fca6ea1SDimitry Andric                            /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
90*0fca6ea1SDimitry Andric                            Discriminator);
91*0fca6ea1SDimitry Andric }
92*0fca6ea1SDimitry Andric 
93*0fca6ea1SDimitry Andric llvm::Value *
94*0fca6ea1SDimitry Andric CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress,
95*0fca6ea1SDimitry Andric                                                    llvm::Value *Discriminator) {
96*0fca6ea1SDimitry Andric   StorageAddress = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
97*0fca6ea1SDimitry Andric   auto Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend);
98*0fca6ea1SDimitry Andric   return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
99*0fca6ea1SDimitry Andric }
100*0fca6ea1SDimitry Andric 
101*0fca6ea1SDimitry Andric /// Emit the concrete pointer authentication informaton for the
102*0fca6ea1SDimitry Andric /// given authentication schema.
103*0fca6ea1SDimitry Andric CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo(
104*0fca6ea1SDimitry Andric     const PointerAuthSchema &Schema, llvm::Value *StorageAddress,
105*0fca6ea1SDimitry Andric     GlobalDecl SchemaDecl, QualType SchemaType) {
106*0fca6ea1SDimitry Andric   if (!Schema)
107*0fca6ea1SDimitry Andric     return CGPointerAuthInfo();
108*0fca6ea1SDimitry Andric 
109*0fca6ea1SDimitry Andric   llvm::Value *Discriminator =
110*0fca6ea1SDimitry Andric       CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
111*0fca6ea1SDimitry Andric 
112*0fca6ea1SDimitry Andric   if (Schema.isAddressDiscriminated()) {
113*0fca6ea1SDimitry Andric     assert(StorageAddress &&
114*0fca6ea1SDimitry Andric            "address not provided for address-discriminated schema");
115*0fca6ea1SDimitry Andric 
116*0fca6ea1SDimitry Andric     if (Discriminator)
117*0fca6ea1SDimitry Andric       Discriminator =
118*0fca6ea1SDimitry Andric           EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
119*0fca6ea1SDimitry Andric     else
120*0fca6ea1SDimitry Andric       Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
121*0fca6ea1SDimitry Andric   }
122*0fca6ea1SDimitry Andric 
123*0fca6ea1SDimitry Andric   return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
124*0fca6ea1SDimitry Andric                            Schema.isIsaPointer(),
125*0fca6ea1SDimitry Andric                            Schema.authenticatesNullValues(), Discriminator);
126*0fca6ea1SDimitry Andric }
127*0fca6ea1SDimitry Andric 
128*0fca6ea1SDimitry Andric /// Return the natural pointer authentication for values of the given
129*0fca6ea1SDimitry Andric /// pointee type.
130*0fca6ea1SDimitry Andric static CGPointerAuthInfo
131*0fca6ea1SDimitry Andric getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType) {
132*0fca6ea1SDimitry Andric   if (PointeeType.isNull())
133*0fca6ea1SDimitry Andric     return CGPointerAuthInfo();
134*0fca6ea1SDimitry Andric 
135*0fca6ea1SDimitry Andric   // Function pointers use the function-pointer schema by default.
136*0fca6ea1SDimitry Andric   if (PointeeType->isFunctionType())
137*0fca6ea1SDimitry Andric     return CGM.getFunctionPointerAuthInfo(PointeeType);
138*0fca6ea1SDimitry Andric 
139*0fca6ea1SDimitry Andric   // Normal data pointers never use direct pointer authentication by default.
140*0fca6ea1SDimitry Andric   return CGPointerAuthInfo();
141*0fca6ea1SDimitry Andric }
142*0fca6ea1SDimitry Andric 
143*0fca6ea1SDimitry Andric CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) {
144*0fca6ea1SDimitry Andric   return ::getPointerAuthInfoForPointeeType(*this, T);
145*0fca6ea1SDimitry Andric }
146*0fca6ea1SDimitry Andric 
147*0fca6ea1SDimitry Andric /// Return the natural pointer authentication for values of the given
148*0fca6ea1SDimitry Andric /// pointer type.
149*0fca6ea1SDimitry Andric static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM,
150*0fca6ea1SDimitry Andric                                                    QualType PointerType) {
151*0fca6ea1SDimitry Andric   assert(PointerType->isSignableType());
152*0fca6ea1SDimitry Andric 
153*0fca6ea1SDimitry Andric   // Block pointers are currently not signed.
154*0fca6ea1SDimitry Andric   if (PointerType->isBlockPointerType())
155*0fca6ea1SDimitry Andric     return CGPointerAuthInfo();
156*0fca6ea1SDimitry Andric 
157*0fca6ea1SDimitry Andric   auto PointeeType = PointerType->getPointeeType();
158*0fca6ea1SDimitry Andric 
159*0fca6ea1SDimitry Andric   if (PointeeType.isNull())
160*0fca6ea1SDimitry Andric     return CGPointerAuthInfo();
161*0fca6ea1SDimitry Andric 
162*0fca6ea1SDimitry Andric   return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
163*0fca6ea1SDimitry Andric }
164*0fca6ea1SDimitry Andric 
165*0fca6ea1SDimitry Andric CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) {
166*0fca6ea1SDimitry Andric   return ::getPointerAuthInfoForType(*this, T);
167*0fca6ea1SDimitry Andric }
168*0fca6ea1SDimitry Andric 
169*0fca6ea1SDimitry Andric static bool isZeroConstant(const llvm::Value *Value) {
170*0fca6ea1SDimitry Andric   if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value))
171*0fca6ea1SDimitry Andric     return CI->isZero();
172*0fca6ea1SDimitry Andric   return false;
173*0fca6ea1SDimitry Andric }
174*0fca6ea1SDimitry Andric 
175*0fca6ea1SDimitry Andric static bool equalAuthPolicies(const CGPointerAuthInfo &Left,
176*0fca6ea1SDimitry Andric                               const CGPointerAuthInfo &Right) {
177*0fca6ea1SDimitry Andric   assert((Left.isSigned() || Right.isSigned()) &&
178*0fca6ea1SDimitry Andric          "shouldn't be called if neither is signed");
179*0fca6ea1SDimitry Andric   if (Left.isSigned() != Right.isSigned())
180*0fca6ea1SDimitry Andric     return false;
181*0fca6ea1SDimitry Andric   return Left.getKey() == Right.getKey() &&
182*0fca6ea1SDimitry Andric          Left.getAuthenticationMode() == Right.getAuthenticationMode();
183*0fca6ea1SDimitry Andric }
184*0fca6ea1SDimitry Andric 
185*0fca6ea1SDimitry Andric // Return the discriminator or return zero if the discriminator is null.
186*0fca6ea1SDimitry Andric static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info,
187*0fca6ea1SDimitry Andric                                            CGBuilderTy &Builder) {
188*0fca6ea1SDimitry Andric   llvm::Value *Discriminator = Info.getDiscriminator();
189*0fca6ea1SDimitry Andric   return Discriminator ? Discriminator : Builder.getSize(0);
190*0fca6ea1SDimitry Andric }
191*0fca6ea1SDimitry Andric 
192*0fca6ea1SDimitry Andric llvm::Value *
193*0fca6ea1SDimitry Andric CodeGenFunction::emitPointerAuthResignCall(llvm::Value *Value,
194*0fca6ea1SDimitry Andric                                            const CGPointerAuthInfo &CurAuth,
195*0fca6ea1SDimitry Andric                                            const CGPointerAuthInfo &NewAuth) {
196*0fca6ea1SDimitry Andric   assert(CurAuth && NewAuth);
197*0fca6ea1SDimitry Andric 
198*0fca6ea1SDimitry Andric   if (CurAuth.getAuthenticationMode() !=
199*0fca6ea1SDimitry Andric           PointerAuthenticationMode::SignAndAuth ||
200*0fca6ea1SDimitry Andric       NewAuth.getAuthenticationMode() !=
201*0fca6ea1SDimitry Andric           PointerAuthenticationMode::SignAndAuth) {
202*0fca6ea1SDimitry Andric     llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value);
203*0fca6ea1SDimitry Andric     return EmitPointerAuthSign(NewAuth, AuthedValue);
204*0fca6ea1SDimitry Andric   }
205*0fca6ea1SDimitry Andric   // Convert the pointer to intptr_t before signing it.
206*0fca6ea1SDimitry Andric   auto *OrigType = Value->getType();
207*0fca6ea1SDimitry Andric   Value = Builder.CreatePtrToInt(Value, IntPtrTy);
208*0fca6ea1SDimitry Andric 
209*0fca6ea1SDimitry Andric   auto *CurKey = Builder.getInt32(CurAuth.getKey());
210*0fca6ea1SDimitry Andric   auto *NewKey = Builder.getInt32(NewAuth.getKey());
211*0fca6ea1SDimitry Andric 
212*0fca6ea1SDimitry Andric   llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder);
213*0fca6ea1SDimitry Andric   llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder);
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric   // call i64 @llvm.ptrauth.resign(i64 %pointer,
216*0fca6ea1SDimitry Andric   //                               i32 %curKey, i64 %curDiscriminator,
217*0fca6ea1SDimitry Andric   //                               i32 %newKey, i64 %newDiscriminator)
218*0fca6ea1SDimitry Andric   auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
219*0fca6ea1SDimitry Andric   Value = EmitRuntimeCall(
220*0fca6ea1SDimitry Andric       Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
221*0fca6ea1SDimitry Andric 
222*0fca6ea1SDimitry Andric   // Convert back to the original type.
223*0fca6ea1SDimitry Andric   Value = Builder.CreateIntToPtr(Value, OrigType);
224*0fca6ea1SDimitry Andric   return Value;
225*0fca6ea1SDimitry Andric }
226*0fca6ea1SDimitry Andric 
227*0fca6ea1SDimitry Andric llvm::Value *CodeGenFunction::emitPointerAuthResign(
228*0fca6ea1SDimitry Andric     llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo,
229*0fca6ea1SDimitry Andric     const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) {
230*0fca6ea1SDimitry Andric   // Fast path: if neither schema wants a signature, we're done.
231*0fca6ea1SDimitry Andric   if (!CurAuthInfo && !NewAuthInfo)
232*0fca6ea1SDimitry Andric     return Value;
233*0fca6ea1SDimitry Andric 
234*0fca6ea1SDimitry Andric   llvm::Value *Null = nullptr;
235*0fca6ea1SDimitry Andric   // If the value is obviously null, we're done.
236*0fca6ea1SDimitry Andric   if (auto *PointerValue = dyn_cast<llvm::PointerType>(Value->getType())) {
237*0fca6ea1SDimitry Andric     Null = CGM.getNullPointer(PointerValue, Type);
238*0fca6ea1SDimitry Andric   } else {
239*0fca6ea1SDimitry Andric     assert(Value->getType()->isIntegerTy());
240*0fca6ea1SDimitry Andric     Null = llvm::ConstantInt::get(IntPtrTy, 0);
241*0fca6ea1SDimitry Andric   }
242*0fca6ea1SDimitry Andric   if (Value == Null)
243*0fca6ea1SDimitry Andric     return Value;
244*0fca6ea1SDimitry Andric 
245*0fca6ea1SDimitry Andric   // If both schemas sign the same way, we're done.
246*0fca6ea1SDimitry Andric   if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) {
247*0fca6ea1SDimitry Andric     const llvm::Value *CurD = CurAuthInfo.getDiscriminator();
248*0fca6ea1SDimitry Andric     const llvm::Value *NewD = NewAuthInfo.getDiscriminator();
249*0fca6ea1SDimitry Andric     if (CurD == NewD)
250*0fca6ea1SDimitry Andric       return Value;
251*0fca6ea1SDimitry Andric 
252*0fca6ea1SDimitry Andric     if ((CurD == nullptr && isZeroConstant(NewD)) ||
253*0fca6ea1SDimitry Andric         (NewD == nullptr && isZeroConstant(CurD)))
254*0fca6ea1SDimitry Andric       return Value;
255*0fca6ea1SDimitry Andric   }
256*0fca6ea1SDimitry Andric 
257*0fca6ea1SDimitry Andric   llvm::BasicBlock *InitBB = Builder.GetInsertBlock();
258*0fca6ea1SDimitry Andric   llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr;
259*0fca6ea1SDimitry Andric 
260*0fca6ea1SDimitry Andric   // Null pointers have to be mapped to null, and the ptrauth_resign
261*0fca6ea1SDimitry Andric   // intrinsic doesn't do that.
262*0fca6ea1SDimitry Andric   if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) {
263*0fca6ea1SDimitry Andric     ContBB = createBasicBlock("resign.cont");
264*0fca6ea1SDimitry Andric     ResignBB = createBasicBlock("resign.nonnull");
265*0fca6ea1SDimitry Andric 
266*0fca6ea1SDimitry Andric     auto *IsNonNull = Builder.CreateICmpNE(Value, Null);
267*0fca6ea1SDimitry Andric     Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
268*0fca6ea1SDimitry Andric     EmitBlock(ResignBB);
269*0fca6ea1SDimitry Andric   }
270*0fca6ea1SDimitry Andric 
271*0fca6ea1SDimitry Andric   // Perform the auth/sign/resign operation.
272*0fca6ea1SDimitry Andric   if (!NewAuthInfo)
273*0fca6ea1SDimitry Andric     Value = EmitPointerAuthAuth(CurAuthInfo, Value);
274*0fca6ea1SDimitry Andric   else if (!CurAuthInfo)
275*0fca6ea1SDimitry Andric     Value = EmitPointerAuthSign(NewAuthInfo, Value);
276*0fca6ea1SDimitry Andric   else
277*0fca6ea1SDimitry Andric     Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo);
278*0fca6ea1SDimitry Andric 
279*0fca6ea1SDimitry Andric   // Clean up with a phi if we branched before.
280*0fca6ea1SDimitry Andric   if (ContBB) {
281*0fca6ea1SDimitry Andric     EmitBlock(ContBB);
282*0fca6ea1SDimitry Andric     auto *Phi = Builder.CreatePHI(Value->getType(), 2);
283*0fca6ea1SDimitry Andric     Phi->addIncoming(Null, InitBB);
284*0fca6ea1SDimitry Andric     Phi->addIncoming(Value, ResignBB);
285*0fca6ea1SDimitry Andric     Value = Phi;
286*0fca6ea1SDimitry Andric   }
287*0fca6ea1SDimitry Andric 
288*0fca6ea1SDimitry Andric   return Value;
289*0fca6ea1SDimitry Andric }
290*0fca6ea1SDimitry Andric 
291*0fca6ea1SDimitry Andric llvm::Constant *
292*0fca6ea1SDimitry Andric CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key,
293*0fca6ea1SDimitry Andric                                         llvm::Constant *StorageAddress,
294*0fca6ea1SDimitry Andric                                         llvm::ConstantInt *OtherDiscriminator) {
295*0fca6ea1SDimitry Andric   llvm::Constant *AddressDiscriminator;
296*0fca6ea1SDimitry Andric   if (StorageAddress) {
297*0fca6ea1SDimitry Andric     assert(StorageAddress->getType() == UnqualPtrTy);
298*0fca6ea1SDimitry Andric     AddressDiscriminator = StorageAddress;
299*0fca6ea1SDimitry Andric   } else {
300*0fca6ea1SDimitry Andric     AddressDiscriminator = llvm::Constant::getNullValue(UnqualPtrTy);
301*0fca6ea1SDimitry Andric   }
302*0fca6ea1SDimitry Andric 
303*0fca6ea1SDimitry Andric   llvm::ConstantInt *IntegerDiscriminator;
304*0fca6ea1SDimitry Andric   if (OtherDiscriminator) {
305*0fca6ea1SDimitry Andric     assert(OtherDiscriminator->getType() == Int64Ty);
306*0fca6ea1SDimitry Andric     IntegerDiscriminator = OtherDiscriminator;
307*0fca6ea1SDimitry Andric   } else {
308*0fca6ea1SDimitry Andric     IntegerDiscriminator = llvm::ConstantInt::get(Int64Ty, 0);
309*0fca6ea1SDimitry Andric   }
310*0fca6ea1SDimitry Andric 
311*0fca6ea1SDimitry Andric   return llvm::ConstantPtrAuth::get(Pointer,
312*0fca6ea1SDimitry Andric                                     llvm::ConstantInt::get(Int32Ty, Key),
313*0fca6ea1SDimitry Andric                                     IntegerDiscriminator, AddressDiscriminator);
314*0fca6ea1SDimitry Andric }
315*0fca6ea1SDimitry Andric 
316*0fca6ea1SDimitry Andric /// Does a given PointerAuthScheme require us to sign a value
317*0fca6ea1SDimitry Andric bool CodeGenModule::shouldSignPointer(const PointerAuthSchema &Schema) {
318*0fca6ea1SDimitry Andric   auto AuthenticationMode = Schema.getAuthenticationMode();
319*0fca6ea1SDimitry Andric   return AuthenticationMode == PointerAuthenticationMode::SignAndStrip ||
320*0fca6ea1SDimitry Andric          AuthenticationMode == PointerAuthenticationMode::SignAndAuth;
321*0fca6ea1SDimitry Andric }
322*0fca6ea1SDimitry Andric 
323*0fca6ea1SDimitry Andric /// Sign a constant pointer using the given scheme, producing a constant
324*0fca6ea1SDimitry Andric /// with the same IR type.
325*0fca6ea1SDimitry Andric llvm::Constant *CodeGenModule::getConstantSignedPointer(
326*0fca6ea1SDimitry Andric     llvm::Constant *Pointer, const PointerAuthSchema &Schema,
327*0fca6ea1SDimitry Andric     llvm::Constant *StorageAddress, GlobalDecl SchemaDecl,
328*0fca6ea1SDimitry Andric     QualType SchemaType) {
329*0fca6ea1SDimitry Andric   assert(shouldSignPointer(Schema));
330*0fca6ea1SDimitry Andric   llvm::ConstantInt *OtherDiscriminator =
331*0fca6ea1SDimitry Andric       getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
332*0fca6ea1SDimitry Andric 
333*0fca6ea1SDimitry Andric   return getConstantSignedPointer(Pointer, Schema.getKey(), StorageAddress,
334*0fca6ea1SDimitry Andric                                   OtherDiscriminator);
335*0fca6ea1SDimitry Andric }
336*0fca6ea1SDimitry Andric 
337*0fca6ea1SDimitry Andric /// If applicable, sign a given constant function pointer with the ABI rules for
338*0fca6ea1SDimitry Andric /// functionType.
339*0fca6ea1SDimitry Andric llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer,
340*0fca6ea1SDimitry Andric                                                   QualType FunctionType) {
341*0fca6ea1SDimitry Andric   assert(FunctionType->isFunctionType() ||
342*0fca6ea1SDimitry Andric          FunctionType->isFunctionReferenceType() ||
343*0fca6ea1SDimitry Andric          FunctionType->isFunctionPointerType());
344*0fca6ea1SDimitry Andric 
345*0fca6ea1SDimitry Andric   if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType))
346*0fca6ea1SDimitry Andric     return getConstantSignedPointer(
347*0fca6ea1SDimitry Andric         Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr,
348*0fca6ea1SDimitry Andric         cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
349*0fca6ea1SDimitry Andric 
350*0fca6ea1SDimitry Andric   return Pointer;
351*0fca6ea1SDimitry Andric }
352*0fca6ea1SDimitry Andric 
353*0fca6ea1SDimitry Andric llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
354*0fca6ea1SDimitry Andric                                                   llvm::Type *Ty) {
355*0fca6ea1SDimitry Andric   const auto *FD = cast<FunctionDecl>(GD.getDecl());
356*0fca6ea1SDimitry Andric   QualType FuncType = FD->getType();
357*0fca6ea1SDimitry Andric 
358*0fca6ea1SDimitry Andric   // Annoyingly, K&R functions have prototypes in the clang AST, but
359*0fca6ea1SDimitry Andric   // expressions referring to them are unprototyped.
360*0fca6ea1SDimitry Andric   if (!FD->hasPrototype())
361*0fca6ea1SDimitry Andric     if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
362*0fca6ea1SDimitry Andric       FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
363*0fca6ea1SDimitry Andric                                                 Proto->getExtInfo());
364*0fca6ea1SDimitry Andric 
365*0fca6ea1SDimitry Andric   return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType);
366*0fca6ea1SDimitry Andric }
367*0fca6ea1SDimitry Andric 
368*0fca6ea1SDimitry Andric CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) {
369*0fca6ea1SDimitry Andric   assert(FT->getAs<MemberPointerType>() && "MemberPointerType expected");
370*0fca6ea1SDimitry Andric   const auto &Schema = getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
371*0fca6ea1SDimitry Andric   if (!Schema)
372*0fca6ea1SDimitry Andric     return CGPointerAuthInfo();
373*0fca6ea1SDimitry Andric 
374*0fca6ea1SDimitry Andric   assert(!Schema.isAddressDiscriminated() &&
375*0fca6ea1SDimitry Andric          "function pointers cannot use address-specific discrimination");
376*0fca6ea1SDimitry Andric 
377*0fca6ea1SDimitry Andric   llvm::ConstantInt *Discriminator =
378*0fca6ea1SDimitry Andric       getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), FT);
379*0fca6ea1SDimitry Andric   return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
380*0fca6ea1SDimitry Andric                            /* IsIsaPointer */ false,
381*0fca6ea1SDimitry Andric                            /* AuthenticatesNullValues */ false, Discriminator);
382*0fca6ea1SDimitry Andric }
383*0fca6ea1SDimitry Andric 
384*0fca6ea1SDimitry Andric llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer,
385*0fca6ea1SDimitry Andric                                                         QualType FT) {
386*0fca6ea1SDimitry Andric   if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT))
387*0fca6ea1SDimitry Andric     return getConstantSignedPointer(
388*0fca6ea1SDimitry Andric         Pointer, PointerAuth.getKey(), nullptr,
389*0fca6ea1SDimitry Andric         cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
390*0fca6ea1SDimitry Andric 
391*0fca6ea1SDimitry Andric   return Pointer;
392*0fca6ea1SDimitry Andric }
393*0fca6ea1SDimitry Andric 
394*0fca6ea1SDimitry Andric llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD,
395*0fca6ea1SDimitry Andric                                                         llvm::Type *Ty) {
396*0fca6ea1SDimitry Andric   QualType FT = FD->getType();
397*0fca6ea1SDimitry Andric   FT = getContext().getMemberPointerType(
398*0fca6ea1SDimitry Andric       FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl());
399*0fca6ea1SDimitry Andric   return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT);
400*0fca6ea1SDimitry Andric }
401*0fca6ea1SDimitry Andric 
402*0fca6ea1SDimitry Andric std::optional<PointerAuthQualifier>
403*0fca6ea1SDimitry Andric CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) {
404*0fca6ea1SDimitry Andric   auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers;
405*0fca6ea1SDimitry Andric   if (!DefaultAuthentication)
406*0fca6ea1SDimitry Andric     return std::nullopt;
407*0fca6ea1SDimitry Andric   const CXXRecordDecl *PrimaryBase =
408*0fca6ea1SDimitry Andric       Context.baseForVTableAuthentication(ThisClass);
409*0fca6ea1SDimitry Andric 
410*0fca6ea1SDimitry Andric   unsigned Key = DefaultAuthentication.getKey();
411*0fca6ea1SDimitry Andric   bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
412*0fca6ea1SDimitry Andric   auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
413*0fca6ea1SDimitry Andric   unsigned TypeBasedDiscriminator =
414*0fca6ea1SDimitry Andric       Context.getPointerAuthVTablePointerDiscriminator(PrimaryBase);
415*0fca6ea1SDimitry Andric   unsigned Discriminator;
416*0fca6ea1SDimitry Andric   if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) {
417*0fca6ea1SDimitry Andric     Discriminator = TypeBasedDiscriminator;
418*0fca6ea1SDimitry Andric   } else if (DefaultDiscrimination ==
419*0fca6ea1SDimitry Andric              PointerAuthSchema::Discrimination::Constant) {
420*0fca6ea1SDimitry Andric     Discriminator = DefaultAuthentication.getConstantDiscrimination();
421*0fca6ea1SDimitry Andric   } else {
422*0fca6ea1SDimitry Andric     assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None);
423*0fca6ea1SDimitry Andric     Discriminator = 0;
424*0fca6ea1SDimitry Andric   }
425*0fca6ea1SDimitry Andric   if (auto ExplicitAuthentication =
426*0fca6ea1SDimitry Andric           PrimaryBase->getAttr<VTablePointerAuthenticationAttr>()) {
427*0fca6ea1SDimitry Andric     auto ExplicitAddressDiscrimination =
428*0fca6ea1SDimitry Andric         ExplicitAuthentication->getAddressDiscrimination();
429*0fca6ea1SDimitry Andric     auto ExplicitDiscriminator =
430*0fca6ea1SDimitry Andric         ExplicitAuthentication->getExtraDiscrimination();
431*0fca6ea1SDimitry Andric 
432*0fca6ea1SDimitry Andric     unsigned ExplicitKey = ExplicitAuthentication->getKey();
433*0fca6ea1SDimitry Andric     if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
434*0fca6ea1SDimitry Andric       return std::nullopt;
435*0fca6ea1SDimitry Andric 
436*0fca6ea1SDimitry Andric     if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
437*0fca6ea1SDimitry Andric       if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
438*0fca6ea1SDimitry Andric         Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA;
439*0fca6ea1SDimitry Andric       else {
440*0fca6ea1SDimitry Andric         assert(ExplicitKey ==
441*0fca6ea1SDimitry Andric                VTablePointerAuthenticationAttr::ProcessDependent);
442*0fca6ea1SDimitry Andric         Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB;
443*0fca6ea1SDimitry Andric       }
444*0fca6ea1SDimitry Andric     }
445*0fca6ea1SDimitry Andric 
446*0fca6ea1SDimitry Andric     if (ExplicitAddressDiscrimination !=
447*0fca6ea1SDimitry Andric         VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
448*0fca6ea1SDimitry Andric       AddressDiscriminated =
449*0fca6ea1SDimitry Andric           ExplicitAddressDiscrimination ==
450*0fca6ea1SDimitry Andric           VTablePointerAuthenticationAttr::AddressDiscrimination;
451*0fca6ea1SDimitry Andric 
452*0fca6ea1SDimitry Andric     if (ExplicitDiscriminator ==
453*0fca6ea1SDimitry Andric         VTablePointerAuthenticationAttr::TypeDiscrimination)
454*0fca6ea1SDimitry Andric       Discriminator = TypeBasedDiscriminator;
455*0fca6ea1SDimitry Andric     else if (ExplicitDiscriminator ==
456*0fca6ea1SDimitry Andric              VTablePointerAuthenticationAttr::CustomDiscrimination)
457*0fca6ea1SDimitry Andric       Discriminator = ExplicitAuthentication->getCustomDiscriminationValue();
458*0fca6ea1SDimitry Andric     else if (ExplicitDiscriminator ==
459*0fca6ea1SDimitry Andric              VTablePointerAuthenticationAttr::NoExtraDiscrimination)
460*0fca6ea1SDimitry Andric       Discriminator = 0;
461*0fca6ea1SDimitry Andric   }
462*0fca6ea1SDimitry Andric   return PointerAuthQualifier::Create(Key, AddressDiscriminated, Discriminator,
463*0fca6ea1SDimitry Andric                                       PointerAuthenticationMode::SignAndAuth,
464*0fca6ea1SDimitry Andric                                       /* IsIsaPointer */ false,
465*0fca6ea1SDimitry Andric                                       /* AuthenticatesNullValues */ false);
466*0fca6ea1SDimitry Andric }
467*0fca6ea1SDimitry Andric 
468*0fca6ea1SDimitry Andric std::optional<PointerAuthQualifier>
469*0fca6ea1SDimitry Andric CodeGenModule::getVTablePointerAuthentication(const CXXRecordDecl *Record) {
470*0fca6ea1SDimitry Andric   if (!Record->getDefinition() || !Record->isPolymorphic())
471*0fca6ea1SDimitry Andric     return std::nullopt;
472*0fca6ea1SDimitry Andric 
473*0fca6ea1SDimitry Andric   auto Existing = VTablePtrAuthInfos.find(Record);
474*0fca6ea1SDimitry Andric   std::optional<PointerAuthQualifier> Authentication;
475*0fca6ea1SDimitry Andric   if (Existing != VTablePtrAuthInfos.end()) {
476*0fca6ea1SDimitry Andric     Authentication = Existing->getSecond();
477*0fca6ea1SDimitry Andric   } else {
478*0fca6ea1SDimitry Andric     Authentication = computeVTPointerAuthentication(Record);
479*0fca6ea1SDimitry Andric     VTablePtrAuthInfos.insert(std::make_pair(Record, Authentication));
480*0fca6ea1SDimitry Andric   }
481*0fca6ea1SDimitry Andric   return Authentication;
482*0fca6ea1SDimitry Andric }
483*0fca6ea1SDimitry Andric 
484*0fca6ea1SDimitry Andric std::optional<CGPointerAuthInfo>
485*0fca6ea1SDimitry Andric CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF,
486*0fca6ea1SDimitry Andric                                         const CXXRecordDecl *Record,
487*0fca6ea1SDimitry Andric                                         llvm::Value *StorageAddress) {
488*0fca6ea1SDimitry Andric   auto Authentication = getVTablePointerAuthentication(Record);
489*0fca6ea1SDimitry Andric   if (!Authentication)
490*0fca6ea1SDimitry Andric     return std::nullopt;
491*0fca6ea1SDimitry Andric 
492*0fca6ea1SDimitry Andric   llvm::Value *Discriminator = nullptr;
493*0fca6ea1SDimitry Andric   if (auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
494*0fca6ea1SDimitry Andric     Discriminator = llvm::ConstantInt::get(IntPtrTy, ExtraDiscriminator);
495*0fca6ea1SDimitry Andric 
496*0fca6ea1SDimitry Andric   if (Authentication->isAddressDiscriminated()) {
497*0fca6ea1SDimitry Andric     assert(StorageAddress &&
498*0fca6ea1SDimitry Andric            "address not provided for address-discriminated schema");
499*0fca6ea1SDimitry Andric     if (Discriminator)
500*0fca6ea1SDimitry Andric       Discriminator =
501*0fca6ea1SDimitry Andric           CGF->EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
502*0fca6ea1SDimitry Andric     else
503*0fca6ea1SDimitry Andric       Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
504*0fca6ea1SDimitry Andric   }
505*0fca6ea1SDimitry Andric 
506*0fca6ea1SDimitry Andric   return CGPointerAuthInfo(Authentication->getKey(),
507*0fca6ea1SDimitry Andric                            PointerAuthenticationMode::SignAndAuth,
508*0fca6ea1SDimitry Andric                            /* IsIsaPointer */ false,
509*0fca6ea1SDimitry Andric                            /* AuthenticatesNullValues */ false, Discriminator);
510*0fca6ea1SDimitry Andric }
511*0fca6ea1SDimitry Andric 
512*0fca6ea1SDimitry Andric llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr,
513*0fca6ea1SDimitry Andric                                                        QualType SourceType,
514*0fca6ea1SDimitry Andric                                                        QualType DestType) {
515*0fca6ea1SDimitry Andric   CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
516*0fca6ea1SDimitry Andric   if (SourceType->isSignableType())
517*0fca6ea1SDimitry Andric     CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
518*0fca6ea1SDimitry Andric 
519*0fca6ea1SDimitry Andric   if (DestType->isSignableType())
520*0fca6ea1SDimitry Andric     NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
521*0fca6ea1SDimitry Andric 
522*0fca6ea1SDimitry Andric   if (!CurAuthInfo && !NewAuthInfo)
523*0fca6ea1SDimitry Andric     return ResultPtr;
524*0fca6ea1SDimitry Andric 
525*0fca6ea1SDimitry Andric   // If only one side of the cast is a function pointer, then we still need to
526*0fca6ea1SDimitry Andric   // resign to handle casts to/from opaque pointers.
527*0fca6ea1SDimitry Andric   if (!CurAuthInfo && DestType->isFunctionPointerType())
528*0fca6ea1SDimitry Andric     CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType);
529*0fca6ea1SDimitry Andric 
530*0fca6ea1SDimitry Andric   if (!NewAuthInfo && SourceType->isFunctionPointerType())
531*0fca6ea1SDimitry Andric     NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
532*0fca6ea1SDimitry Andric 
533*0fca6ea1SDimitry Andric   return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo,
534*0fca6ea1SDimitry Andric                                /*IsKnownNonNull=*/false);
535*0fca6ea1SDimitry Andric }
536*0fca6ea1SDimitry Andric 
537*0fca6ea1SDimitry Andric Address CodeGenFunction::authPointerToPointerCast(Address Ptr,
538*0fca6ea1SDimitry Andric                                                   QualType SourceType,
539*0fca6ea1SDimitry Andric                                                   QualType DestType) {
540*0fca6ea1SDimitry Andric   CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
541*0fca6ea1SDimitry Andric   if (SourceType->isSignableType())
542*0fca6ea1SDimitry Andric     CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
543*0fca6ea1SDimitry Andric 
544*0fca6ea1SDimitry Andric   if (DestType->isSignableType())
545*0fca6ea1SDimitry Andric     NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
546*0fca6ea1SDimitry Andric 
547*0fca6ea1SDimitry Andric   if (!CurAuthInfo && !NewAuthInfo)
548*0fca6ea1SDimitry Andric     return Ptr;
549*0fca6ea1SDimitry Andric 
550*0fca6ea1SDimitry Andric   if (!CurAuthInfo && DestType->isFunctionPointerType()) {
551*0fca6ea1SDimitry Andric     // When casting a non-signed pointer to a function pointer, just set the
552*0fca6ea1SDimitry Andric     // auth info on Ptr to the assumed schema. The pointer will be resigned to
553*0fca6ea1SDimitry Andric     // the effective type when used.
554*0fca6ea1SDimitry Andric     Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType));
555*0fca6ea1SDimitry Andric     return Ptr;
556*0fca6ea1SDimitry Andric   }
557*0fca6ea1SDimitry Andric 
558*0fca6ea1SDimitry Andric   if (!NewAuthInfo && SourceType->isFunctionPointerType()) {
559*0fca6ea1SDimitry Andric     NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
560*0fca6ea1SDimitry Andric     Ptr = Ptr.getResignedAddress(NewAuthInfo, *this);
561*0fca6ea1SDimitry Andric     Ptr.setPointerAuthInfo(CGPointerAuthInfo());
562*0fca6ea1SDimitry Andric     return Ptr;
563*0fca6ea1SDimitry Andric   }
564*0fca6ea1SDimitry Andric 
565*0fca6ea1SDimitry Andric   return Ptr;
566*0fca6ea1SDimitry Andric }
567*0fca6ea1SDimitry Andric 
568*0fca6ea1SDimitry Andric Address CodeGenFunction::getAsNaturalAddressOf(Address Addr,
569*0fca6ea1SDimitry Andric                                                QualType PointeeTy) {
570*0fca6ea1SDimitry Andric   CGPointerAuthInfo Info =
571*0fca6ea1SDimitry Andric       PointeeTy.isNull() ? CGPointerAuthInfo()
572*0fca6ea1SDimitry Andric                          : CGM.getPointerAuthInfoForPointeeType(PointeeTy);
573*0fca6ea1SDimitry Andric   return Addr.getResignedAddress(Info, *this);
574*0fca6ea1SDimitry Andric }
575*0fca6ea1SDimitry Andric 
576*0fca6ea1SDimitry Andric Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo,
577*0fca6ea1SDimitry Andric                                     CodeGenFunction &CGF) const {
578*0fca6ea1SDimitry Andric   assert(isValid() && "pointer isn't valid");
579*0fca6ea1SDimitry Andric   CGPointerAuthInfo CurInfo = getPointerAuthInfo();
580*0fca6ea1SDimitry Andric   llvm::Value *Val;
581*0fca6ea1SDimitry Andric 
582*0fca6ea1SDimitry Andric   // Nothing to do if neither the current or the new ptrauth info needs signing.
583*0fca6ea1SDimitry Andric   if (!CurInfo.isSigned() && !NewInfo.isSigned())
584*0fca6ea1SDimitry Andric     return Address(getBasePointer(), getElementType(), getAlignment(),
585*0fca6ea1SDimitry Andric                    isKnownNonNull());
586*0fca6ea1SDimitry Andric 
587*0fca6ea1SDimitry Andric   assert(ElementType && "Effective type has to be set");
588*0fca6ea1SDimitry Andric   assert(!Offset && "unexpected non-null offset");
589*0fca6ea1SDimitry Andric 
590*0fca6ea1SDimitry Andric   // If the current and the new ptrauth infos are the same and the offset is
591*0fca6ea1SDimitry Andric   // null, just cast the base pointer to the effective type.
592*0fca6ea1SDimitry Andric   if (CurInfo == NewInfo && !hasOffset())
593*0fca6ea1SDimitry Andric     Val = getBasePointer();
594*0fca6ea1SDimitry Andric   else
595*0fca6ea1SDimitry Andric     Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo,
596*0fca6ea1SDimitry Andric                                     NewInfo, isKnownNonNull());
597*0fca6ea1SDimitry Andric 
598*0fca6ea1SDimitry Andric   Val = CGF.Builder.CreateBitCast(Val, getType());
599*0fca6ea1SDimitry Andric   return Address(Val, getElementType(), getAlignment(), NewInfo,
600*0fca6ea1SDimitry Andric                  /*Offset=*/nullptr, isKnownNonNull());
601*0fca6ea1SDimitry Andric }
602*0fca6ea1SDimitry Andric 
603*0fca6ea1SDimitry Andric llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const {
604*0fca6ea1SDimitry Andric   return CGF.getAsNaturalPointerTo(*this, QualType());
605*0fca6ea1SDimitry Andric }
606*0fca6ea1SDimitry Andric 
607*0fca6ea1SDimitry Andric llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const {
608*0fca6ea1SDimitry Andric   assert(isSimple());
609*0fca6ea1SDimitry Andric   return emitResignedPointer(getType(), CGF);
610*0fca6ea1SDimitry Andric }
611*0fca6ea1SDimitry Andric 
612*0fca6ea1SDimitry Andric llvm::Value *LValue::emitResignedPointer(QualType PointeeTy,
613*0fca6ea1SDimitry Andric                                          CodeGenFunction &CGF) const {
614*0fca6ea1SDimitry Andric   assert(isSimple());
615*0fca6ea1SDimitry Andric   return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer();
616*0fca6ea1SDimitry Andric }
617*0fca6ea1SDimitry Andric 
618*0fca6ea1SDimitry Andric llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const {
619*0fca6ea1SDimitry Andric   assert(isSimple());
620*0fca6ea1SDimitry Andric   return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr;
621*0fca6ea1SDimitry Andric }
622