llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Ahmed Bougacha (ahmedbougacha)

<details>
<summary>Changes</summary>

The functions are currently always signed/authenticated with zero discriminator.

Co-Authored-By: John McCall &lt;rjmccall@<!-- -->apple.com&gt;

---

Patch is 37.62 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/93906.diff


24 Files Affected:

- (modified) clang/include/clang/Basic/CodeGenOptions.h (+4) 
- (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+3) 
- (modified) clang/include/clang/Basic/LangOptions.h (+2) 
- (modified) clang/include/clang/Basic/PointerAuthOptions.h (+136) 
- (modified) clang/include/clang/Frontend/CompilerInvocation.h (+10) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+1-2) 
- (modified) clang/lib/CodeGen/CGCall.cpp (+3) 
- (modified) clang/lib/CodeGen/CGCall.h (+22-6) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+9-8) 
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+18-1) 
- (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+51) 
- (added) clang/lib/CodeGen/CGPointerAuthInfo.h (+96) 
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+22) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+7) 
- (modified) clang/lib/CodeGen/CodeGenModule.h (+34) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+36) 
- (modified) clang/lib/Headers/ptrauth.h (+34) 
- (added) clang/test/CodeGen/ptrauth-function-attributes.c (+13) 
- (added) clang/test/CodeGen/ptrauth-function-init-fail.c (+5) 
- (added) clang/test/CodeGen/ptrauth-function-init.c (+31) 
- (added) clang/test/CodeGen/ptrauth-function-lvalue-cast.c (+23) 
- (added) clang/test/CodeGen/ptrauth-function.c (+28) 
- (added) clang/test/CodeGen/ptrauth-weak_import.c (+10) 
- (added) clang/test/CodeGenCXX/ptrauth.cpp (+24) 


``````````diff
diff --git a/clang/include/clang/Basic/CodeGenOptions.h 
b/clang/include/clang/Basic/CodeGenOptions.h
index 9469a424045bb..502722a6ec4eb 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
 #define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
 
+#include "clang/Basic/PointerAuthOptions.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Basic/XRayInstr.h"
 #include "llvm/ADT/FloatingPointMode.h"
@@ -388,6 +389,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
 
   std::vector<std::string> Reciprocals;
 
+  /// Configuration for pointer-signing.
+  PointerAuthOptions PointerAuth;
+
   /// The preferred width for auto-vectorization transforms. This is intended 
to
   /// override default transforms based on the width of the architected vector
   /// registers.
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 773b234cd68fe..6cbb0c8401c15 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -351,6 +351,9 @@ def err_drv_omp_host_ir_file_not_found : Error<
   "target regions but cannot be found">;
 def err_drv_omp_host_target_not_supported : Error<
   "target '%0' is not a supported OpenMP host target">;
+def err_drv_ptrauth_not_supported : Error<
+  "target '%0' does not support native pointer authentication">;
+
 def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
   "'-fopenmp-targets' must be used in conjunction with a '-fopenmp' option "
   "compatible with offloading; e.g., '-fopenmp=libomp' or 
'-fopenmp=libiomp5'">;
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 75e88afbd9705..5216822e45b1b 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -346,6 +346,8 @@ class LangOptionsBase {
     BKey
   };
 
