//===--- CGPointerAuth.cpp - IR generation for pointer authentication -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains common routines relating to the emission of
// pointer authentication operations.
//
//===----------------------------------------------------------------------===//

#include "CGCXXABI.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/Attr.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/SipHash.h"

using namespace clang;
using namespace CodeGen;

/// Given a pointer-authentication schema, return a concrete "other"
/// discriminator for it.
llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator(
    const PointerAuthSchema &Schema, GlobalDecl Decl, QualType Type) {
  switch (Schema.getOtherDiscrimination()) {
  case PointerAuthSchema::Discrimination::None:
    return nullptr;

  case PointerAuthSchema::Discrimination::Type:
    assert(!Type.isNull() && "type not provided for type-discriminated schema");
    return llvm::ConstantInt::get(
        IntPtrTy, getContext().getPointerAuthTypeDiscriminator(Type));

  case PointerAuthSchema::Discrimination::Decl:
    assert(Decl.getDecl() &&
           "declaration not provided for decl-discriminated schema");
    return llvm::ConstantInt::get(IntPtrTy,
                                  getPointerAuthDeclDiscriminator(Decl));

  case PointerAuthSchema::Discrimination::Constant:
    return llvm::ConstantInt::get(IntPtrTy, Schema.getConstantDiscrimination());
  }
  llvm_unreachable("bad discrimination kind");
}

uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
                                                  QualType FunctionType) {
  return CGM.getContext().getPointerAuthTypeDiscriminator(FunctionType);
}

uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule &CGM,
                                                  GlobalDecl Declaration) {
  return CGM.getPointerAuthDeclDiscriminator(Declaration);
}

/// Return the "other" decl-specific discriminator for the given decl.
uint16_t
CodeGenModule::getPointerAuthDeclDiscriminator(GlobalDecl Declaration) {
  uint16_t &EntityHash = PtrAuthDiscriminatorHashes[Declaration];

  if (EntityHash == 0) {
    const auto *ND = cast<NamedDecl>(Declaration.getDecl());
    if (ND->hasAttr<AsmLabelAttr>() &&
        ND->getAttr<AsmLabelAttr>()->getLabel().starts_with(
            LLDBManglingABI::FunctionLabelPrefix)) {
      // If the declaration comes from LLDB, the asm label has a prefix that
      // would producing a different discriminator. Compute the real C++ mangled
      // name instead so the discriminator matches what the original translation
      // unit used.
      SmallString<256> Buffer;
      llvm::raw_svector_ostream Out(Buffer);
      getCXXABI().getMangleContext().mangleCXXName(Declaration, Out);
      EntityHash = llvm::getPointerAuthStableSipHash(Out.str());
    } else {
      StringRef Name = getMangledName(Declaration);
      EntityHash = llvm::getPointerAuthStableSipHash(Name);
    }
  }

  return EntityHash;
}

/// Return the abstract pointer authentication schema for a pointer to the given
/// function type.
CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
  const auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
  if (!Schema)
    return CGPointerAuthInfo();

  assert(!Schema.isAddressDiscriminated() &&
         "function pointers cannot use address-specific discrimination");

  llvm::Constant *Discriminator = nullptr;
  if (T->isFunctionPointerType() || T->isFunctionReferenceType())
    T = T->getPointeeType();
  if (T->isFunctionType())
    Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T);

  return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
                           /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
                           Discriminator);
}

llvm::Value *
CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress,
                                                   llvm::Value *Discriminator) {
  StorageAddress = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
  auto Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend);
  return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
}

/// Emit the concrete pointer authentication informaton for the
/// given authentication schema.
CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo(
    const PointerAuthSchema &Schema, llvm::Value *StorageAddress,
    GlobalDecl SchemaDecl, QualType SchemaType) {
  if (!Schema)
    return CGPointerAuthInfo();

  llvm::Value *Discriminator =
      CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);

  if (Schema.isAddressDiscriminated()) {
    assert(StorageAddress &&
           "address not provided for address-discriminated schema");

    if (Discriminator)
      Discriminator =
          EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
    else
      Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
  }

  return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
                           Schema.isIsaPointer(),
                           Schema.authenticatesNullValues(), Discriminator);
}

