17c814c13SAhmed Bougacha //===--- CGPointerAuth.cpp - IR generation for pointer authentication -----===// 27c814c13SAhmed Bougacha // 37c814c13SAhmed Bougacha // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47c814c13SAhmed Bougacha // See https://llvm.org/LICENSE.txt for license information. 57c814c13SAhmed Bougacha // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67c814c13SAhmed Bougacha // 77c814c13SAhmed Bougacha //===----------------------------------------------------------------------===// 87c814c13SAhmed Bougacha // 97c814c13SAhmed Bougacha // This file contains common routines relating to the emission of 107c814c13SAhmed Bougacha // pointer authentication operations. 117c814c13SAhmed Bougacha // 127c814c13SAhmed Bougacha //===----------------------------------------------------------------------===// 137c814c13SAhmed Bougacha 141b8ab2f0SOliver Hunt #include "CodeGenFunction.h" 157c814c13SAhmed Bougacha #include "CodeGenModule.h" 167c814c13SAhmed Bougacha #include "clang/CodeGen/CodeGenABITypes.h" 171b8ab2f0SOliver Hunt #include "clang/CodeGen/ConstantInitBuilder.h" 18f6b06b42SAkira Hatanaka #include "llvm/Analysis/ValueTracking.h" 191b8ab2f0SOliver Hunt #include "llvm/Support/SipHash.h" 207c814c13SAhmed Bougacha 217c814c13SAhmed Bougacha using namespace clang; 227c814c13SAhmed Bougacha using namespace CodeGen; 237c814c13SAhmed Bougacha 241b8ab2f0SOliver Hunt /// Given a pointer-authentication schema, return a concrete "other" 251b8ab2f0SOliver Hunt /// discriminator for it. 261b8ab2f0SOliver Hunt llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator( 271b8ab2f0SOliver Hunt const PointerAuthSchema &Schema, GlobalDecl Decl, QualType Type) { 281b8ab2f0SOliver Hunt switch (Schema.getOtherDiscrimination()) { 291b8ab2f0SOliver Hunt case PointerAuthSchema::Discrimination::None: 301b8ab2f0SOliver Hunt return nullptr; 311b8ab2f0SOliver Hunt 321b8ab2f0SOliver Hunt case PointerAuthSchema::Discrimination::Type: 33ae18b941SAkira Hatanaka assert(!Type.isNull() && "type not provided for type-discriminated schema"); 34ae18b941SAkira Hatanaka return llvm::ConstantInt::get( 35ae18b941SAkira Hatanaka IntPtrTy, getContext().getPointerAuthTypeDiscriminator(Type)); 361b8ab2f0SOliver Hunt 371b8ab2f0SOliver Hunt case PointerAuthSchema::Discrimination::Decl: 381b8ab2f0SOliver Hunt assert(Decl.getDecl() && 391b8ab2f0SOliver Hunt "declaration not provided for decl-discriminated schema"); 401b8ab2f0SOliver Hunt return llvm::ConstantInt::get(IntPtrTy, 411b8ab2f0SOliver Hunt getPointerAuthDeclDiscriminator(Decl)); 421b8ab2f0SOliver Hunt 431b8ab2f0SOliver Hunt case PointerAuthSchema::Discrimination::Constant: 441b8ab2f0SOliver Hunt return llvm::ConstantInt::get(IntPtrTy, Schema.getConstantDiscrimination()); 451b8ab2f0SOliver Hunt } 461b8ab2f0SOliver Hunt llvm_unreachable("bad discrimination kind"); 471b8ab2f0SOliver Hunt } 481b8ab2f0SOliver Hunt 49ae18b941SAkira Hatanaka uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule &CGM, 50ae18b941SAkira Hatanaka QualType FunctionType) { 51ae18b941SAkira Hatanaka return CGM.getContext().getPointerAuthTypeDiscriminator(FunctionType); 52ae18b941SAkira Hatanaka } 53ae18b941SAkira Hatanaka 541b8ab2f0SOliver Hunt uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule &CGM, 551b8ab2f0SOliver Hunt GlobalDecl Declaration) { 561b8ab2f0SOliver Hunt return CGM.getPointerAuthDeclDiscriminator(Declaration); 571b8ab2f0SOliver Hunt } 581b8ab2f0SOliver Hunt 591b8ab2f0SOliver Hunt /// Return the "other" decl-specific discriminator for the given decl. 601b8ab2f0SOliver Hunt uint16_t 611b8ab2f0SOliver Hunt CodeGenModule::getPointerAuthDeclDiscriminator(GlobalDecl Declaration) { 621b8ab2f0SOliver Hunt uint16_t &EntityHash = PtrAuthDiscriminatorHashes[Declaration]; 631b8ab2f0SOliver Hunt 641b8ab2f0SOliver Hunt if (EntityHash == 0) { 651b8ab2f0SOliver Hunt StringRef Name = getMangledName(Declaration); 661b8ab2f0SOliver Hunt EntityHash = llvm::getPointerAuthStableSipHash(Name); 671b8ab2f0SOliver Hunt } 681b8ab2f0SOliver Hunt 691b8ab2f0SOliver Hunt return EntityHash; 701b8ab2f0SOliver Hunt } 711b8ab2f0SOliver Hunt 72e23250ecSAhmed Bougacha /// Return the abstract pointer authentication schema for a pointer to the given 73e23250ecSAhmed Bougacha /// function type. 74e23250ecSAhmed Bougacha CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) { 75e23250ecSAhmed Bougacha const auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers; 76e23250ecSAhmed Bougacha if (!Schema) 77e23250ecSAhmed Bougacha return CGPointerAuthInfo(); 78e23250ecSAhmed Bougacha 79e23250ecSAhmed Bougacha assert(!Schema.isAddressDiscriminated() && 80e23250ecSAhmed Bougacha "function pointers cannot use address-specific discrimination"); 81e23250ecSAhmed Bougacha 82ae18b941SAkira Hatanaka llvm::Constant *Discriminator = nullptr; 83ae18b941SAkira Hatanaka if (T->isFunctionPointerType() || T->isFunctionReferenceType()) 84ae18b941SAkira Hatanaka T = T->getPointeeType(); 85ae18b941SAkira Hatanaka if (T->isFunctionType()) 86ae18b941SAkira Hatanaka Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T); 87e23250ecSAhmed Bougacha 88e23250ecSAhmed Bougacha return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(), 89e23250ecSAhmed Bougacha /*IsaPointer=*/false, /*AuthenticatesNull=*/false, 90ae18b941SAkira Hatanaka Discriminator); 91e23250ecSAhmed Bougacha } 92e23250ecSAhmed Bougacha 931b8ab2f0SOliver Hunt llvm::Value * 941b8ab2f0SOliver Hunt CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, 951b8ab2f0SOliver Hunt llvm::Value *Discriminator) { 961b8ab2f0SOliver Hunt StorageAddress = Builder.CreatePtrToInt(StorageAddress, IntPtrTy); 971b8ab2f0SOliver Hunt auto Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend); 981b8ab2f0SOliver Hunt return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator}); 991b8ab2f0SOliver Hunt } 1001b8ab2f0SOliver Hunt 1011b8ab2f0SOliver Hunt /// Emit the concrete pointer authentication informaton for the 1021b8ab2f0SOliver Hunt /// given authentication schema. 1031b8ab2f0SOliver Hunt CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo( 1041b8ab2f0SOliver Hunt const PointerAuthSchema &Schema, llvm::Value *StorageAddress, 1051b8ab2f0SOliver Hunt GlobalDecl SchemaDecl, QualType SchemaType) { 1061b8ab2f0SOliver Hunt if (!Schema) 1071b8ab2f0SOliver Hunt return CGPointerAuthInfo(); 1081b8ab2f0SOliver Hunt 1091b8ab2f0SOliver Hunt llvm::Value *Discriminator = 1101b8ab2f0SOliver Hunt CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType); 1111b8ab2f0SOliver Hunt 1121b8ab2f0SOliver Hunt if (Schema.isAddressDiscriminated()) { 1131b8ab2f0SOliver Hunt assert(StorageAddress && 1141b8ab2f0SOliver Hunt "address not provided for address-discriminated schema"); 1151b8ab2f0SOliver Hunt 1161b8ab2f0SOliver Hunt if (Discriminator) 1171b8ab2f0SOliver Hunt Discriminator = 1181b8ab2f0SOliver Hunt EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator); 1191b8ab2f0SOliver Hunt else 1201b8ab2f0SOliver Hunt Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy); 1211b8ab2f0SOliver Hunt } 1221b8ab2f0SOliver Hunt 1231b8ab2f0SOliver Hunt return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(), 1241b8ab2f0SOliver Hunt Schema.isIsaPointer(), 1251b8ab2f0SOliver Hunt Schema.authenticatesNullValues(), Discriminator); 1261b8ab2f0SOliver Hunt } 1271b8ab2f0SOliver Hunt 128ae18b941SAkira Hatanaka /// Return the natural pointer authentication for values of the given 129ae18b941SAkira Hatanaka /// pointee type. 130ae18b941SAkira Hatanaka static CGPointerAuthInfo 131ae18b941SAkira Hatanaka getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType) { 132ae18b941SAkira Hatanaka if (PointeeType.isNull()) 133ae18b941SAkira Hatanaka return CGPointerAuthInfo(); 134ae18b941SAkira Hatanaka 135ae18b941SAkira Hatanaka // Function pointers use the function-pointer schema by default. 136ae18b941SAkira Hatanaka if (PointeeType->isFunctionType()) 137ae18b941SAkira Hatanaka return CGM.getFunctionPointerAuthInfo(PointeeType); 138ae18b941SAkira Hatanaka 139ae18b941SAkira Hatanaka // Normal data pointers never use direct pointer authentication by default. 140ae18b941SAkira Hatanaka return CGPointerAuthInfo(); 141ae18b941SAkira Hatanaka } 142ae18b941SAkira Hatanaka 143ae18b941SAkira Hatanaka CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) { 144ae18b941SAkira Hatanaka return ::getPointerAuthInfoForPointeeType(*this, T); 145ae18b941SAkira Hatanaka } 146ae18b941SAkira Hatanaka 147ae18b941SAkira Hatanaka /// Return the natural pointer authentication for values of the given 148ae18b941SAkira Hatanaka /// pointer type. 149ae18b941SAkira Hatanaka static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM, 150ae18b941SAkira Hatanaka QualType PointerType) { 151ae18b941SAkira Hatanaka assert(PointerType->isSignableType()); 152ae18b941SAkira Hatanaka 153ae18b941SAkira Hatanaka // Block pointers are currently not signed. 154ae18b941SAkira Hatanaka if (PointerType->isBlockPointerType()) 155ae18b941SAkira Hatanaka return CGPointerAuthInfo(); 156ae18b941SAkira Hatanaka 157ae18b941SAkira Hatanaka auto PointeeType = PointerType->getPointeeType(); 158ae18b941SAkira Hatanaka 159ae18b941SAkira Hatanaka if (PointeeType.isNull()) 160ae18b941SAkira Hatanaka return CGPointerAuthInfo(); 161ae18b941SAkira Hatanaka 162ae18b941SAkira Hatanaka return ::getPointerAuthInfoForPointeeType(CGM, PointeeType); 163ae18b941SAkira Hatanaka } 164ae18b941SAkira Hatanaka 165ae18b941SAkira Hatanaka CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) { 166ae18b941SAkira Hatanaka return ::getPointerAuthInfoForType(*this, T); 167ae18b941SAkira Hatanaka } 168ae18b941SAkira Hatanaka 169f6b06b42SAkira Hatanaka static bool isZeroConstant(const llvm::Value *Value) { 170f6b06b42SAkira Hatanaka if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value)) 171f6b06b42SAkira Hatanaka return CI->isZero(); 172f6b06b42SAkira Hatanaka return false; 173f6b06b42SAkira Hatanaka } 174f6b06b42SAkira Hatanaka 175f6b06b42SAkira Hatanaka static bool equalAuthPolicies(const CGPointerAuthInfo &Left, 176f6b06b42SAkira Hatanaka const CGPointerAuthInfo &Right) { 177f6b06b42SAkira Hatanaka assert((Left.isSigned() || Right.isSigned()) && 178f6b06b42SAkira Hatanaka "shouldn't be called if neither is signed"); 179f6b06b42SAkira Hatanaka if (Left.isSigned() != Right.isSigned()) 180f6b06b42SAkira Hatanaka return false; 181f6b06b42SAkira Hatanaka return Left.getKey() == Right.getKey() && 182f6b06b42SAkira Hatanaka Left.getAuthenticationMode() == Right.getAuthenticationMode(); 183f6b06b42SAkira Hatanaka } 184f6b06b42SAkira Hatanaka 185f6b06b42SAkira Hatanaka // Return the discriminator or return zero if the discriminator is null. 186f6b06b42SAkira Hatanaka static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info, 187f6b06b42SAkira Hatanaka CGBuilderTy &Builder) { 188f6b06b42SAkira Hatanaka llvm::Value *Discriminator = Info.getDiscriminator(); 189f6b06b42SAkira Hatanaka return Discriminator ? Discriminator : Builder.getSize(0); 190f6b06b42SAkira Hatanaka } 191f6b06b42SAkira Hatanaka 192f6b06b42SAkira Hatanaka llvm::Value * 193f6b06b42SAkira Hatanaka CodeGenFunction::emitPointerAuthResignCall(llvm::Value *Value, 194f6b06b42SAkira Hatanaka const CGPointerAuthInfo &CurAuth, 195f6b06b42SAkira Hatanaka const CGPointerAuthInfo &NewAuth) { 196f6b06b42SAkira Hatanaka assert(CurAuth && NewAuth); 197f6b06b42SAkira Hatanaka 198f6b06b42SAkira Hatanaka if (CurAuth.getAuthenticationMode() != 199f6b06b42SAkira Hatanaka PointerAuthenticationMode::SignAndAuth || 200f6b06b42SAkira Hatanaka NewAuth.getAuthenticationMode() != 201f6b06b42SAkira Hatanaka PointerAuthenticationMode::SignAndAuth) { 202f6b06b42SAkira Hatanaka llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value); 203f6b06b42SAkira Hatanaka return EmitPointerAuthSign(NewAuth, AuthedValue); 204f6b06b42SAkira Hatanaka } 205f6b06b42SAkira Hatanaka // Convert the pointer to intptr_t before signing it. 206f6b06b42SAkira Hatanaka auto *OrigType = Value->getType(); 207f6b06b42SAkira Hatanaka Value = Builder.CreatePtrToInt(Value, IntPtrTy); 208f6b06b42SAkira Hatanaka 209f6b06b42SAkira Hatanaka auto *CurKey = Builder.getInt32(CurAuth.getKey()); 210f6b06b42SAkira Hatanaka auto *NewKey = Builder.getInt32(NewAuth.getKey()); 211f6b06b42SAkira Hatanaka 212f6b06b42SAkira Hatanaka llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder); 213f6b06b42SAkira Hatanaka llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder); 214f6b06b42SAkira Hatanaka 215f6b06b42SAkira Hatanaka // call i64 @llvm.ptrauth.resign(i64 %pointer, 216f6b06b42SAkira Hatanaka // i32 %curKey, i64 %curDiscriminator, 217f6b06b42SAkira Hatanaka // i32 %newKey, i64 %newDiscriminator) 218f6b06b42SAkira Hatanaka auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign); 219f6b06b42SAkira Hatanaka Value = EmitRuntimeCall( 220f6b06b42SAkira Hatanaka Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator}); 221f6b06b42SAkira Hatanaka 222f6b06b42SAkira Hatanaka // Convert back to the original type. 223f6b06b42SAkira Hatanaka Value = Builder.CreateIntToPtr(Value, OrigType); 224f6b06b42SAkira Hatanaka return Value; 225f6b06b42SAkira Hatanaka } 226f6b06b42SAkira Hatanaka 227f6b06b42SAkira Hatanaka llvm::Value *CodeGenFunction::emitPointerAuthResign( 228f6b06b42SAkira Hatanaka llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo, 229f6b06b42SAkira Hatanaka const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) { 230f6b06b42SAkira Hatanaka // Fast path: if neither schema wants a signature, we're done. 231f6b06b42SAkira Hatanaka if (!CurAuthInfo && !NewAuthInfo) 232f6b06b42SAkira Hatanaka return Value; 233f6b06b42SAkira Hatanaka 234f6b06b42SAkira Hatanaka llvm::Value *Null = nullptr; 235f6b06b42SAkira Hatanaka // If the value is obviously null, we're done. 236f6b06b42SAkira Hatanaka if (auto *PointerValue = dyn_cast<llvm::PointerType>(Value->getType())) { 237f6b06b42SAkira Hatanaka Null = CGM.getNullPointer(PointerValue, Type); 238f6b06b42SAkira Hatanaka } else { 239f6b06b42SAkira Hatanaka assert(Value->getType()->isIntegerTy()); 240f6b06b42SAkira Hatanaka Null = llvm::ConstantInt::get(IntPtrTy, 0); 241f6b06b42SAkira Hatanaka } 242f6b06b42SAkira Hatanaka if (Value == Null) 243f6b06b42SAkira Hatanaka return Value; 244f6b06b42SAkira Hatanaka 245f6b06b42SAkira Hatanaka // If both schemas sign the same way, we're done. 246f6b06b42SAkira Hatanaka if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) { 247f6b06b42SAkira Hatanaka const llvm::Value *CurD = CurAuthInfo.getDiscriminator(); 248f6b06b42SAkira Hatanaka const llvm::Value *NewD = NewAuthInfo.getDiscriminator(); 249f6b06b42SAkira Hatanaka if (CurD == NewD) 250f6b06b42SAkira Hatanaka return Value; 251f6b06b42SAkira Hatanaka 252f6b06b42SAkira Hatanaka if ((CurD == nullptr && isZeroConstant(NewD)) || 253f6b06b42SAkira Hatanaka (NewD == nullptr && isZeroConstant(CurD))) 254f6b06b42SAkira Hatanaka return Value; 255f6b06b42SAkira Hatanaka } 256f6b06b42SAkira Hatanaka 257f6b06b42SAkira Hatanaka llvm::BasicBlock *InitBB = Builder.GetInsertBlock(); 258f6b06b42SAkira Hatanaka llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr; 259f6b06b42SAkira Hatanaka 260f6b06b42SAkira Hatanaka // Null pointers have to be mapped to null, and the ptrauth_resign 261f6b06b42SAkira Hatanaka // intrinsic doesn't do that. 262f6b06b42SAkira Hatanaka if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) { 263f6b06b42SAkira Hatanaka ContBB = createBasicBlock("resign.cont"); 264f6b06b42SAkira Hatanaka ResignBB = createBasicBlock("resign.nonnull"); 265f6b06b42SAkira Hatanaka 266f6b06b42SAkira Hatanaka auto *IsNonNull = Builder.CreateICmpNE(Value, Null); 267f6b06b42SAkira Hatanaka Builder.CreateCondBr(IsNonNull, ResignBB, ContBB); 268f6b06b42SAkira Hatanaka EmitBlock(ResignBB); 269f6b06b42SAkira Hatanaka } 270f6b06b42SAkira Hatanaka 271f6b06b42SAkira Hatanaka // Perform the auth/sign/resign operation. 272f6b06b42SAkira Hatanaka if (!NewAuthInfo) 273f6b06b42SAkira Hatanaka Value = EmitPointerAuthAuth(CurAuthInfo, Value); 274f6b06b42SAkira Hatanaka else if (!CurAuthInfo) 275f6b06b42SAkira Hatanaka Value = EmitPointerAuthSign(NewAuthInfo, Value); 276f6b06b42SAkira Hatanaka else 277f6b06b42SAkira Hatanaka Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo); 278f6b06b42SAkira Hatanaka 279f6b06b42SAkira Hatanaka // Clean up with a phi if we branched before. 280f6b06b42SAkira Hatanaka if (ContBB) { 281f6b06b42SAkira Hatanaka EmitBlock(ContBB); 282f6b06b42SAkira Hatanaka auto *Phi = Builder.CreatePHI(Value->getType(), 2); 283f6b06b42SAkira Hatanaka Phi->addIncoming(Null, InitBB); 284f6b06b42SAkira Hatanaka Phi->addIncoming(Value, ResignBB); 285f6b06b42SAkira Hatanaka Value = Phi; 286f6b06b42SAkira Hatanaka } 287f6b06b42SAkira Hatanaka 288f6b06b42SAkira Hatanaka return Value; 289f6b06b42SAkira Hatanaka } 290f6b06b42SAkira Hatanaka 2917c814c13SAhmed Bougacha llvm::Constant * 2927c814c13SAhmed Bougacha CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, 2937c814c13SAhmed Bougacha llvm::Constant *StorageAddress, 2947c814c13SAhmed Bougacha llvm::ConstantInt *OtherDiscriminator) { 2957c814c13SAhmed Bougacha llvm::Constant *AddressDiscriminator; 2967c814c13SAhmed Bougacha if (StorageAddress) { 2977c814c13SAhmed Bougacha assert(StorageAddress->getType() == UnqualPtrTy); 2987c814c13SAhmed Bougacha AddressDiscriminator = StorageAddress; 2997c814c13SAhmed Bougacha } else { 3007c814c13SAhmed Bougacha AddressDiscriminator = llvm::Constant::getNullValue(UnqualPtrTy); 3017c814c13SAhmed Bougacha } 3027c814c13SAhmed Bougacha 3037c814c13SAhmed Bougacha llvm::ConstantInt *IntegerDiscriminator; 3047c814c13SAhmed Bougacha if (OtherDiscriminator) { 3057c814c13SAhmed Bougacha assert(OtherDiscriminator->getType() == Int64Ty); 3067c814c13SAhmed Bougacha IntegerDiscriminator = OtherDiscriminator; 3077c814c13SAhmed Bougacha } else { 3087c814c13SAhmed Bougacha IntegerDiscriminator = llvm::ConstantInt::get(Int64Ty, 0); 3097c814c13SAhmed Bougacha } 3107c814c13SAhmed Bougacha 3117c814c13SAhmed Bougacha return llvm::ConstantPtrAuth::get(Pointer, 3127c814c13SAhmed Bougacha llvm::ConstantInt::get(Int32Ty, Key), 3137c814c13SAhmed Bougacha IntegerDiscriminator, AddressDiscriminator); 3147c814c13SAhmed Bougacha } 315e23250ecSAhmed Bougacha 3161b8ab2f0SOliver Hunt /// Does a given PointerAuthScheme require us to sign a value 3171b8ab2f0SOliver Hunt bool CodeGenModule::shouldSignPointer(const PointerAuthSchema &Schema) { 3181b8ab2f0SOliver Hunt auto AuthenticationMode = Schema.getAuthenticationMode(); 3191b8ab2f0SOliver Hunt return AuthenticationMode == PointerAuthenticationMode::SignAndStrip || 3201b8ab2f0SOliver Hunt AuthenticationMode == PointerAuthenticationMode::SignAndAuth; 3211b8ab2f0SOliver Hunt } 3221b8ab2f0SOliver Hunt 3231b8ab2f0SOliver Hunt /// Sign a constant pointer using the given scheme, producing a constant 3241b8ab2f0SOliver Hunt /// with the same IR type. 3251b8ab2f0SOliver Hunt llvm::Constant *CodeGenModule::getConstantSignedPointer( 3261b8ab2f0SOliver Hunt llvm::Constant *Pointer, const PointerAuthSchema &Schema, 3271b8ab2f0SOliver Hunt llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, 3281b8ab2f0SOliver Hunt QualType SchemaType) { 3291b8ab2f0SOliver Hunt assert(shouldSignPointer(Schema)); 3301b8ab2f0SOliver Hunt llvm::ConstantInt *OtherDiscriminator = 3311b8ab2f0SOliver Hunt getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType); 3321b8ab2f0SOliver Hunt 3331b8ab2f0SOliver Hunt return getConstantSignedPointer(Pointer, Schema.getKey(), StorageAddress, 3341b8ab2f0SOliver Hunt OtherDiscriminator); 3351b8ab2f0SOliver Hunt } 3361b8ab2f0SOliver Hunt 3371b8ab2f0SOliver Hunt /// If applicable, sign a given constant function pointer with the ABI rules for 3381b8ab2f0SOliver Hunt /// functionType. 339e23250ecSAhmed Bougacha llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer, 340e23250ecSAhmed Bougacha QualType FunctionType) { 341e23250ecSAhmed Bougacha assert(FunctionType->isFunctionType() || 342e23250ecSAhmed Bougacha FunctionType->isFunctionReferenceType() || 343e23250ecSAhmed Bougacha FunctionType->isFunctionPointerType()); 344e23250ecSAhmed Bougacha 345e23250ecSAhmed Bougacha if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType)) 346e23250ecSAhmed Bougacha return getConstantSignedPointer( 347e23250ecSAhmed Bougacha Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr, 348e23250ecSAhmed Bougacha cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator())); 349e23250ecSAhmed Bougacha 350e23250ecSAhmed Bougacha return Pointer; 351e23250ecSAhmed Bougacha } 352e23250ecSAhmed Bougacha 353e23250ecSAhmed Bougacha llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD, 354e23250ecSAhmed Bougacha llvm::Type *Ty) { 355e23250ecSAhmed Bougacha const auto *FD = cast<FunctionDecl>(GD.getDecl()); 356e23250ecSAhmed Bougacha QualType FuncType = FD->getType(); 357ae18b941SAkira Hatanaka 358ae18b941SAkira Hatanaka // Annoyingly, K&R functions have prototypes in the clang AST, but 359ae18b941SAkira Hatanaka // expressions referring to them are unprototyped. 360ae18b941SAkira Hatanaka if (!FD->hasPrototype()) 361ae18b941SAkira Hatanaka if (const auto *Proto = FuncType->getAs<FunctionProtoType>()) 362ae18b941SAkira Hatanaka FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(), 363ae18b941SAkira Hatanaka Proto->getExtInfo()); 364ae18b941SAkira Hatanaka 365e23250ecSAhmed Bougacha return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType); 366e23250ecSAhmed Bougacha } 3671b8ab2f0SOliver Hunt 368*4dcd91aeSOliver Hunt CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) { 369*4dcd91aeSOliver Hunt assert(FT->getAs<MemberPointerType>() && "MemberPointerType expected"); 370*4dcd91aeSOliver Hunt const auto &Schema = getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers; 371*4dcd91aeSOliver Hunt if (!Schema) 372*4dcd91aeSOliver Hunt return CGPointerAuthInfo(); 373*4dcd91aeSOliver Hunt 374*4dcd91aeSOliver Hunt assert(!Schema.isAddressDiscriminated() && 375*4dcd91aeSOliver Hunt "function pointers cannot use address-specific discrimination"); 376*4dcd91aeSOliver Hunt 377*4dcd91aeSOliver Hunt llvm::ConstantInt *Discriminator = 378*4dcd91aeSOliver Hunt getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), FT); 379*4dcd91aeSOliver Hunt return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(), 380*4dcd91aeSOliver Hunt /* IsIsaPointer */ false, 381*4dcd91aeSOliver Hunt /* AuthenticatesNullValues */ false, Discriminator); 382*4dcd91aeSOliver Hunt } 383*4dcd91aeSOliver Hunt 384*4dcd91aeSOliver Hunt llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, 385*4dcd91aeSOliver Hunt QualType FT) { 386*4dcd91aeSOliver Hunt if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT)) 387*4dcd91aeSOliver Hunt return getConstantSignedPointer( 388*4dcd91aeSOliver Hunt Pointer, PointerAuth.getKey(), nullptr, 389*4dcd91aeSOliver Hunt cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator())); 390*4dcd91aeSOliver Hunt 391*4dcd91aeSOliver Hunt return Pointer; 392*4dcd91aeSOliver Hunt } 393*4dcd91aeSOliver Hunt 394*4dcd91aeSOliver Hunt llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD, 395*4dcd91aeSOliver Hunt llvm::Type *Ty) { 396*4dcd91aeSOliver Hunt QualType FT = FD->getType(); 397*4dcd91aeSOliver Hunt FT = getContext().getMemberPointerType( 398*4dcd91aeSOliver Hunt FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl()); 399*4dcd91aeSOliver Hunt return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); 400*4dcd91aeSOliver Hunt } 401*4dcd91aeSOliver Hunt 4021b8ab2f0SOliver Hunt std::optional<PointerAuthQualifier> 4031b8ab2f0SOliver Hunt CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) { 4041b8ab2f0SOliver Hunt auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers; 4051b8ab2f0SOliver Hunt if (!DefaultAuthentication) 4061b8ab2f0SOliver Hunt return std::nullopt; 4071b8ab2f0SOliver Hunt const CXXRecordDecl *PrimaryBase = 4081b8ab2f0SOliver Hunt Context.baseForVTableAuthentication(ThisClass); 4091b8ab2f0SOliver Hunt 4101b8ab2f0SOliver Hunt unsigned Key = DefaultAuthentication.getKey(); 4111b8ab2f0SOliver Hunt bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated(); 4121b8ab2f0SOliver Hunt auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination(); 4131b8ab2f0SOliver Hunt unsigned TypeBasedDiscriminator = 4141b8ab2f0SOliver Hunt Context.getPointerAuthVTablePointerDiscriminator(PrimaryBase); 4151b8ab2f0SOliver Hunt unsigned Discriminator; 4161b8ab2f0SOliver Hunt if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) { 4171b8ab2f0SOliver Hunt Discriminator = TypeBasedDiscriminator; 4181b8ab2f0SOliver Hunt } else if (DefaultDiscrimination == 4191b8ab2f0SOliver Hunt PointerAuthSchema::Discrimination::Constant) { 4201b8ab2f0SOliver Hunt Discriminator = DefaultAuthentication.getConstantDiscrimination(); 4211b8ab2f0SOliver Hunt } else { 4221b8ab2f0SOliver Hunt assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None); 4231b8ab2f0SOliver Hunt Discriminator = 0; 4241b8ab2f0SOliver Hunt } 4251b8ab2f0SOliver Hunt if (auto ExplicitAuthentication = 4261b8ab2f0SOliver Hunt PrimaryBase->getAttr<VTablePointerAuthenticationAttr>()) { 4271b8ab2f0SOliver Hunt auto ExplicitAddressDiscrimination = 4281b8ab2f0SOliver Hunt ExplicitAuthentication->getAddressDiscrimination(); 4291b8ab2f0SOliver Hunt auto ExplicitDiscriminator = 4301b8ab2f0SOliver Hunt ExplicitAuthentication->getExtraDiscrimination(); 4311b8ab2f0SOliver Hunt 4321b8ab2f0SOliver Hunt unsigned ExplicitKey = ExplicitAuthentication->getKey(); 4331b8ab2f0SOliver Hunt if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey) 4341b8ab2f0SOliver Hunt return std::nullopt; 4351b8ab2f0SOliver Hunt 4361b8ab2f0SOliver Hunt if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) { 4371b8ab2f0SOliver Hunt if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent) 4381b8ab2f0SOliver Hunt Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA; 4391b8ab2f0SOliver Hunt else { 4401b8ab2f0SOliver Hunt assert(ExplicitKey == 4411b8ab2f0SOliver Hunt VTablePointerAuthenticationAttr::ProcessDependent); 4421b8ab2f0SOliver Hunt Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB; 4431b8ab2f0SOliver Hunt } 4441b8ab2f0SOliver Hunt } 4451b8ab2f0SOliver Hunt 4461b8ab2f0SOliver Hunt if (ExplicitAddressDiscrimination != 4471b8ab2f0SOliver Hunt VTablePointerAuthenticationAttr::DefaultAddressDiscrimination) 4481b8ab2f0SOliver Hunt AddressDiscriminated = 4491b8ab2f0SOliver Hunt ExplicitAddressDiscrimination == 4501b8ab2f0SOliver Hunt VTablePointerAuthenticationAttr::AddressDiscrimination; 4511b8ab2f0SOliver Hunt 4521b8ab2f0SOliver Hunt if (ExplicitDiscriminator == 4531b8ab2f0SOliver Hunt VTablePointerAuthenticationAttr::TypeDiscrimination) 4541b8ab2f0SOliver Hunt Discriminator = TypeBasedDiscriminator; 4551b8ab2f0SOliver Hunt else if (ExplicitDiscriminator == 4561b8ab2f0SOliver Hunt VTablePointerAuthenticationAttr::CustomDiscrimination) 4571b8ab2f0SOliver Hunt Discriminator = ExplicitAuthentication->getCustomDiscriminationValue(); 4581b8ab2f0SOliver Hunt else if (ExplicitDiscriminator == 4591b8ab2f0SOliver Hunt VTablePointerAuthenticationAttr::NoExtraDiscrimination) 4601b8ab2f0SOliver Hunt Discriminator = 0; 4611b8ab2f0SOliver Hunt } 4621b8ab2f0SOliver Hunt return PointerAuthQualifier::Create(Key, AddressDiscriminated, Discriminator, 4631b8ab2f0SOliver Hunt PointerAuthenticationMode::SignAndAuth, 4641b8ab2f0SOliver Hunt /* IsIsaPointer */ false, 4651b8ab2f0SOliver Hunt /* AuthenticatesNullValues */ false); 4661b8ab2f0SOliver Hunt } 4671b8ab2f0SOliver Hunt 4681b8ab2f0SOliver Hunt std::optional<PointerAuthQualifier> 4691b8ab2f0SOliver Hunt CodeGenModule::getVTablePointerAuthentication(const CXXRecordDecl *Record) { 4701b8ab2f0SOliver Hunt if (!Record->getDefinition() || !Record->isPolymorphic()) 4711b8ab2f0SOliver Hunt return std::nullopt; 4721b8ab2f0SOliver Hunt 4731b8ab2f0SOliver Hunt auto Existing = VTablePtrAuthInfos.find(Record); 4741b8ab2f0SOliver Hunt std::optional<PointerAuthQualifier> Authentication; 4751b8ab2f0SOliver Hunt if (Existing != VTablePtrAuthInfos.end()) { 4761b8ab2f0SOliver Hunt Authentication = Existing->getSecond(); 4771b8ab2f0SOliver Hunt } else { 4781b8ab2f0SOliver Hunt Authentication = computeVTPointerAuthentication(Record); 4791b8ab2f0SOliver Hunt VTablePtrAuthInfos.insert(std::make_pair(Record, Authentication)); 4801b8ab2f0SOliver Hunt } 4811b8ab2f0SOliver Hunt return Authentication; 4821b8ab2f0SOliver Hunt } 4831b8ab2f0SOliver Hunt 4841b8ab2f0SOliver Hunt std::optional<CGPointerAuthInfo> 4851b8ab2f0SOliver Hunt CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF, 4861b8ab2f0SOliver Hunt const CXXRecordDecl *Record, 4871b8ab2f0SOliver Hunt llvm::Value *StorageAddress) { 4881b8ab2f0SOliver Hunt auto Authentication = getVTablePointerAuthentication(Record); 4891b8ab2f0SOliver Hunt if (!Authentication) 4901b8ab2f0SOliver Hunt return std::nullopt; 4911b8ab2f0SOliver Hunt 4921b8ab2f0SOliver Hunt llvm::Value *Discriminator = nullptr; 4931b8ab2f0SOliver Hunt if (auto ExtraDiscriminator = Authentication->getExtraDiscriminator()) 4941b8ab2f0SOliver Hunt Discriminator = llvm::ConstantInt::get(IntPtrTy, ExtraDiscriminator); 4951b8ab2f0SOliver Hunt 4961b8ab2f0SOliver Hunt if (Authentication->isAddressDiscriminated()) { 4971b8ab2f0SOliver Hunt assert(StorageAddress && 4981b8ab2f0SOliver Hunt "address not provided for address-discriminated schema"); 4991b8ab2f0SOliver Hunt if (Discriminator) 5001b8ab2f0SOliver Hunt Discriminator = 5011b8ab2f0SOliver Hunt CGF->EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator); 5021b8ab2f0SOliver Hunt else 5031b8ab2f0SOliver Hunt Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy); 5041b8ab2f0SOliver Hunt } 5051b8ab2f0SOliver Hunt 5061b8ab2f0SOliver Hunt return CGPointerAuthInfo(Authentication->getKey(), 5071b8ab2f0SOliver Hunt PointerAuthenticationMode::SignAndAuth, 5081b8ab2f0SOliver Hunt /* IsIsaPointer */ false, 5091b8ab2f0SOliver Hunt /* AuthenticatesNullValues */ false, Discriminator); 5101b8ab2f0SOliver Hunt } 511f6b06b42SAkira Hatanaka 512f6b06b42SAkira Hatanaka llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr, 513f6b06b42SAkira Hatanaka QualType SourceType, 514f6b06b42SAkira Hatanaka QualType DestType) { 515f6b06b42SAkira Hatanaka CGPointerAuthInfo CurAuthInfo, NewAuthInfo; 516f6b06b42SAkira Hatanaka if (SourceType->isSignableType()) 517f6b06b42SAkira Hatanaka CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType); 518f6b06b42SAkira Hatanaka 519f6b06b42SAkira Hatanaka if (DestType->isSignableType()) 520f6b06b42SAkira Hatanaka NewAuthInfo = getPointerAuthInfoForType(CGM, DestType); 521f6b06b42SAkira Hatanaka 522f6b06b42SAkira Hatanaka if (!CurAuthInfo && !NewAuthInfo) 523f6b06b42SAkira Hatanaka return ResultPtr; 524f6b06b42SAkira Hatanaka 525f6b06b42SAkira Hatanaka // If only one side of the cast is a function pointer, then we still need to 526f6b06b42SAkira Hatanaka // resign to handle casts to/from opaque pointers. 527f6b06b42SAkira Hatanaka if (!CurAuthInfo && DestType->isFunctionPointerType()) 528f6b06b42SAkira Hatanaka CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType); 529f6b06b42SAkira Hatanaka 530f6b06b42SAkira Hatanaka if (!NewAuthInfo && SourceType->isFunctionPointerType()) 531f6b06b42SAkira Hatanaka NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); 532f6b06b42SAkira Hatanaka 533f6b06b42SAkira Hatanaka return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo, 534f6b06b42SAkira Hatanaka /*IsKnownNonNull=*/false); 535f6b06b42SAkira Hatanaka } 536f6b06b42SAkira Hatanaka 537f6b06b42SAkira Hatanaka Address CodeGenFunction::authPointerToPointerCast(Address Ptr, 538f6b06b42SAkira Hatanaka QualType SourceType, 539f6b06b42SAkira Hatanaka QualType DestType) { 540f6b06b42SAkira Hatanaka CGPointerAuthInfo CurAuthInfo, NewAuthInfo; 541f6b06b42SAkira Hatanaka if (SourceType->isSignableType()) 542f6b06b42SAkira Hatanaka CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType); 543f6b06b42SAkira Hatanaka 544f6b06b42SAkira Hatanaka if (DestType->isSignableType()) 545f6b06b42SAkira Hatanaka NewAuthInfo = getPointerAuthInfoForType(CGM, DestType); 546f6b06b42SAkira Hatanaka 547f6b06b42SAkira Hatanaka if (!CurAuthInfo && !NewAuthInfo) 548f6b06b42SAkira Hatanaka return Ptr; 549f6b06b42SAkira Hatanaka 550f6b06b42SAkira Hatanaka if (!CurAuthInfo && DestType->isFunctionPointerType()) { 551f6b06b42SAkira Hatanaka // When casting a non-signed pointer to a function pointer, just set the 552f6b06b42SAkira Hatanaka // auth info on Ptr to the assumed schema. The pointer will be resigned to 553f6b06b42SAkira Hatanaka // the effective type when used. 554f6b06b42SAkira Hatanaka Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType)); 555f6b06b42SAkira Hatanaka return Ptr; 556f6b06b42SAkira Hatanaka } 557f6b06b42SAkira Hatanaka 558f6b06b42SAkira Hatanaka if (!NewAuthInfo && SourceType->isFunctionPointerType()) { 559f6b06b42SAkira Hatanaka NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); 560f6b06b42SAkira Hatanaka Ptr = Ptr.getResignedAddress(NewAuthInfo, *this); 561f6b06b42SAkira Hatanaka Ptr.setPointerAuthInfo(CGPointerAuthInfo()); 562f6b06b42SAkira Hatanaka return Ptr; 563f6b06b42SAkira Hatanaka } 564f6b06b42SAkira Hatanaka 565f6b06b42SAkira Hatanaka return Ptr; 566f6b06b42SAkira Hatanaka } 567f6b06b42SAkira Hatanaka 568f6b06b42SAkira Hatanaka Address CodeGenFunction::getAsNaturalAddressOf(Address Addr, 569f6b06b42SAkira Hatanaka QualType PointeeTy) { 570f6b06b42SAkira Hatanaka CGPointerAuthInfo Info = 571f6b06b42SAkira Hatanaka PointeeTy.isNull() ? CGPointerAuthInfo() 572f6b06b42SAkira Hatanaka : CGM.getPointerAuthInfoForPointeeType(PointeeTy); 573f6b06b42SAkira Hatanaka return Addr.getResignedAddress(Info, *this); 574f6b06b42SAkira Hatanaka } 575f6b06b42SAkira Hatanaka 576f6b06b42SAkira Hatanaka Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, 577f6b06b42SAkira Hatanaka CodeGenFunction &CGF) const { 578f6b06b42SAkira Hatanaka assert(isValid() && "pointer isn't valid"); 579f6b06b42SAkira Hatanaka CGPointerAuthInfo CurInfo = getPointerAuthInfo(); 580f6b06b42SAkira Hatanaka llvm::Value *Val; 581f6b06b42SAkira Hatanaka 582f6b06b42SAkira Hatanaka // Nothing to do if neither the current or the new ptrauth info needs signing. 583f6b06b42SAkira Hatanaka if (!CurInfo.isSigned() && !NewInfo.isSigned()) 584f6b06b42SAkira Hatanaka return Address(getBasePointer(), getElementType(), getAlignment(), 585f6b06b42SAkira Hatanaka isKnownNonNull()); 586f6b06b42SAkira Hatanaka 587f6b06b42SAkira Hatanaka assert(ElementType && "Effective type has to be set"); 588f6b06b42SAkira Hatanaka assert(!Offset && "unexpected non-null offset"); 589f6b06b42SAkira Hatanaka 590f6b06b42SAkira Hatanaka // If the current and the new ptrauth infos are the same and the offset is 591f6b06b42SAkira Hatanaka // null, just cast the base pointer to the effective type. 592f6b06b42SAkira Hatanaka if (CurInfo == NewInfo && !hasOffset()) 593f6b06b42SAkira Hatanaka Val = getBasePointer(); 594f6b06b42SAkira Hatanaka else 595f6b06b42SAkira Hatanaka Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo, 596f6b06b42SAkira Hatanaka NewInfo, isKnownNonNull()); 597f6b06b42SAkira Hatanaka 598f6b06b42SAkira Hatanaka Val = CGF.Builder.CreateBitCast(Val, getType()); 599f6b06b42SAkira Hatanaka return Address(Val, getElementType(), getAlignment(), NewInfo, 600f6b06b42SAkira Hatanaka /*Offset=*/nullptr, isKnownNonNull()); 601f6b06b42SAkira Hatanaka } 602f6b06b42SAkira Hatanaka 603cf50a84dSAkira Hatanaka llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const { 604cf50a84dSAkira Hatanaka return CGF.getAsNaturalPointerTo(*this, QualType()); 605cf50a84dSAkira Hatanaka } 606cf50a84dSAkira Hatanaka 607f6b06b42SAkira Hatanaka llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const { 608f6b06b42SAkira Hatanaka assert(isSimple()); 609f6b06b42SAkira Hatanaka return emitResignedPointer(getType(), CGF); 610f6b06b42SAkira Hatanaka } 611f6b06b42SAkira Hatanaka 612f6b06b42SAkira Hatanaka llvm::Value *LValue::emitResignedPointer(QualType PointeeTy, 613f6b06b42SAkira Hatanaka CodeGenFunction &CGF) const { 614f6b06b42SAkira Hatanaka assert(isSimple()); 615f6b06b42SAkira Hatanaka return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer(); 616f6b06b42SAkira Hatanaka } 617f6b06b42SAkira Hatanaka 618f6b06b42SAkira Hatanaka llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const { 619f6b06b42SAkira Hatanaka assert(isSimple()); 620f6b06b42SAkira Hatanaka return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; 621f6b06b42SAkira Hatanaka } 622