1 //===--- CGPointerAuth.cpp - IR generation for pointer authentication -----===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains common routines relating to the emission of
10 // pointer authentication operations.
12 //===----------------------------------------------------------------------===//
14 #include "CodeGenFunction.h"
15 #include "CodeGenModule.h"
16 #include "clang/CodeGen/CodeGenABITypes.h"
17 #include "clang/CodeGen/ConstantInitBuilder.h"
18 #include "llvm/Analysis/ValueTracking.h"
19 #include "llvm/Support/SipHash.h"
21 using namespace clang
;
22 using namespace CodeGen
;
24 /// Given a pointer-authentication schema, return a concrete "other"
25 /// discriminator for it.
26 llvm::ConstantInt
*CodeGenModule::getPointerAuthOtherDiscriminator(
27 const PointerAuthSchema
&Schema
, GlobalDecl Decl
, QualType Type
) {
28 switch (Schema
.getOtherDiscrimination()) {
29 case PointerAuthSchema::Discrimination::None
:
32 case PointerAuthSchema::Discrimination::Type
:
33 assert(!Type
.isNull() && "type not provided for type-discriminated schema");
34 return llvm::ConstantInt::get(
35 IntPtrTy
, getContext().getPointerAuthTypeDiscriminator(Type
));
37 case PointerAuthSchema::Discrimination::Decl
:
38 assert(Decl
.getDecl() &&
39 "declaration not provided for decl-discriminated schema");
40 return llvm::ConstantInt::get(IntPtrTy
,
41 getPointerAuthDeclDiscriminator(Decl
));
43 case PointerAuthSchema::Discrimination::Constant
:
44 return llvm::ConstantInt::get(IntPtrTy
, Schema
.getConstantDiscrimination());
46 llvm_unreachable("bad discrimination kind");
49 uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule
&CGM
,
50 QualType FunctionType
) {
51 return CGM
.getContext().getPointerAuthTypeDiscriminator(FunctionType
);
54 uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule
&CGM
,
55 GlobalDecl Declaration
) {
56 return CGM
.getPointerAuthDeclDiscriminator(Declaration
);
59 /// Return the "other" decl-specific discriminator for the given decl.
61 CodeGenModule::getPointerAuthDeclDiscriminator(GlobalDecl Declaration
) {
62 uint16_t &EntityHash
= PtrAuthDiscriminatorHashes
[Declaration
];
64 if (EntityHash
== 0) {
65 StringRef Name
= getMangledName(Declaration
);
66 EntityHash
= llvm::getPointerAuthStableSipHash(Name
);
72 /// Return the abstract pointer authentication schema for a pointer to the given
74 CGPointerAuthInfo
CodeGenModule::getFunctionPointerAuthInfo(QualType T
) {
75 const auto &Schema
= getCodeGenOpts().PointerAuth
.FunctionPointers
;
77 return CGPointerAuthInfo();
79 assert(!Schema
.isAddressDiscriminated() &&
80 "function pointers cannot use address-specific discrimination");
82 llvm::Constant
*Discriminator
= nullptr;
83 if (T
->isFunctionPointerType() || T
->isFunctionReferenceType())
84 T
= T
->getPointeeType();
85 if (T
->isFunctionType())
86 Discriminator
= getPointerAuthOtherDiscriminator(Schema
, GlobalDecl(), T
);
88 return CGPointerAuthInfo(Schema
.getKey(), Schema
.getAuthenticationMode(),
89 /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
94 CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value
*StorageAddress
,
95 llvm::Value
*Discriminator
) {
96 StorageAddress
= Builder
.CreatePtrToInt(StorageAddress
, IntPtrTy
);
97 auto Intrinsic
= CGM
.getIntrinsic(llvm::Intrinsic::ptrauth_blend
);
98 return Builder
.CreateCall(Intrinsic
, {StorageAddress
, Discriminator
});
101 /// Emit the concrete pointer authentication informaton for the
102 /// given authentication schema.
103 CGPointerAuthInfo
CodeGenFunction::EmitPointerAuthInfo(
104 const PointerAuthSchema
&Schema
, llvm::Value
*StorageAddress
,
105 GlobalDecl SchemaDecl
, QualType SchemaType
) {
107 return CGPointerAuthInfo();
109 llvm::Value
*Discriminator
=
110 CGM
.getPointerAuthOtherDiscriminator(Schema
, SchemaDecl
, SchemaType
);
112 if (Schema
.isAddressDiscriminated()) {
113 assert(StorageAddress
&&
114 "address not provided for address-discriminated schema");
118 EmitPointerAuthBlendDiscriminator(StorageAddress
, Discriminator
);
120 Discriminator
= Builder
.CreatePtrToInt(StorageAddress
, IntPtrTy
);
123 return CGPointerAuthInfo(Schema
.getKey(), Schema
.getAuthenticationMode(),
124 Schema
.isIsaPointer(),
125 Schema
.authenticatesNullValues(), Discriminator
);
128 /// Return the natural pointer authentication for values of the given
130 static CGPointerAuthInfo
131 getPointerAuthInfoForPointeeType(CodeGenModule
&CGM
, QualType PointeeType
) {
132 if (PointeeType
.isNull())
133 return CGPointerAuthInfo();
135 // Function pointers use the function-pointer schema by default.
136 if (PointeeType
->isFunctionType())
137 return CGM
.getFunctionPointerAuthInfo(PointeeType
);
139 // Normal data pointers never use direct pointer authentication by default.
140 return CGPointerAuthInfo();
143 CGPointerAuthInfo
CodeGenModule::getPointerAuthInfoForPointeeType(QualType T
) {
144 return ::getPointerAuthInfoForPointeeType(*this, T
);
147 /// Return the natural pointer authentication for values of the given
149 static CGPointerAuthInfo
getPointerAuthInfoForType(CodeGenModule
&CGM
,
150 QualType PointerType
) {
151 assert(PointerType
->isSignableType());
153 // Block pointers are currently not signed.
154 if (PointerType
->isBlockPointerType())
155 return CGPointerAuthInfo();
157 auto PointeeType
= PointerType
->getPointeeType();
159 if (PointeeType
.isNull())
160 return CGPointerAuthInfo();
162 return ::getPointerAuthInfoForPointeeType(CGM
, PointeeType
);
165 CGPointerAuthInfo
CodeGenModule::getPointerAuthInfoForType(QualType T
) {
166 return ::getPointerAuthInfoForType(*this, T
);
169 static bool isZeroConstant(const llvm::Value
*Value
) {
170 if (const auto *CI
= dyn_cast
<llvm::ConstantInt
>(Value
))
175 static bool equalAuthPolicies(const CGPointerAuthInfo
&Left
,
176 const CGPointerAuthInfo
&Right
) {
177 assert((Left
.isSigned() || Right
.isSigned()) &&
178 "shouldn't be called if neither is signed");
179 if (Left
.isSigned() != Right
.isSigned())
181 return Left
.getKey() == Right
.getKey() &&
182 Left
.getAuthenticationMode() == Right
.getAuthenticationMode();
185 // Return the discriminator or return zero if the discriminator is null.
186 static llvm::Value
*getDiscriminatorOrZero(const CGPointerAuthInfo
&Info
,
187 CGBuilderTy
&Builder
) {
188 llvm::Value
*Discriminator
= Info
.getDiscriminator();
189 return Discriminator
? Discriminator
: Builder
.getSize(0);
193 CodeGenFunction::emitPointerAuthResignCall(llvm::Value
*Value
,
194 const CGPointerAuthInfo
&CurAuth
,
195 const CGPointerAuthInfo
&NewAuth
) {
196 assert(CurAuth
&& NewAuth
);
198 if (CurAuth
.getAuthenticationMode() !=
199 PointerAuthenticationMode::SignAndAuth
||
200 NewAuth
.getAuthenticationMode() !=
201 PointerAuthenticationMode::SignAndAuth
) {
202 llvm::Value
*AuthedValue
= EmitPointerAuthAuth(CurAuth
, Value
);
203 return EmitPointerAuthSign(NewAuth
, AuthedValue
);
205 // Convert the pointer to intptr_t before signing it.
206 auto *OrigType
= Value
->getType();
207 Value
= Builder
.CreatePtrToInt(Value
, IntPtrTy
);
209 auto *CurKey
= Builder
.getInt32(CurAuth
.getKey());
210 auto *NewKey
= Builder
.getInt32(NewAuth
.getKey());
212 llvm::Value
*CurDiscriminator
= getDiscriminatorOrZero(CurAuth
, Builder
);
213 llvm::Value
*NewDiscriminator
= getDiscriminatorOrZero(NewAuth
, Builder
);
215 // call i64 @llvm.ptrauth.resign(i64 %pointer,
216 // i32 %curKey, i64 %curDiscriminator,
217 // i32 %newKey, i64 %newDiscriminator)
218 auto *Intrinsic
= CGM
.getIntrinsic(llvm::Intrinsic::ptrauth_resign
);
219 Value
= EmitRuntimeCall(
220 Intrinsic
, {Value
, CurKey
, CurDiscriminator
, NewKey
, NewDiscriminator
});
222 // Convert back to the original type.
223 Value
= Builder
.CreateIntToPtr(Value
, OrigType
);
227 llvm::Value
*CodeGenFunction::emitPointerAuthResign(
228 llvm::Value
*Value
, QualType Type
, const CGPointerAuthInfo
&CurAuthInfo
,
229 const CGPointerAuthInfo
&NewAuthInfo
, bool IsKnownNonNull
) {
230 // Fast path: if neither schema wants a signature, we're done.
231 if (!CurAuthInfo
&& !NewAuthInfo
)
234 llvm::Value
*Null
= nullptr;
235 // If the value is obviously null, we're done.
236 if (auto *PointerValue
= dyn_cast
<llvm::PointerType
>(Value
->getType())) {
237 Null
= CGM
.getNullPointer(PointerValue
, Type
);
239 assert(Value
->getType()->isIntegerTy());
240 Null
= llvm::ConstantInt::get(IntPtrTy
, 0);
245 // If both schemas sign the same way, we're done.
246 if (equalAuthPolicies(CurAuthInfo
, NewAuthInfo
)) {
247 const llvm::Value
*CurD
= CurAuthInfo
.getDiscriminator();
248 const llvm::Value
*NewD
= NewAuthInfo
.getDiscriminator();
252 if ((CurD
== nullptr && isZeroConstant(NewD
)) ||
253 (NewD
== nullptr && isZeroConstant(CurD
)))
257 llvm::BasicBlock
*InitBB
= Builder
.GetInsertBlock();
258 llvm::BasicBlock
*ResignBB
= nullptr, *ContBB
= nullptr;
260 // Null pointers have to be mapped to null, and the ptrauth_resign
261 // intrinsic doesn't do that.
262 if (!IsKnownNonNull
&& !llvm::isKnownNonZero(Value
, CGM
.getDataLayout())) {
263 ContBB
= createBasicBlock("resign.cont");
264 ResignBB
= createBasicBlock("resign.nonnull");
266 auto *IsNonNull
= Builder
.CreateICmpNE(Value
, Null
);
267 Builder
.CreateCondBr(IsNonNull
, ResignBB
, ContBB
);
271 // Perform the auth/sign/resign operation.
273 Value
= EmitPointerAuthAuth(CurAuthInfo
, Value
);
274 else if (!CurAuthInfo
)
275 Value
= EmitPointerAuthSign(NewAuthInfo
, Value
);
277 Value
= emitPointerAuthResignCall(Value
, CurAuthInfo
, NewAuthInfo
);
279 // Clean up with a phi if we branched before.
282 auto *Phi
= Builder
.CreatePHI(Value
->getType(), 2);
283 Phi
->addIncoming(Null
, InitBB
);
284 Phi
->addIncoming(Value
, ResignBB
);
292 CodeGenModule::getConstantSignedPointer(llvm::Constant
*Pointer
, unsigned Key
,
293 llvm::Constant
*StorageAddress
,
294 llvm::ConstantInt
*OtherDiscriminator
) {
295 llvm::Constant
*AddressDiscriminator
;
296 if (StorageAddress
) {
297 assert(StorageAddress
->getType() == UnqualPtrTy
);
298 AddressDiscriminator
= StorageAddress
;
300 AddressDiscriminator
= llvm::Constant::getNullValue(UnqualPtrTy
);
303 llvm::ConstantInt
*IntegerDiscriminator
;
304 if (OtherDiscriminator
) {
305 assert(OtherDiscriminator
->getType() == Int64Ty
);
306 IntegerDiscriminator
= OtherDiscriminator
;
308 IntegerDiscriminator
= llvm::ConstantInt::get(Int64Ty
, 0);
311 return llvm::ConstantPtrAuth::get(Pointer
,
312 llvm::ConstantInt::get(Int32Ty
, Key
),
313 IntegerDiscriminator
, AddressDiscriminator
);
316 /// Does a given PointerAuthScheme require us to sign a value
317 bool CodeGenModule::shouldSignPointer(const PointerAuthSchema
&Schema
) {
318 auto AuthenticationMode
= Schema
.getAuthenticationMode();
319 return AuthenticationMode
== PointerAuthenticationMode::SignAndStrip
||
320 AuthenticationMode
== PointerAuthenticationMode::SignAndAuth
;
323 /// Sign a constant pointer using the given scheme, producing a constant
324 /// with the same IR type.
325 llvm::Constant
*CodeGenModule::getConstantSignedPointer(
326 llvm::Constant
*Pointer
, const PointerAuthSchema
&Schema
,
327 llvm::Constant
*StorageAddress
, GlobalDecl SchemaDecl
,
328 QualType SchemaType
) {
329 assert(shouldSignPointer(Schema
));
330 llvm::ConstantInt
*OtherDiscriminator
=
331 getPointerAuthOtherDiscriminator(Schema
, SchemaDecl
, SchemaType
);
333 return getConstantSignedPointer(Pointer
, Schema
.getKey(), StorageAddress
,
337 /// If applicable, sign a given constant function pointer with the ABI rules for
339 llvm::Constant
*CodeGenModule::getFunctionPointer(llvm::Constant
*Pointer
,
340 QualType FunctionType
) {
341 assert(FunctionType
->isFunctionType() ||
342 FunctionType
->isFunctionReferenceType() ||
343 FunctionType
->isFunctionPointerType());
345 if (auto PointerAuth
= getFunctionPointerAuthInfo(FunctionType
))
346 return getConstantSignedPointer(
347 Pointer
, PointerAuth
.getKey(), /*StorageAddress=*/nullptr,
348 cast_or_null
<llvm::ConstantInt
>(PointerAuth
.getDiscriminator()));
353 llvm::Constant
*CodeGenModule::getFunctionPointer(GlobalDecl GD
,
355 const auto *FD
= cast
<FunctionDecl
>(GD
.getDecl());
356 QualType FuncType
= FD
->getType();
358 // Annoyingly, K&R functions have prototypes in the clang AST, but
359 // expressions referring to them are unprototyped.
360 if (!FD
->hasPrototype())
361 if (const auto *Proto
= FuncType
->getAs
<FunctionProtoType
>())
362 FuncType
= Context
.getFunctionNoProtoType(Proto
->getReturnType(),
363 Proto
->getExtInfo());
365 return getFunctionPointer(getRawFunctionPointer(GD
, Ty
), FuncType
);
368 CGPointerAuthInfo
CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT
) {
369 assert(FT
->getAs
<MemberPointerType
>() && "MemberPointerType expected");
370 const auto &Schema
= getCodeGenOpts().PointerAuth
.CXXMemberFunctionPointers
;
372 return CGPointerAuthInfo();
374 assert(!Schema
.isAddressDiscriminated() &&
375 "function pointers cannot use address-specific discrimination");
377 llvm::ConstantInt
*Discriminator
=
378 getPointerAuthOtherDiscriminator(Schema
, GlobalDecl(), FT
);
379 return CGPointerAuthInfo(Schema
.getKey(), Schema
.getAuthenticationMode(),
380 /* IsIsaPointer */ false,
381 /* AuthenticatesNullValues */ false, Discriminator
);
384 llvm::Constant
*CodeGenModule::getMemberFunctionPointer(llvm::Constant
*Pointer
,
386 if (CGPointerAuthInfo PointerAuth
= getMemberFunctionPointerAuthInfo(FT
))
387 return getConstantSignedPointer(
388 Pointer
, PointerAuth
.getKey(), nullptr,
389 cast_or_null
<llvm::ConstantInt
>(PointerAuth
.getDiscriminator()));
394 llvm::Constant
*CodeGenModule::getMemberFunctionPointer(const FunctionDecl
*FD
,
396 QualType FT
= FD
->getType();
397 FT
= getContext().getMemberPointerType(
398 FT
, cast
<CXXMethodDecl
>(FD
)->getParent()->getTypeForDecl());
399 return getMemberFunctionPointer(getRawFunctionPointer(FD
, Ty
), FT
);
402 std::optional
<PointerAuthQualifier
>
403 CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl
*ThisClass
) {
404 auto DefaultAuthentication
= getCodeGenOpts().PointerAuth
.CXXVTablePointers
;
405 if (!DefaultAuthentication
)
407 const CXXRecordDecl
*PrimaryBase
=
408 Context
.baseForVTableAuthentication(ThisClass
);
410 unsigned Key
= DefaultAuthentication
.getKey();
411 bool AddressDiscriminated
= DefaultAuthentication
.isAddressDiscriminated();
412 auto DefaultDiscrimination
= DefaultAuthentication
.getOtherDiscrimination();
413 unsigned TypeBasedDiscriminator
=
414 Context
.getPointerAuthVTablePointerDiscriminator(PrimaryBase
);
415 unsigned Discriminator
;
416 if (DefaultDiscrimination
== PointerAuthSchema::Discrimination::Type
) {
417 Discriminator
= TypeBasedDiscriminator
;
418 } else if (DefaultDiscrimination
==
419 PointerAuthSchema::Discrimination::Constant
) {
420 Discriminator
= DefaultAuthentication
.getConstantDiscrimination();
422 assert(DefaultDiscrimination
== PointerAuthSchema::Discrimination::None
);
425 if (auto ExplicitAuthentication
=
426 PrimaryBase
->getAttr
<VTablePointerAuthenticationAttr
>()) {
427 auto ExplicitAddressDiscrimination
=
428 ExplicitAuthentication
->getAddressDiscrimination();
429 auto ExplicitDiscriminator
=
430 ExplicitAuthentication
->getExtraDiscrimination();
432 unsigned ExplicitKey
= ExplicitAuthentication
->getKey();
433 if (ExplicitKey
== VTablePointerAuthenticationAttr::NoKey
)
436 if (ExplicitKey
!= VTablePointerAuthenticationAttr::DefaultKey
) {
437 if (ExplicitKey
== VTablePointerAuthenticationAttr::ProcessIndependent
)
438 Key
= (unsigned)PointerAuthSchema::ARM8_3Key::ASDA
;
440 assert(ExplicitKey
==
441 VTablePointerAuthenticationAttr::ProcessDependent
);
442 Key
= (unsigned)PointerAuthSchema::ARM8_3Key::ASDB
;
446 if (ExplicitAddressDiscrimination
!=
447 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination
)
448 AddressDiscriminated
=
449 ExplicitAddressDiscrimination
==
450 VTablePointerAuthenticationAttr::AddressDiscrimination
;
452 if (ExplicitDiscriminator
==
453 VTablePointerAuthenticationAttr::TypeDiscrimination
)
454 Discriminator
= TypeBasedDiscriminator
;
455 else if (ExplicitDiscriminator
==
456 VTablePointerAuthenticationAttr::CustomDiscrimination
)
457 Discriminator
= ExplicitAuthentication
->getCustomDiscriminationValue();
458 else if (ExplicitDiscriminator
==
459 VTablePointerAuthenticationAttr::NoExtraDiscrimination
)
462 return PointerAuthQualifier::Create(Key
, AddressDiscriminated
, Discriminator
,
463 PointerAuthenticationMode::SignAndAuth
,
464 /* IsIsaPointer */ false,
465 /* AuthenticatesNullValues */ false);
468 std::optional
<PointerAuthQualifier
>
469 CodeGenModule::getVTablePointerAuthentication(const CXXRecordDecl
*Record
) {
470 if (!Record
->getDefinition() || !Record
->isPolymorphic())
473 auto Existing
= VTablePtrAuthInfos
.find(Record
);
474 std::optional
<PointerAuthQualifier
> Authentication
;
475 if (Existing
!= VTablePtrAuthInfos
.end()) {
476 Authentication
= Existing
->getSecond();
478 Authentication
= computeVTPointerAuthentication(Record
);
479 VTablePtrAuthInfos
.insert(std::make_pair(Record
, Authentication
));
481 return Authentication
;
484 std::optional
<CGPointerAuthInfo
>
485 CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction
*CGF
,
486 const CXXRecordDecl
*Record
,
487 llvm::Value
*StorageAddress
) {
488 auto Authentication
= getVTablePointerAuthentication(Record
);
492 llvm::Value
*Discriminator
= nullptr;
493 if (auto ExtraDiscriminator
= Authentication
->getExtraDiscriminator())
494 Discriminator
= llvm::ConstantInt::get(IntPtrTy
, ExtraDiscriminator
);
496 if (Authentication
->isAddressDiscriminated()) {
497 assert(StorageAddress
&&
498 "address not provided for address-discriminated schema");
501 CGF
->EmitPointerAuthBlendDiscriminator(StorageAddress
, Discriminator
);
503 Discriminator
= CGF
->Builder
.CreatePtrToInt(StorageAddress
, IntPtrTy
);
506 return CGPointerAuthInfo(Authentication
->getKey(),
507 PointerAuthenticationMode::SignAndAuth
,
508 /* IsIsaPointer */ false,
509 /* AuthenticatesNullValues */ false, Discriminator
);
512 llvm::Value
*CodeGenFunction::authPointerToPointerCast(llvm::Value
*ResultPtr
,
515 CGPointerAuthInfo CurAuthInfo
, NewAuthInfo
;
516 if (SourceType
->isSignableType())
517 CurAuthInfo
= getPointerAuthInfoForType(CGM
, SourceType
);
519 if (DestType
->isSignableType())
520 NewAuthInfo
= getPointerAuthInfoForType(CGM
, DestType
);
522 if (!CurAuthInfo
&& !NewAuthInfo
)
525 // If only one side of the cast is a function pointer, then we still need to
526 // resign to handle casts to/from opaque pointers.
527 if (!CurAuthInfo
&& DestType
->isFunctionPointerType())
528 CurAuthInfo
= CGM
.getFunctionPointerAuthInfo(SourceType
);
530 if (!NewAuthInfo
&& SourceType
->isFunctionPointerType())
531 NewAuthInfo
= CGM
.getFunctionPointerAuthInfo(DestType
);
533 return emitPointerAuthResign(ResultPtr
, DestType
, CurAuthInfo
, NewAuthInfo
,
534 /*IsKnownNonNull=*/false);
537 Address
CodeGenFunction::authPointerToPointerCast(Address Ptr
,
540 CGPointerAuthInfo CurAuthInfo
, NewAuthInfo
;
541 if (SourceType
->isSignableType())
542 CurAuthInfo
= getPointerAuthInfoForType(CGM
, SourceType
);
544 if (DestType
->isSignableType())
545 NewAuthInfo
= getPointerAuthInfoForType(CGM
, DestType
);
547 if (!CurAuthInfo
&& !NewAuthInfo
)
550 if (!CurAuthInfo
&& DestType
->isFunctionPointerType()) {
551 // When casting a non-signed pointer to a function pointer, just set the
552 // auth info on Ptr to the assumed schema. The pointer will be resigned to
553 // the effective type when used.
554 Ptr
.setPointerAuthInfo(CGM
.getFunctionPointerAuthInfo(SourceType
));
558 if (!NewAuthInfo
&& SourceType
->isFunctionPointerType()) {
559 NewAuthInfo
= CGM
.getFunctionPointerAuthInfo(DestType
);
560 Ptr
= Ptr
.getResignedAddress(NewAuthInfo
, *this);
561 Ptr
.setPointerAuthInfo(CGPointerAuthInfo());
568 Address
CodeGenFunction::getAsNaturalAddressOf(Address Addr
,
569 QualType PointeeTy
) {
570 CGPointerAuthInfo Info
=
571 PointeeTy
.isNull() ? CGPointerAuthInfo()
572 : CGM
.getPointerAuthInfoForPointeeType(PointeeTy
);
573 return Addr
.getResignedAddress(Info
, *this);
576 Address
Address::getResignedAddress(const CGPointerAuthInfo
&NewInfo
,
577 CodeGenFunction
&CGF
) const {
578 assert(isValid() && "pointer isn't valid");
579 CGPointerAuthInfo CurInfo
= getPointerAuthInfo();
582 // Nothing to do if neither the current or the new ptrauth info needs signing.
583 if (!CurInfo
.isSigned() && !NewInfo
.isSigned())
584 return Address(getBasePointer(), getElementType(), getAlignment(),
587 assert(ElementType
&& "Effective type has to be set");
588 assert(!Offset
&& "unexpected non-null offset");
590 // If the current and the new ptrauth infos are the same and the offset is
591 // null, just cast the base pointer to the effective type.
592 if (CurInfo
== NewInfo
&& !hasOffset())
593 Val
= getBasePointer();
595 Val
= CGF
.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo
,
596 NewInfo
, isKnownNonNull());
598 Val
= CGF
.Builder
.CreateBitCast(Val
, getType());
599 return Address(Val
, getElementType(), getAlignment(), NewInfo
,
600 /*Offset=*/nullptr, isKnownNonNull());
603 llvm::Value
*Address::emitRawPointerSlow(CodeGenFunction
&CGF
) const {
604 return CGF
.getAsNaturalPointerTo(*this, QualType());
607 llvm::Value
*LValue::getPointer(CodeGenFunction
&CGF
) const {
609 return emitResignedPointer(getType(), CGF
);
612 llvm::Value
*LValue::emitResignedPointer(QualType PointeeTy
,
613 CodeGenFunction
&CGF
) const {
615 return CGF
.getAsNaturalAddressOf(Addr
, PointeeTy
).getBasePointer();
618 llvm::Value
*LValue::emitRawPointer(CodeGenFunction
&CGF
) const {
620 return Addr
.isValid() ? Addr
.emitRawPointer(CGF
) : nullptr;