+  using PointerAuthenticationMode = ::clang::PointerAuthenticationMode;
+
   enum class ThreadModelKind {
     /// POSIX Threads.
     POSIX,
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h 
b/clang/include/clang/Basic/PointerAuthOptions.h
index e5cdcc31ebfb7..32b179e3f9460 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -14,10 +14,146 @@
 #ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
 #define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
 
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetOptions.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
 namespace clang {
 
 constexpr unsigned PointerAuthKeyNone = -1;
 
+class PointerAuthSchema {
+public:
+  enum class Kind : unsigned {
+    None,
+    ARM8_3,
+  };
+
+  /// Hardware pointer-signing keys in ARM8.3.
+  ///
+  /// These values are the same used in ptrauth.h.
+  enum class ARM8_3Key : unsigned {
+    ASIA = 0,
+    ASIB = 1,
+    ASDA = 2,
+    ASDB = 3
+  };
+
+  /// Forms of extra discrimination.
+  enum class Discrimination : unsigned {
+    /// No additional discrimination.
+    None,
+
+    /// Discriminate using a constant value.
+    Constant,
+  };
+
+private:
+  Kind TheKind : 2;
+  unsigned IsAddressDiscriminated : 1;
+  unsigned IsIsaPointer : 1;
+  unsigned AuthenticatesNullValues : 1;
+  PointerAuthenticationMode SelectedAuthenticationMode : 2;
+  Discrimination DiscriminationKind : 2;
+  unsigned Key : 4;
+  unsigned ConstantDiscriminator : 16;
+
+public:
+  PointerAuthSchema() : TheKind(Kind::None) {}
+
+  PointerAuthSchema(
+      ARM8_3Key Key, bool IsAddressDiscriminated,
+      PointerAuthenticationMode AuthenticationMode,
+      Discrimination OtherDiscrimination,
+      std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
+      bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
+      : TheKind(Kind::ARM8_3), IsAddressDiscriminated(IsAddressDiscriminated),
+        IsIsaPointer(IsIsaPointer),
+        AuthenticatesNullValues(AuthenticatesNullValues),
+        SelectedAuthenticationMode(AuthenticationMode),
+        DiscriminationKind(OtherDiscrimination), Key(unsigned(Key)) {
+    assert((getOtherDiscrimination() != Discrimination::Constant ||
+            ConstantDiscriminatorOrNone) &&
+           "constant discrimination requires a constant!");
+    if (ConstantDiscriminatorOrNone)
+      ConstantDiscriminator = *ConstantDiscriminatorOrNone;
+  }
+
+  PointerAuthSchema(
+      ARM8_3Key Key, bool IsAddressDiscriminated,
+      Discrimination OtherDiscrimination,
+      std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
+      bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
+      : PointerAuthSchema(Key, IsAddressDiscriminated,
+                          PointerAuthenticationMode::SignAndAuth,
+                          OtherDiscrimination, ConstantDiscriminatorOrNone,
+                          IsIsaPointer, AuthenticatesNullValues) {}
+
+  Kind getKind() const { return TheKind; }
+
+  explicit operator bool() const { return isEnabled(); }
+
+  bool isEnabled() const { return getKind() != Kind::None; }
+
+  bool isAddressDiscriminated() const {
+    assert(getKind() != Kind::None);
+    return IsAddressDiscriminated;
+  }
+
+  bool isIsaPointer() const {
+    assert(getKind() != Kind::None);
+    return IsIsaPointer;
+  }
+
+  bool authenticatesNullValues() const {
+    assert(getKind() != Kind::None);
+    return AuthenticatesNullValues;
+  }
+
+  bool hasOtherDiscrimination() const {
+    return getOtherDiscrimination() != Discrimination::None;
+  }
+
+  Discrimination getOtherDiscrimination() const {
+    assert(getKind() != Kind::None);
+    return DiscriminationKind;
+  }
+
+  uint16_t getConstantDiscrimination() const {
+    assert(getOtherDiscrimination() == Discrimination::Constant);
+    return (uint16_t)ConstantDiscriminator;
+  }
+
+  unsigned getKey() const {
+    switch (getKind()) {
+    case Kind::None:
+      llvm_unreachable("calling getKey() on disabled schema");
+    case Kind::ARM8_3:
+      return unsigned(getARM8_3Key());
+    }
+    llvm_unreachable("bad key kind");
+  }
+
+  PointerAuthenticationMode getAuthenticationMode() const {
+    return SelectedAuthenticationMode;
+  }
+
+  ARM8_3Key getARM8_3Key() const {
+    assert(getKind() == Kind::ARM8_3);
+    return ARM8_3Key(Key);
+  }
+};
+
+struct PointerAuthOptions {
+  /// The ABI for C function pointers.
+  PointerAuthSchema FunctionPointers;
+};
+
 } // end namespace clang
 
 #endif
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h 
b/clang/include/clang/Frontend/CompilerInvocation.h
index 1a2a39411e58d..e60e5aad6c70d 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -305,6 +305,16 @@ class CompilerInvocation : public CompilerInvocationBase {
   /// executable), for finding the builtin compiler path.
   static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
 
+  /// Populate \p Opts with the default set of pointer authentication-related
+  /// options given \p LangOpts and \p Triple. Return true if defaults are
+  /// available.
+  ///
+  /// Note: This is intended to be used by tools which must be aware of
+  /// pointer authentication-related code generation, e.g. lldb.
+  static bool setDefaultPointerAuthOptions(PointerAuthOptions &Opts,
+                                           const LangOptions &LangOpts,
+                                           const llvm::Triple &Triple);
+
   /// Retrieve a module hash string that is suitable for uniquely
   /// identifying the conditions under which the module was built.
   std::string getModuleHash() const;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b2e3b6fa64284..1f528f9490cd2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5999,8 +5999,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
   // If this is a predefined lib function (e.g. malloc), emit the call
   // using exactly the normal call path.
   if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
-    return emitLibraryCall(
-        *this, FD, E, cast<llvm::Constant>(EmitScalarExpr(E->getCallee())));
+    return emitLibraryCall(*this, FD, E, CGM.getRawFunctionPointer(FD));
 
   // Check that a call to a target specific builtin has the correct target
   // features.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 97449a5e51e73..c33f37bf5b8c4 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5677,6 +5677,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
       !isa_and_nonnull<FunctionDecl>(TargetDecl))
     EmitKCFIOperandBundle(ConcreteCallee, BundleList);
 
+  // Add the pointer-authentication bundle.
+  EmitPointerAuthOperandBundle(ConcreteCallee.getPointerAuthInfo(), 
BundleList);
+
   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
     if (FD->hasAttr<StrictFPAttr>())
       // All calls within a strictfp function are marked strictfp
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 6b676ac196db2..4b0e1561b4ef5 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H
 #define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
 
+#include "CGPointerAuthInfo.h"
 #include "CGValue.h"
 #include "EHScopeStack.h"
 #include "clang/AST/ASTFwd.h"
@@ -69,6 +70,10 @@ class CGCallee {
     Last = Virtual
   };
 
+  struct OrdinaryInfoStorage {
+    CGCalleeInfo AbstractInfo;
+    CGPointerAuthInfo PointerAuthInfo;
+  };
   struct BuiltinInfoStorage {
     const FunctionDecl *Decl;
     unsigned ID;
@@ -85,7 +90,7 @@ class CGCallee {
 
   SpecialKind KindOrFunctionPointer;
   union {
-    CGCalleeInfo AbstractInfo;
+    OrdinaryInfoStorage OrdinaryInfo;
     BuiltinInfoStorage BuiltinInfo;
     PseudoDestructorInfoStorage PseudoDestructorInfo;
     VirtualInfoStorage VirtualInfo;
@@ -104,10 +109,13 @@ class CGCallee {
 
   /// Construct a callee.  Call this constructor directly when this
   /// isn't a direct call.
-  CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
+  CGCallee(
+      const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,
+      const CGPointerAuthInfo &pointerAuthInfo = /*FIXME*/ CGPointerAuthInfo())
       : KindOrFunctionPointer(
             SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
-    AbstractInfo = abstractInfo;
+    OrdinaryInfo.AbstractInfo = abstractInfo;
+    OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;
     assert(functionPtr && "configuring callee without function pointer");
     assert(functionPtr->getType()->isPointerTy());
   }
@@ -128,12 +136,12 @@ class CGCallee {
 
   static CGCallee forDirect(llvm::Constant *functionPtr,
                             const CGCalleeInfo &abstractInfo = CGCalleeInfo()) 
{
-    return CGCallee(abstractInfo, functionPtr);
+    return CGCallee(abstractInfo, functionPtr, CGPointerAuthInfo());
   }
 
   static CGCallee forDirect(llvm::FunctionCallee functionPtr,
                             const CGCalleeInfo &abstractInfo = CGCalleeInfo()) 
{
-    return CGCallee(abstractInfo, functionPtr.getCallee());
+    return CGCallee(abstractInfo, functionPtr.getCallee(), 
CGPointerAuthInfo());
   }
 
   static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
@@ -173,7 +181,11 @@ class CGCallee {
     if (isVirtual())
       return VirtualInfo.MD;
     assert(isOrdinary());
-    return AbstractInfo;
+    return OrdinaryInfo.AbstractInfo;
+  }
+  const CGPointerAuthInfo &getPointerAuthInfo() const {
+    assert(isOrdinary());
+    return OrdinaryInfo.PointerAuthInfo;
   }
   llvm::Value *getFunctionPointer() const {
     assert(isOrdinary());
@@ -184,6 +196,10 @@ class CGCallee {
     KindOrFunctionPointer =
         SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
   }
+  void setPointerAuthInfo(CGPointerAuthInfo pointerAuth) {
+    assert(isOrdinary());
+    OrdinaryInfo.PointerAuthInfo = pointerAuth;
+  }
 
   bool isVirtual() const {
     return KindOrFunctionPointer == SpecialKind::Virtual;
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index d6478cc6835d8..152f51f5865e0 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2850,22 +2850,22 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction 
&CGF,
   return LV;
 }
 
-static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM,
-                                               GlobalDecl GD) {
+llvm::Constant *CodeGenModule::getRawFunctionPointer(GlobalDecl GD,
+                                                     llvm::Type *Ty) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
   if (FD->hasAttr<WeakRefAttr>()) {
-    ConstantAddress aliasee = CGM.GetWeakRefReference(FD);
+    ConstantAddress aliasee = GetWeakRefReference(FD);
     return aliasee.getPointer();
   }
 
-  llvm::Constant *V = CGM.GetAddrOfFunction(GD);
+  llvm::Constant *V = GetAddrOfFunction(GD, Ty);
   return V;
 }
 
 static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E,
                                      GlobalDecl GD) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
-  llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, GD);
+  llvm::Constant *V = CGF.CGM.getFunctionPointer(GD);
   CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
   return CGF.MakeAddrLValue(V, E->getType(), Alignment,
                             AlignmentSource::Decl);
@@ -5501,7 +5501,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, 
GlobalDecl GD) {
     // name to make it clear it's not the actual builtin.
     if (CGF.CurFn->getName() != FDInlineName &&
         OnlyHasInlineBuiltinDeclaration(FD)) {
-      llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+      llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
       llvm::Function *Fn = llvm::cast<llvm::Function>(CalleePtr);
       llvm::Module *M = Fn->getParent();
       llvm::Function *Clone = M->getFunction(FDInlineName);
@@ -5524,7 +5524,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, 
GlobalDecl GD) {
       return CGCallee::forBuiltin(builtinID, FD);
   }
 
-  llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+  llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
   if (CGF.CGM.getLangOpts().CUDA && !CGF.CGM.getLangOpts().CUDAIsDevice &&
       FD->hasAttr<CUDAGlobalAttr>())
     CalleePtr = CGF.CGM.getCUDARuntime().getKernelStub(
@@ -5581,7 +5581,8 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
     GD = GlobalDecl(VD);
 
   CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD);
-  CGCallee callee(calleeInfo, calleePtr);
+  CGPointerAuthInfo pointerAuth = CGM.getFunctionPointerAuthInfo(functionType);
+  CGCallee callee(calleeInfo, calleePtr, pointerAuth);
   return callee;
 }
 
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp 
b/clang/lib/CodeGen/CGExprConstant.cpp
index de9380c0e63be..bfb545a2fe1f6 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1956,8 +1956,25 @@ ConstantLValueEmitter::tryEmitBase(const 
APValue::LValueBase &base) {
     if (D->hasAttr<WeakRefAttr>())
       return CGM.GetWeakRefReference(D).getPointer();
 
+    auto PtrAuthSign = [&](llvm::Constant *C) {
+      CGPointerAuthInfo AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
+
+      if (AuthInfo) {
+        if (hasNonZeroOffset())
+          return ConstantLValue(nullptr);
+
+        C = applyOffset(C);
+        C = CGM.getConstantSignedPointer(
+            C, AuthInfo.getKey(), nullptr,
+            cast_or_null<llvm::Constant>(AuthInfo.getDiscriminator()));
+        return ConstantLValue(C, /*applied offset*/ true);
+      }
+
+      return ConstantLValue(C);
+    };
+
     if (auto FD = dyn_cast<FunctionDecl>(D))
-      return CGM.GetAddrOfFunction(FD);
+      return PtrAuthSign(CGM.getRawFunctionPointer(FD));
 
     if (auto VD = dyn_cast<VarDecl>(D)) {
       // We can never refer to a variable with local storage.
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp 
b/clang/lib/CodeGen/CGPointerAuth.cpp
index 756c00aa42c8c..adfa721ac89d3 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -28,6 +28,24 @@
 using namespace clang;
 using namespace CodeGen;
 
+/// Return the abstract pointer authentication schema for a pointer to the 
given
+/// function type.
+CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
+  auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
+  if (!Schema)
+    return CGPointerAuthInfo();
+
+  assert(!Schema.isAddressDiscriminated() &&
+         "function pointers cannot use address-specific discrimination");
+
+  assert(!Schema.hasOtherDiscrimination() &&
+         "function pointers don't support any discrimination yet");
+
+  return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
+                           /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
+                           /*Discriminator=*/nullptr);
+}
+
 /// Build a signed-pointer "ptrauth" constant.
 static llvm::ConstantPtrAuth *
 buildConstantAddress(CodeGenModule &CGM, llvm::Constant *pointer, unsigned key,
@@ -75,3 +93,36 @@ CodeGen::getConstantSignedPointer(CodeGenModule &CGM,
   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,
+                                                  GlobalDecl GD) {
+  assert(functionType->isFunctionType() ||
+         functionType->isFunctionReferenceType() ||
+         functionType->isFunctionPointerType());
+
+  if (auto pointerAuth = getFunctionPointerAuthInfo(functionType)) {
+    return getConstantSignedPointer(
+      pointer, pointerAuth.getKey(), nullptr,
+      cast_or_null<llvm::Constant>(pointerAuth.getDiscriminator()));
+  }
+
+  return pointer;
+}
+
+llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
+                                                  llvm::Type *Ty) {
+  const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+  // Annoyingly, K&R functions have prototypes in the clang AST, but
+  // expressions referring to them are unprototyped.
+  QualType FuncType = FD->getType();
+  if (!FD->hasPrototype())
+    if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
+      FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
+                                                Proto->getExtInfo());
+
+  return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType, GD);
+}
diff --git a/clang/lib/CodeGen/CGPointerAuthInfo.h 
b/clang/lib/CodeGen/CGPointerAuthInfo.h
new file mode 100644
index 0000000000000..e870c3145acba
--- /dev/null
+++ b/clang/lib/CodeGen/CGPointerAuthInfo.h
@@ -0,0 +1,96 @@
+//===----- CGPointerAuthInfo.h -  -------------------------------*- C++ 
-*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Pointer auth info class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H
+#define LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+
+namespace clang {
+namespace CodeGen {
+
+class CGPointerAuthInfo {
+private:
+  PointerAuthenticationMode AuthenticationMode : 2;
+  bool IsIsaPointer : 1;
+  bool AuthenticatesNullValues : 1;
+  unsigned Key : 28;
+  llvm::Value *Discriminator;
+
+public:
+  CGPointerAuthInfo()
+      : AuthenticationMode(PointerAuthenticationMode...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/93906
_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to