CGPointerAuthInfo
CodeGenFunction::EmitPointerAuthInfo(PointerAuthQualifier Qual,
                                     Address StorageAddress) {
  assert(Qual && "don't call this if you don't know that the Qual is present");
  if (Qual.hasKeyNone())
    return CGPointerAuthInfo();

  llvm::Value *Discriminator = nullptr;
  if (unsigned Extra = Qual.getExtraDiscriminator())
    Discriminator = llvm::ConstantInt::get(IntPtrTy, Extra);

  if (Qual.isAddressDiscriminated()) {
    assert(StorageAddress.isValid() &&
           "address discrimination without address");
    llvm::Value *StoragePtr = StorageAddress.emitRawPointer(*this);
    if (Discriminator)
      Discriminator =
          EmitPointerAuthBlendDiscriminator(StoragePtr, Discriminator);
    else
      Discriminator = Builder.CreatePtrToInt(StoragePtr, IntPtrTy);
  }

  return CGPointerAuthInfo(Qual.getKey(), Qual.getAuthenticationMode(),
                           Qual.isIsaPointer(), Qual.authenticatesNullValues(),
                           Discriminator);
}

/// Return the natural pointer authentication for values of the given
/// pointee type.
static CGPointerAuthInfo
getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType) {
  if (PointeeType.isNull())
    return CGPointerAuthInfo();

  // Function pointers use the function-pointer schema by default.
  if (PointeeType->isFunctionType())
    return CGM.getFunctionPointerAuthInfo(PointeeType);

  // Normal data pointers never use direct pointer authentication by default.
  return CGPointerAuthInfo();
}

CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) {
  return ::getPointerAuthInfoForPointeeType(*this, T);
}

/// Return the natural pointer authentication for values of the given
/// pointer type.
static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM,
                                                   QualType PointerType) {
  assert(PointerType->isSignableType(CGM.getContext()));

  // Block pointers are currently not signed.
  if (PointerType->isBlockPointerType())
    return CGPointerAuthInfo();

  auto PointeeType = PointerType->getPointeeType();

  if (PointeeType.isNull())
    return CGPointerAuthInfo();

  return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
}

CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) {
  return ::getPointerAuthInfoForType(*this, T);
}

static std::pair<llvm::Value *, CGPointerAuthInfo>
emitLoadOfOrigPointerRValue(CodeGenFunction &CGF, const LValue &LV,
                            SourceLocation Loc) {
  llvm::Value *Value = CGF.EmitLoadOfScalar(LV, Loc);
  CGPointerAuthInfo AuthInfo;
  if (PointerAuthQualifier PtrAuth = LV.getQuals().getPointerAuth())
    AuthInfo = CGF.EmitPointerAuthInfo(PtrAuth, LV.getAddress());
  else
    AuthInfo = getPointerAuthInfoForType(CGF.CGM, LV.getType());
  return {Value, AuthInfo};
}

/// Retrieve a pointer rvalue and its ptrauth info. When possible, avoid
/// needlessly resigning the pointer.
std::pair<llvm::Value *, CGPointerAuthInfo>
CodeGenFunction::EmitOrigPointerRValue(const Expr *E) {
  assert(E->getType()->isSignableType(getContext()));

  E = E->IgnoreParens();
  if (const auto *Load = dyn_cast<ImplicitCastExpr>(E)) {
    if (Load->getCastKind() == CK_LValueToRValue) {
      E = Load->getSubExpr()->IgnoreParens();

      // We're semantically required to not emit loads of certain DREs naively.
      if (const auto *RefExpr = dyn_cast<DeclRefExpr>(E)) {
        if (ConstantEmission Result = tryEmitAsConstant(RefExpr)) {
          // Fold away a use of an intermediate variable.
          if (!Result.isReference())
            return {Result.getValue(),
                    getPointerAuthInfoForType(CGM, RefExpr->getType())};

          // Fold away a use of an intermediate reference.
          LValue LV = Result.getReferenceLValue(*this, RefExpr);
          return emitLoadOfOrigPointerRValue(*this, LV, RefExpr->getLocation());
        }
      }

      // Otherwise, load and use the pointer
      LValue LV = EmitCheckedLValue(E, CodeGenFunction::TCK_Load);
      return emitLoadOfOrigPointerRValue(*this, LV, E->getExprLoc());
    }
  }

  // Fallback: just use the normal rules for the type.
  llvm::Value *Value = EmitScalarExpr(E);
  return {Value, getPointerAuthInfoForType(CGM, E->getType())};
}

