[clang] [llvm] [CodeGen][AArch64][FMV] PAC the stub_helper's frame on arm64e (PR #84704)

Jon Roelofs via cfe-commits cfe-commits at lists.llvm.org
Sun Mar 10 16:50:55 PDT 2024


https://github.com/jroelofs created https://github.com/llvm/llvm-project/pull/84704

... and apply default function attributes so that the resolver will also be PAC'd (once more `arm64e` patches land upstream).

>From b352a41e1788819afbb15a5b6d79cbf2968dc5dc Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sun, 10 Mar 2024 16:46:50 -0700
Subject: [PATCH] [CodeGen][AArch64][FMV] PAC the stub_helper's frame on arm64e

---
 clang/lib/CodeGen/CodeGenModule.cpp           | 18 ++++--
 .../test/CodeGen/attr-target-version-arm64e.c | 58 +++++++++++++++++++
 llvm/include/llvm/CodeGen/AsmPrinter.h        | 13 +++--
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  3 +-
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 45 ++++++++++++++
 llvm/test/CodeGen/AArch64/ifunc-asm.ll        | 21 +++++--
 6 files changed, 142 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/CodeGen/attr-target-version-arm64e.c

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 967319bdfc4571..dadc76d04c5f6b 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4365,13 +4365,16 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
   // For cpu_specific, don't create an ifunc yet because we don't know if the
   // cpu_dispatch will be emitted in this translation unit.
   if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
-    llvm::Type *ResolverType = llvm::FunctionType::get(
+    llvm::FunctionType *ResolverType = llvm::FunctionType::get(
         llvm::PointerType::get(DeclTy,
                                getTypes().getTargetAddressSpace(FD->getType())),
         false);
-    llvm::Constant *Resolver = GetOrCreateLLVMFunction(
-        MangledName + ".resolver", ResolverType, GlobalDecl{},
-        /*ForVTable=*/false);
+    llvm::Function *Resolver = cast<llvm::Function>(
+        CreateRuntimeFunction(ResolverType, MangledName + ".resolver")
+            .getCallee());
+    llvm::AttrBuilder Attrs(getLLVMContext());
+    addDefaultFunctionDefinitionAttributes(Attrs);
+    Resolver->addFnAttrs(Attrs);
     llvm::GlobalIFunc *GIF =
         llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
                                   "", Resolver, &getModule());
@@ -4381,8 +4384,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
     return GIF;
   }
 
-  llvm::Constant *Resolver = GetOrCreateLLVMFunction(
-      ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
+  llvm::Function *Resolver = cast<llvm::Function>(
+      CreateRuntimeFunction(DeclTy, ResolverName).getCallee());
+  llvm::AttrBuilder Attrs(getLLVMContext());
+  addDefaultFunctionDefinitionAttributes(Attrs);
+  Resolver->addFnAttrs(Attrs);
   assert(isa<llvm::GlobalValue>(Resolver) &&
          "Resolver should be created for the first time");
   SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
diff --git a/clang/test/CodeGen/attr-target-version-arm64e.c b/clang/test/CodeGen/attr-target-version-arm64e.c
new file mode 100644
index 00000000000000..2deff9a688daaa
--- /dev/null
+++ b/clang/test/CodeGen/attr-target-version-arm64e.c
@@ -0,0 +1,58 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs
+// RUN: %clang_cc1 -triple arm64e-apple-ios -target-feature +ls64 -target-feature +fullfp16 -S -emit-llvm -o - %s | FileCheck %s
+
+int __attribute__((target_version("sha1"))) fmv(void) { return 1; }
+int __attribute__((target_version("default"))) fmv(void) { return 0; }
+int foo() {
+  return fmv();
+}
+
+//.
+// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
+// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv
+// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
+//.
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv._Msha1
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 1
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@foo
+// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @fmv()
+// CHECK-NEXT:    ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT:  resolver_entry:
+// CHECK-NEXT:    call void @__init_cpu_features_resolver()
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 2048
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2048
+// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       resolver_return:
+// CHECK-NEXT:    ret ptr @fmv._Msha1
+// CHECK:       resolver_else:
+// CHECK-NEXT:    ret ptr @fmv.default
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv.default
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 0
+//
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+// CHECK: attributes #[[ATTR2]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a7fbf4aeb74494..3b7e9c282120f9 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -603,16 +603,21 @@ class AsmPrinter : public MachineFunctionPass {
     return nullptr;
   }
 
+  virtual const MCExpr *
+  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+    return Init;
+  }
+
   virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                       MCSymbol *LazyPointer) {
-    llvm_unreachable(
-        "Mach-O IFunc lowering is not yet supported on this target");
+    assert(false &&
+           "Mach-O IFunc lowering is not yet supported on this target");
   }
 
   virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
                                             MCSymbol *LazyPointer) {
-    llvm_unreachable(
-        "Mach-O IFunc lowering is not yet supported on this target");
+    assert(false &&
+           "Mach-O IFunc lowering is not yet supported on this target");
   }
 
   /// Emit N NOP instructions.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0efe7a0e733672..b70221cdec296b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2259,7 +2259,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
   emitAlignment(Align(DL.getPointerSize()));
   OutStreamer->emitLabel(LazyPointer);
   emitVisibility(LazyPointer, GI.getVisibility());
