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