llvm::Value *
CodeGenFunction::EmitPointerAuthQualify(PointerAuthQualifier DestQualifier,
                                        const Expr *E,
                                        Address DestStorageAddress) {
  assert(DestQualifier);
  auto [Value, CurAuthInfo] = EmitOrigPointerRValue(E);

  CGPointerAuthInfo DestAuthInfo =
      EmitPointerAuthInfo(DestQualifier, DestStorageAddress);
  return emitPointerAuthResign(Value, E->getType(), CurAuthInfo, DestAuthInfo,
                               isPointerKnownNonNull(E));
}

llvm::Value *CodeGenFunction::EmitPointerAuthQualify(
    PointerAuthQualifier DestQualifier, llvm::Value *Value,
    QualType PointerType, Address DestStorageAddress, bool IsKnownNonNull) {
  assert(DestQualifier);

  CGPointerAuthInfo CurAuthInfo = getPointerAuthInfoForType(CGM, PointerType);
  CGPointerAuthInfo DestAuthInfo =
      EmitPointerAuthInfo(DestQualifier, DestStorageAddress);
  return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo,
                               IsKnownNonNull);
}

llvm::Value *CodeGenFunction::EmitPointerAuthUnqualify(
    PointerAuthQualifier CurQualifier, llvm::Value *Value, QualType PointerType,
    Address CurStorageAddress, bool IsKnownNonNull) {
  assert(CurQualifier);

  CGPointerAuthInfo CurAuthInfo =
      EmitPointerAuthInfo(CurQualifier, CurStorageAddress);
  CGPointerAuthInfo DestAuthInfo = getPointerAuthInfoForType(CGM, PointerType);
  return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo,
                               IsKnownNonNull);
}

static bool isZeroConstant(const llvm::Value *Value) {
  if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value))
    return CI->isZero();
  return false;
}

static bool equalAuthPolicies(const CGPointerAuthInfo &Left,
                              const CGPointerAuthInfo &Right) {
  assert((Left.isSigned() || Right.isSigned()) &&
         "shouldn't be called if neither is signed");
  if (Left.isSigned() != Right.isSigned())
    return false;
  return Left.getKey() == Right.getKey() &&
         Left.getAuthenticationMode() == Right.getAuthenticationMode() &&
         Left.isIsaPointer() == Right.isIsaPointer() &&
         Left.authenticatesNullValues() == Right.authenticatesNullValues() &&
         Left.getDiscriminator() == Right.getDiscriminator();
}

// Return the discriminator or return zero if the discriminator is null.
static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info,
                                           CGBuilderTy &Builder) {
  llvm::Value *Discriminator = Info.getDiscriminator();
  return Discriminator ? Discriminator : Builder.getSize(0);
}

