From 30bbcebb5a3be58b55229f8eda80423813bcd623 Mon Sep 17 00:00:00 2001 From: Maryam Moghadas Date: Thu, 31 Jul 2025 17:54:42 +0000 Subject: [PATCH] [PowerPC] Support `-fpatchable-function-entry` on PPC64LE This patch enables `-fpatchable-function-entry` on PPC64 little-endian Linux. It is mutually exclusive with existing XRay instrumentation on this target. --- clang/include/clang/Basic/Attr.td | 2 +- clang/include/clang/Basic/AttrDocs.td | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 3 +- clang/test/Driver/fpatchable-function-entry.c | 1 + .../Sema/patchable-function-entry-attr.cpp | 2 +- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 12 +++-- .../PowerPC/patchable-function-entry.ll | 49 +++++++++++++++++++ 7 files changed, 62 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 224cb6a32af28..f495706030a0e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -954,7 +954,7 @@ def PatchableFunctionEntry : InheritableAttr, TargetSpecificAttr> { + "riscv64", "x86", "x86_64", "ppc", "ppc64", "ppc64le"]>> { let Spellings = [GCC<"patchable_function_entry">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>, diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 76747d2b11811..b1f664c99c2dd 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -6567,7 +6567,7 @@ if omitted.``Section`` defaults to the ``-fpatchable-function-entry`` section n set, or to ``__patchable_function_entries`` otherwise. This attribute is only supported on -aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64 targets. +aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64/ppc64le targets. For ppc/ppc64 targets, AIX is still not supported. }]; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4e1b1d9e33621..b008a0cc4a916 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6744,7 +6744,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() && !Triple.isX86() && !(!Triple.isOSAIX() && (Triple.getArch() == llvm::Triple::ppc || - Triple.getArch() == llvm::Triple::ppc64))) + Triple.getArch() == llvm::Triple::ppc64 || + Triple.getArch() == llvm::Triple::ppc64le))) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) << TripleStr; else if (S.consumeInteger(10, Size) || diff --git a/clang/test/Driver/fpatchable-function-entry.c b/clang/test/Driver/fpatchable-function-entry.c index 43be6c5a47e47..5248a7c008812 100644 --- a/clang/test/Driver/fpatchable-function-entry.c +++ b/clang/test/Driver/fpatchable-function-entry.c @@ -8,6 +8,7 @@ // RUN: %clang --target=riscv64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s // RUN: %clang --target=powerpc-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s // RUN: %clang --target=powerpc64-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s +// RUN: %clang --target=powerpc64le-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s // CHECK: "-fpatchable-function-entry=1" // RUN: %clang --target=aarch64 -fsyntax-only %s -fpatchable-function-entry=1,1 -c -### 2>&1 | FileCheck --check-prefix=11 %s diff --git a/clang/test/Sema/patchable-function-entry-attr.cpp b/clang/test/Sema/patchable-function-entry-attr.cpp index 7498e67de302d..97b9c26af1edb 100644 --- a/clang/test/Sema/patchable-function-entry-attr.cpp +++ b/clang/test/Sema/patchable-function-entry-attr.cpp @@ -8,7 +8,7 @@ // RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s // RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify=silence %s // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -fsyntax-only -verify=silence %s -// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify=silence %s // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify=AIX %s // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify=AIX %s diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index ce1d51a0de091..357d2bd6c17f0 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -920,10 +920,6 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { assert(!Subtarget->isAIXABI() && "AIX does not support patchable function entry!"); - // PATCHABLE_FUNCTION_ENTER on little endian is for XRAY support which is - // handled in PPCLinuxAsmPrinter. - if (MAI->isLittleEndian()) - return; const Function &F = MF->getFunction(); unsigned Num = 0; (void)F.getFnAttribute("patchable-function-entry") @@ -1789,7 +1785,13 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) { // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number // of instructions change. // XRAY is only supported on PPC Linux little endian. - if (!MAI->isLittleEndian()) + const Function &F = MF->getFunction(); + unsigned Num = 0; + (void)F.getFnAttribute("patchable-function-entry") + .getValueAsString() + .getAsInteger(10, Num); + + if (!MAI->isLittleEndian() || Num) break; MCSymbol *BeginOfSled = OutContext.createTempSymbol(); MCSymbol *EndOfSled = OutContext.createTempSymbol(); diff --git a/llvm/test/CodeGen/PowerPC/patchable-function-entry.ll b/llvm/test/CodeGen/PowerPC/patchable-function-entry.ll index 0c2d2829a6d4b..f5977543784f9 100644 --- a/llvm/test/CodeGen/PowerPC/patchable-function-entry.ll +++ b/llvm/test/CodeGen/PowerPC/patchable-function-entry.ll @@ -1,5 +1,6 @@ ; RUN: llc -mtriple=powerpc %s -o - | FileCheck %s --check-prefixes=CHECK,PPC32 ; RUN: llc -mtriple=powerpc64 %s -o - | FileCheck %s --check-prefixes=CHECK,PPC64 +; RUN: llc -mtriple=powerpc64le %s -o - | FileCheck %s --check-prefix=PPC64LE @a = global i32 0, align 4 @@ -9,6 +10,12 @@ define void @f0() { ; CHECK: # %bb.0: ; CHECK-NEXT: blr ; CHECK-NOT: .section __patchable_function_entries +; +; PPC64LE-LABEL: f0: +; PPC64LE-NOT: nop +; PPC64LE: # %bb.0: +; PPC64LE-NEXT: blr +; PPC64LE-NOT: .section __patchable_function_entries ret void } @@ -18,6 +25,22 @@ define void @f1() "patchable-function-entry"="0" { ; CHECK: # %bb.0: ; CHECK-NEXT: blr ; CHECK-NOT: .section __patchable_function_entries +; +; PPC64LE-LABEL: f1: +; PPC64LE: # %bb.0: +; PPC64LE-NEXT: .Ltmp0: +; PPC64LE-NEXT: b .Ltmp1 +; PPC64LE-NEXT: nop +; PPC64LE-NEXT: std 0, -8(1) +; PPC64LE-NEXT: mflr 0 +; PPC64LE-NEXT: bl __xray_FunctionEntry +; PPC64LE-NEXT: nop +; PPC64LE-NEXT: mtlr 0 +; PPC64LE-NEXT: .Ltmp1: +; PPC64LE-NEXT: blr +; PPC64LE-NOT: .section __patchable_function_entries +; PPC64LE: .section xray_instr_map +; PPC64LE: .section xray_fn_idx ret void } @@ -32,6 +55,17 @@ define void @f2() "patchable-function-entry"="1" { ; PPC64: .p2align 3, 0x0 ; PPC32-NEXT: .long .Lfunc_begin2 ; PPC64-NEXT: .quad .Lfunc_begin2 +; +; PPC64LE-LABEL: f2: +; PPC64LE-LABEL-NEXT: .Lfunc_begin2: +; PPC64LE: # %bb.0: +; PPC64LE-NEXT: nop +; PPC64LE-NEXT: blr +; PPC64LE: .section __patchable_function_entries +; PPC64LE: .p2align 3, 0x0 +; PPC64LE-NEXT: .quad .Lfunc_begin2 +; PPC64LE-NOT: .section xray_instr_map +; PPC64LE-NOT: .section xray_fn_idx ret void } @@ -52,6 +86,21 @@ define i32 @f3() "patchable-function-entry"="1" "patchable-function-prefix"="2" ; PPC64: .p2align 3, 0x0 ; PPC32-NEXT: .long .Ltmp0 ; PPC64-NEXT: .quad .Ltmp0 +; +; PC64LE-LABEL: .Ltmp3: +; PC64LE-COUNT-2: nop +; PC64LE-LABEL: f3: +; PC64LE: # %bb.0: +; PC64LE-NEXT: nop +; PC64LE: addis 3, 2, .LC0@toc@ha +; PC64LE-NEXT: ld 3, .LC0@toc@l(3) +; PC64LE-NEXT: lwz 3, 0(3) +; PC64LE: blr +; PC64LE: .section __patchable_function_entries +; PPC64LE: .p2align 3, 0x0 +; PPC64LE-NEXT: .quad .Ltmp3 +; PC64LE-NOT: .section xray_instr_map +; PC64LE-NOT: .section xray_fn_idx entry: %0 = load i32, ptr @a, align 4 ret i32 %0