-  OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);
+  const MCSymbolRefExpr *Init = MCSymbolRefExpr::create(StubHelper, OutContext);
+  OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(Init), 8);
 
   OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
 
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4fa719ad67cf33..f191fe3259d270 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,8 @@ class AArch64AsmPrinter : public AsmPrinter {
     assert(STI);
     return STI;
   }
+  const MCExpr *
+  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) override;
   void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                               MCSymbol *LazyPointer) override;
   void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
@@ -1897,6 +1899,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
   EmitToStreamer(*OutStreamer, TmpInst);
 }
 
+const MCExpr *
+AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+  if (TM.getTargetTriple().isArm64e())
+    return AArch64AuthMCExpr::create(Init, /*Disc=*/0, AArch64PACKey::IA,
+                                     /*HasAddressDiversity=*/false, OutContext);
+
+  return Init;
+}
+
 void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                                MCSymbol *LazyPointer) {
   // _ifunc:
@@ -1980,6 +1991,9 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
   //   ldp	fp, lr, [sp], #16
   //   br	x16
 
+  if (TM.getTargetTriple().isArm64e())
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::PACIBSP), *STI);
+
   OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
                                    .addReg(AArch64::SP)
                                    .addReg(AArch64::FP)
@@ -2085,6 +2099,37 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
                                    .addImm(2),
                                *STI);
 
+  if (TM.getTargetTriple().isArm64e()) {
+    //   autibsp
+    //   eor x17, lr, lr, lsl #1
+    //   tbz x17, #62, Lgoodsig
+    //   brk #0xc741
+    // Lgoodsig:
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::AUTIBSP), *STI);
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::EORXrs)
+                                     .addReg(AArch64::X17)
+                                     .addReg(AArch64::LR)
+                                     .addReg(AArch64::LR)
+                                     .addImm(1),
+                                 *STI);
+
+    MCContext &Ctx = OutStreamer->getContext();
+    MCSymbol *GoodSigSym = Ctx.createTempSymbol();
+    const MCExpr *GoodSig = MCSymbolRefExpr::create(GoodSigSym, Ctx);
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::TBZX)
+                                     .addReg(AArch64::X17)
+                                     .addImm(62)
+                                     .addExpr(GoodSig),
+                                 *STI);
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::BRK).addImm(0xc471),
+                                 *STI);
+
+    OutStreamer->emitLabel(GoodSigSym);
+  }
+
   OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
                                                  ? AArch64::BRAAZ
                                                  : AArch64::BR)
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
index 57fc2f0c9d7f5c..6f0d6f633fd513 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -1,6 +1,8 @@
 ; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
-; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefix=MACHO
-; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefix=MACHO
+; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
+; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
 
 define internal ptr @the_resolver() {
 entry:
@@ -21,7 +23,8 @@ entry:
 ; MACHO:           .section __DATA,__data
 ; MACHO-NEXT:      .p2align 3, 0x0
 ; MACHO-NEXT:  _global_ifunc.lazy_pointer:
-; MACHO-NEXT:      .quad _global_ifunc.stub_helper
+; ARM64-NEXT:      .quad _global_ifunc.stub_helper{{$}}
+; PAUTH-NEXT:      .quad _global_ifunc.stub_helper at AUTH(ia,0)
 
 ; MACHO:           .section __TEXT,__text,regular,pure_instructions
 ; MACHO-NEXT:      .globl _global_ifunc
@@ -30,9 +33,11 @@ entry:
 ; MACHO-NEXT:      adrp    x16, _global_ifunc.lazy_pointer at GOTPAGE
 ; MACHO-NEXT:      ldr     x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
 ; MACHO-NEXT:      ldr     x16, [x16]
-; MACHO-NEXT:      br      x16
+; ARM64-NEXT:      br      x16
+; PAUTH-NEXT:      braaz   x16
 ; MACHO-NEXT:      .p2align        2
 ; MACHO-NEXT:  _global_ifunc.stub_helper:
+; PAUTH-NEXT:      pacibsp
 ; MACHO-NEXT:      stp     x29, x30, [sp, #-16]!
 ; MACHO-NEXT:      mov     x29, sp
 ; MACHO-NEXT:      stp     x1, x0, [sp, #-16]!
@@ -57,7 +62,13 @@ entry:
 ; MACHO-NEXT:      ldp     x3, x2, [sp], #16
 ; MACHO-NEXT:      ldp     x1, x0, [sp], #16
 ; MACHO-NEXT:      ldp     x29, x30, [sp], #16
-; MACHO-NEXT:      br      x16
+; PAUTH-NEXT:      autibsp
+; PAUTH-NEXT:      eor     x17, x30, x30, lsl #1
+; PAUTH-NEXT:      tbz     x17, #62, [[GOOD_SIG:Ltmp[0-9]+]]
+; PAUTH-NEXT:      brk     #0xc471
+; PAUTH-NEXT: [[GOOD_SIG]]:
+; ARM64-NEXT:      br      x16
+; PAUTH-NEXT:      braaz   x16
 
 
 @weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver



More information about the cfe-commits mailing list