llvm::Value *
CodeGenFunction::emitPointerAuthResignCall(llvm::Value *Value,
                                           const CGPointerAuthInfo &CurAuth,
                                           const CGPointerAuthInfo &NewAuth) {
  assert(CurAuth && NewAuth);

  if (CurAuth.getAuthenticationMode() !=
          PointerAuthenticationMode::SignAndAuth ||
      NewAuth.getAuthenticationMode() !=
          PointerAuthenticationMode::SignAndAuth) {
    llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value);
    return EmitPointerAuthSign(NewAuth, AuthedValue);
  }
  // Convert the pointer to intptr_t before signing it.
  auto *OrigType = Value->getType();
  Value = Builder.CreatePtrToInt(Value, IntPtrTy);

  auto *CurKey = Builder.getInt32(CurAuth.getKey());
  auto *NewKey = Builder.getInt32(NewAuth.getKey());

  llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder);
  llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder);

  // call i64 @llvm.ptrauth.resign(i64 %pointer,
  //                               i32 %curKey, i64 %curDiscriminator,
  //                               i32 %newKey, i64 %newDiscriminator)
  auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
  Value = EmitRuntimeCall(
      Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});

  // Convert back to the original type.
  Value = Builder.CreateIntToPtr(Value, OrigType);
  return Value;
}

llvm::Value *CodeGenFunction::emitPointerAuthResign(
    llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo,
    const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) {
  // Fast path: if neither schema wants a signature, we're done.
  if (!CurAuthInfo && !NewAuthInfo)
    return Value;

  llvm::Value *Null = nullptr;
  // If the value is obviously null, we're done.
  if (auto *PointerValue = dyn_cast<llvm::PointerType>(Value->getType())) {
    Null = CGM.getNullPointer(PointerValue, Type);
  } else {
    assert(Value->getType()->isIntegerTy());
    Null = llvm::ConstantInt::get(IntPtrTy, 0);
  }
  if (Value == Null)
    return Value;

  // If both schemas sign the same way, we're done.
  if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) {
    const llvm::Value *CurD = CurAuthInfo.getDiscriminator();
    const llvm::Value *NewD = NewAuthInfo.getDiscriminator();
    if (CurD == NewD)
      return Value;

    if ((CurD == nullptr && isZeroConstant(NewD)) ||
        (NewD == nullptr && isZeroConstant(CurD)))
      return Value;
  }

  llvm::BasicBlock *InitBB = Builder.GetInsertBlock();
  llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr;

  // Null pointers have to be mapped to null, and the ptrauth_resign
  // intrinsic doesn't do that.
  if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) {
    ContBB = createBasicBlock("resign.cont");
    ResignBB = createBasicBlock("resign.nonnull");

    auto *IsNonNull = Builder.CreateICmpNE(Value, Null);
    Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
    EmitBlock(ResignBB);
  }

  // Perform the auth/sign/resign operation.
  if (!NewAuthInfo)
    Value = EmitPointerAuthAuth(CurAuthInfo, Value);
  else if (!CurAuthInfo)
    Value = EmitPointerAuthSign(NewAuthInfo, Value);
  else
    Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo);

  // Clean up with a phi if we branched before.
  if (ContBB) {
    EmitBlock(ContBB);
    auto *Phi = Builder.CreatePHI(Value->getType(), 2);
    Phi->addIncoming(Null, InitBB);
    Phi->addIncoming(Value, ResignBB);
    Value = Phi;
  }

  return Value;
}

void CodeGenFunction::EmitPointerAuthCopy(PointerAuthQualifier Qual, QualType T,
                                          Address DestAddress,
                                          Address SrcAddress) {
  assert(Qual);
  llvm::Value *Value = Builder.CreateLoad(SrcAddress);

  // If we're using address-discrimination, we have to re-sign the value.
  if (Qual.isAddressDiscriminated()) {
    CGPointerAuthInfo SrcPtrAuth = EmitPointerAuthInfo(Qual, SrcAddress);
    CGPointerAuthInfo DestPtrAuth = EmitPointerAuthInfo(Qual, DestAddress);
    Value = emitPointerAuthResign(Value, T, SrcPtrAuth, DestPtrAuth,
                                  /*IsKnownNonNull=*/false);
  }

  Builder.CreateStore(Value, DestAddress);
}

