[clang] [llvm] [CodeGen][AArch64][FMV] PAC the stub_helper's frame on arm64e (PR #84704)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Mar 10 16:51:25 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Jon Roelofs (jroelofs)
<details>
<summary>Changes</summary>
... and apply default function attributes so that the resolver will also be PAC'd (once more `arm64e` patches land upstream).
---
Full diff: https://github.com/llvm/llvm-project/pull/84704.diff
6 Files Affected:
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+12-6)
- (added) clang/test/CodeGen/attr-target-version-arm64e.c (+58)
- (modified) llvm/include/llvm/CodeGen/AsmPrinter.h (+9-4)
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+2-1)
- (modified) llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp (+45)
- (modified) llvm/test/CodeGen/AArch64/ifunc-asm.ll (+16-5)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/84704
More information about the cfe-commits
mailing list