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