llvm::Constant *
CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key,
                                        llvm::Constant *StorageAddress,
                                        llvm::ConstantInt *OtherDiscriminator) {
  llvm::Constant *AddressDiscriminator;
  if (StorageAddress) {
    assert(StorageAddress->getType() == DefaultPtrTy);
    AddressDiscriminator = StorageAddress;
  } else {
    AddressDiscriminator = llvm::Constant::getNullValue(DefaultPtrTy);
  }

  llvm::ConstantInt *IntegerDiscriminator;
  if (OtherDiscriminator) {
    assert(OtherDiscriminator->getType() == Int64Ty);
    IntegerDiscriminator = OtherDiscriminator;
  } else {
    IntegerDiscriminator = llvm::ConstantInt::get(Int64Ty, 0);
  }

  return llvm::ConstantPtrAuth::get(
      Pointer, llvm::ConstantInt::get(Int32Ty, Key), IntegerDiscriminator,
      AddressDiscriminator,
      /*DeactivationSymbol=*/llvm::Constant::getNullValue(DefaultPtrTy));
}

/// Does a given PointerAuthScheme require us to sign a value
bool CodeGenModule::shouldSignPointer(const PointerAuthSchema &Schema) {
  auto AuthenticationMode = Schema.getAuthenticationMode();
  return AuthenticationMode == PointerAuthenticationMode::SignAndStrip ||
         AuthenticationMode == PointerAuthenticationMode::SignAndAuth;
}

/// Sign a constant pointer using the given scheme, producing a constant
/// with the same IR type.
llvm::Constant *CodeGenModule::getConstantSignedPointer(
    llvm::Constant *Pointer, const PointerAuthSchema &Schema,
    llvm::Constant *StorageAddress, GlobalDecl SchemaDecl,
    QualType SchemaType) {
  assert(shouldSignPointer(Schema));
  llvm::ConstantInt *OtherDiscriminator =
      getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);

  return getConstantSignedPointer(Pointer, Schema.getKey(), StorageAddress,
                                  OtherDiscriminator);
}

llvm::Constant *
CodeGen::getConstantSignedPointer(CodeGenModule &CGM, llvm::Constant *Pointer,
                                  unsigned Key, llvm::Constant *StorageAddress,
                                  llvm::ConstantInt *OtherDiscriminator) {
  return CGM.getConstantSignedPointer(Pointer, Key, StorageAddress,
                                      OtherDiscriminator);
}

/// If applicable, sign a given constant function pointer with the ABI rules for
/// functionType.
llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer,
                                                  QualType FunctionType) {
  assert(FunctionType->isFunctionType() ||
         FunctionType->isFunctionReferenceType() ||
         FunctionType->isFunctionPointerType());

  if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType))
    return getConstantSignedPointer(
        Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr,
        cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));

  return Pointer;
}

llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
                                                  llvm::Type *Ty) {
  const auto *FD = cast<FunctionDecl>(GD.getDecl());
  QualType FuncType = FD->getType();

  // Annoyingly, K&R functions have prototypes in the clang AST, but
  // expressions referring to them are unprototyped.
  if (!FD->hasPrototype())
    if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
      FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
                                                Proto->getExtInfo());

  return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType);
}

CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) {
  assert(FT->getAs<MemberPointerType>() && "MemberPointerType expected");
  const auto &Schema = getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
  if (!Schema)
    return CGPointerAuthInfo();

  assert(!Schema.isAddressDiscriminated() &&
         "function pointers cannot use address-specific discrimination");

  llvm::ConstantInt *Discriminator =
      getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), FT);
  return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
                           /* IsIsaPointer */ false,
                           /* AuthenticatesNullValues */ false, Discriminator);
}

llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer,
                                                        QualType FT) {
  if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT))
    return getConstantSignedPointer(
        Pointer, PointerAuth.getKey(), nullptr,
        cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));

  if (const auto *MFT = dyn_cast<MemberPointerType>(FT.getTypePtr())) {
    if (MFT->hasPointeeToCFIUncheckedCalleeFunctionType())
      Pointer = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(Pointer));
  }

  return Pointer;
}

llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD,
                                                        llvm::Type *Ty) {
  QualType FT = FD->getType();
  FT = getContext().getMemberPointerType(FT, /*Qualifier=*/std::nullopt,
                                         cast<CXXMethodDecl>(FD)->getParent());
  return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT);
}

std::optional<PointerAuthQualifier>
CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass,
                                              bool IsVTTEntry) {
  auto DefaultAuthentication =
      IsVTTEntry ? getCodeGenOpts().PointerAuth.CXXVTTVTablePointers
                 : getCodeGenOpts().PointerAuth.CXXVTablePointers;
  if (!DefaultAuthentication)
    return std::nullopt;
  const CXXRecordDecl *PrimaryBase =
      Context.baseForVTableAuthentication(ThisClass);
  const CXXRecordDecl *TypeDiscriminatorClass =
      IsVTTEntry ? ThisClass : PrimaryBase;

  unsigned Key = DefaultAuthentication.getKey();
  bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
  auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
  unsigned TypeBasedDiscriminator =
      Context.getPointerAuthVTablePointerDiscriminator(TypeDiscriminatorClass,
                                                       IsVTTEntry);
  unsigned Discriminator;
  if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) {
    Discriminator = TypeBasedDiscriminator;
  } else if (DefaultDiscrimination ==
             PointerAuthSchema::Discrimination::Constant) {
    Discriminator = DefaultAuthentication.getConstantDiscrimination();
  } else {
    assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None);
    Discriminator = 0;
  }
  auto ExplicitAuthentication =
      PrimaryBase->getAttr<VTablePointerAuthenticationAttr>();

  // TODO: enable explicit authentication path for VTT vtable entries.
  if (!IsVTTEntry && ExplicitAuthentication) {
    auto ExplicitAddressDiscrimination =
        ExplicitAuthentication->getAddressDiscrimination();
    auto ExplicitDiscriminator =
        ExplicitAuthentication->getExtraDiscrimination();

    unsigned ExplicitKey = ExplicitAuthentication->getKey();
    if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
      return std::nullopt;

    if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
      if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
        Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA;
      else {
        assert(ExplicitKey ==
               VTablePointerAuthenticationAttr::ProcessDependent);
        Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB;
      }
    }

    if (ExplicitAddressDiscrimination !=
        VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
      AddressDiscriminated =
          ExplicitAddressDiscrimination ==
          VTablePointerAuthenticationAttr::AddressDiscrimination;

    if (ExplicitDiscriminator ==
        VTablePointerAuthenticationAttr::TypeDiscrimination)
      Discriminator = TypeBasedDiscriminator;
    else if (ExplicitDiscriminator ==
             VTablePointerAuthenticationAttr::CustomDiscrimination)
      Discriminator = ExplicitAuthentication->getCustomDiscriminationValue();
    else if (ExplicitDiscriminator ==
             VTablePointerAuthenticationAttr::NoExtraDiscrimination)
      Discriminator = 0;
  }
  return PointerAuthQualifier::Create(Key, AddressDiscriminated, Discriminator,
                                      PointerAuthenticationMode::SignAndAuth,
                                      /* IsIsaPointer */ false,
                                      /* AuthenticatesNullValues */ false);
}

std::optional<PointerAuthQualifier>
CodeGenModule::getVTablePointerAuthentication(const CXXRecordDecl *Record,
                                              bool IsVTTEntry) {
  if (!Record->getDefinition() || !Record->isPolymorphic())
    return std::nullopt;

  if (IsVTTEntry)
    return computeVTPointerAuthentication(Record, IsVTTEntry);

  auto Existing = VTablePtrAuthInfos.find(Record);
  if (Existing != VTablePtrAuthInfos.end())
    return Existing->getSecond();

  std::optional<PointerAuthQualifier> Authentication =
      computeVTPointerAuthentication(Record, IsVTTEntry);
  VTablePtrAuthInfos.insert(std::make_pair(Record, Authentication));
  return Authentication;
}

std::optional<CGPointerAuthInfo> CodeGenModule::getVTablePointerAuthInfo(
    CodeGenFunction *CGF, const CXXRecordDecl *Record,
    llvm::Value *StorageAddress, bool IsVTTEntry) {
  auto Authentication = getVTablePointerAuthentication(Record, IsVTTEntry);
  if (!Authentication)
    return std::nullopt;

  llvm::Value *Discriminator = nullptr;
  if (auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
    Discriminator = llvm::ConstantInt::get(IntPtrTy, ExtraDiscriminator);

  if (Authentication->isAddressDiscriminated()) {
    assert(StorageAddress &&
           "address not provided for address-discriminated schema");
    if (Discriminator)
      Discriminator =
          CGF->EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
    else
      Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
  }

  return CGPointerAuthInfo(Authentication->getKey(),
                           PointerAuthenticationMode::SignAndAuth,
                           /* IsIsaPointer */ false,
                           /* AuthenticatesNullValues */ false, Discriminator);
}

llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr,
                                                       QualType SourceType,
                                                       QualType DestType) {
  CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
  if (SourceType->isSignableType(getContext()))
    CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);

  if (DestType->isSignableType(getContext()))
    NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);

  if (!CurAuthInfo && !NewAuthInfo)
    return ResultPtr;

  // If only one side of the cast is a function pointer, then we still need to
  // resign to handle casts to/from opaque pointers.
  if (!CurAuthInfo && DestType->isFunctionPointerType())
    CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType);

  if (!NewAuthInfo && SourceType->isFunctionPointerType())
    NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);

  return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo,
                               /*IsKnownNonNull=*/false);
}

Address CodeGenFunction::authPointerToPointerCast(Address Ptr,
                                                  QualType SourceType,
                                                  QualType DestType) {
  CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
  if (SourceType->isSignableType(getContext()))
    CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);

  if (DestType->isSignableType(getContext()))
    NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);

  if (!CurAuthInfo && !NewAuthInfo)
    return Ptr;

  if (!CurAuthInfo && DestType->isFunctionPointerType()) {
    // When casting a non-signed pointer to a function pointer, just set the
    // auth info on Ptr to the assumed schema. The pointer will be resigned to
    // the effective type when used.
    Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType));
    return Ptr;
  }

  if (!NewAuthInfo && SourceType->isFunctionPointerType()) {
    NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
    Ptr = Ptr.getResignedAddress(NewAuthInfo, *this);
    Ptr.setPointerAuthInfo(CGPointerAuthInfo());
    return Ptr;
  }

  return Ptr;
}

Address CodeGenFunction::getAsNaturalAddressOf(Address Addr,
                                               QualType PointeeTy) {
  CGPointerAuthInfo Info =
      PointeeTy.isNull() ? CGPointerAuthInfo()
                         : CGM.getPointerAuthInfoForPointeeType(PointeeTy);
  return Addr.getResignedAddress(Info, *this);
}

Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo,
                                    CodeGenFunction &CGF) const {
  assert(isValid() && "pointer isn't valid");
  CGPointerAuthInfo CurInfo = getPointerAuthInfo();
  llvm::Value *Val;

  // Nothing to do if neither the current or the new ptrauth info needs signing.
  if (!CurInfo.isSigned() && !NewInfo.isSigned())
    return Address(getBasePointer(), getElementType(), getAlignment(),
                   isKnownNonNull());

  assert(ElementType && "Effective type has to be set");
  assert(!Offset && "unexpected non-null offset");

  // If the current and the new ptrauth infos are the same and the offset is
  // null, just cast the base pointer to the effective type.
  if (CurInfo == NewInfo && !hasOffset())
    Val = getBasePointer();
  else
    Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo,
                                    NewInfo, isKnownNonNull());

  return Address(Val, getElementType(), getAlignment(), NewInfo,
                 /*Offset=*/nullptr, isKnownNonNull());
}

llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const {
  return CGF.getAsNaturalPointerTo(*this, QualType());
}

llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const {
  assert(isSimple());
  return emitResignedPointer(getType(), CGF);
}

llvm::Value *LValue::emitResignedPointer(QualType PointeeTy,
                                         CodeGenFunction &CGF) const {
  assert(isSimple());
  return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer();
}

llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const {
  assert(isSimple());
  return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr;
}
