Skip to content

Commit 1532e07

Browse files
Chen Zhengyuxuanchen1997
Chen Zheng
authored andcommitted
[PowerPC] Support -fpatchable-function-entry (#92997)
For now only PPC big endian Linux 32 and 64 bit are supported. PPC little endian Linux has XRAY support for 64-bit. PPC AIX has different patchable function entry implementations. Fixes #63220 Fixes #57031
1 parent 54829eb commit 1532e07

File tree

9 files changed

+103
-7
lines changed

9 files changed

+103
-7
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ def PatchableFunctionEntry
902902
: InheritableAttr,
903903
TargetSpecificAttr<TargetArch<
904904
["aarch64", "aarch64_be", "loongarch32", "loongarch64", "riscv32",
905-
"riscv64", "x86", "x86_64"]>> {
905+
"riscv64", "x86", "x86_64", "ppc", "ppc64"]>> {
906906
let Spellings = [GCC<"patchable_function_entry">];
907907
let Subjects = SubjectList<[Function, ObjCMethod]>;
908908
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5800,7 +5800,8 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M``
58005800
``M`` defaults to 0 if omitted.
58015801

58025802
This attribute is only supported on
5803-
aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64 targets.
5803+
aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64 targets.
5804+
For ppc/ppc64 targets, AIX is still not supported.
58045805
}];
58055806
}
58065807

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3492,7 +3492,7 @@ def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
34923492

34933493
def err_attr_codemodel_arg : Error<"code model '%0' is not supported on this target">;
34943494

3495-
def err_aix_attr_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">;
3495+
def err_aix_attr_unsupported : Error<"%0 attribute is not yet supported on AIX">;
34963496

34973497
def err_tls_var_aligned_over_maximum : Error<
34983498
"alignment (%0) of thread-local variable %1 is greater than the maximum supported "

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6666,7 +6666,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
66666666
StringRef S0 = A->getValue(), S = S0;
66676667
unsigned Size, Offset = 0;
66686668
if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() &&
6669-
!Triple.isX86())
6669+
!Triple.isX86() &&
6670+
!(!Triple.isOSAIX() && (Triple.getArch() == llvm::Triple::ppc ||
6671+
Triple.getArch() == llvm::Triple::ppc64)))
66706672
D.Diag(diag::err_drv_unsupported_opt_for_target)
66716673
<< A->getAsString(Args) << TripleStr;
66726674
else if (S.consumeInteger(10, Size) ||

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5247,6 +5247,10 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
52475247

52485248
static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
52495249
const ParsedAttr &AL) {
5250+
if (S.Context.getTargetInfo().getTriple().isOSAIX()) {
5251+
S.Diag(AL.getLoc(), diag::err_aix_attr_unsupported) << AL;
5252+
return;
5253+
}
52505254
uint32_t Count = 0, Offset = 0;
52515255
if (!S.checkUInt32Argument(AL, AL.getArgAsExpr(0), Count, 0, true))
52525256
return;

clang/test/Driver/fpatchable-function-entry.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@
66
// RUN: %clang --target=loongarch64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
77
// RUN: %clang --target=riscv32 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
88
// RUN: %clang --target=riscv64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
9+
// RUN: %clang --target=powerpc-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
10+
// RUN: %clang --target=powerpc64-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
911
// CHECK: "-fpatchable-function-entry=1"
1012

1113
// RUN: %clang --target=aarch64 -fsyntax-only %s -fpatchable-function-entry=1,1 -c -### 2>&1 | FileCheck --check-prefix=11 %s
1214
// 11: "-fpatchable-function-entry=1" "-fpatchable-function-entry-offset=1"
1315
// RUN: %clang --target=aarch64 -fsyntax-only %s -fpatchable-function-entry=2,1 -c -### 2>&1 | FileCheck --check-prefix=21 %s
1416
// 21: "-fpatchable-function-entry=2" "-fpatchable-function-entry-offset=1"
1517

16-
// RUN: not %clang --target=ppc64 -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=TARGET %s
17-
// TARGET: error: unsupported option '-fpatchable-function-entry=1' for target 'ppc64'
18+
// RUN: not %clang --target=powerpc64-ibm-aix-xcoff -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=AIX64 %s
19+
// AIX64: error: unsupported option '-fpatchable-function-entry=1' for target 'powerpc64-ibm-aix-xcoff'
20+
21+
// RUN: not %clang --target=powerpc-ibm-aix-xcoff -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=AIX32 %s
22+
// AIX32: error: unsupported option '-fpatchable-function-entry=1' for target 'powerpc-ibm-aix-xcoff'
1823

1924
// RUN: not %clang --target=x86_64 -fsyntax-only %s -fpatchable-function-entry=1,0, 2>&1 | FileCheck --check-prefix=EXCESS %s
2025
// EXCESS: error: invalid argument '1,0,' to -fpatchable-function-entry=

clang/test/Sema/patchable-function-entry-attr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
// RUN: %clang_cc1 -triple loongarch64 -fsyntax-only -verify=silence %s
77
// RUN: %clang_cc1 -triple riscv32 -fsyntax-only -verify=silence %s
88
// RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s
9+
// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify=silence %s
10+
// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -fsyntax-only -verify=silence %s
911
// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s
12+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify=AIX %s
13+
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify=AIX %s
1014

1115
// silence-no-diagnostics
1216

17+
// AIX-error@+2 {{'patchable_function_entry' attribute is not yet supported on AIX}}
1318
// expected-warning@+1 {{unknown attribute 'patchable_function_entry' ignored}}
1419
[[gnu::patchable_function_entry(0)]] void f();

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,23 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
909909
// Lower multi-instruction pseudo operations.
910910
switch (MI->getOpcode()) {
911911
default: break;
912+
case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
913+
assert(!Subtarget->isAIXABI() &&
914+
"AIX does not support patchable function entry!");
915+
// PATCHABLE_FUNCTION_ENTER on little endian is for XRAY support which is
916+
// handled in PPCLinuxAsmPrinter.
917+
if (MAI->isLittleEndian())
918+
return;
919+
const Function &F = MF->getFunction();
920+
unsigned Num = 0;
921+
(void)F.getFnAttribute("patchable-function-entry")
922+
.getValueAsString()
923+
.getAsInteger(10, Num);
924+
if (!Num)
925+
return;
926+
emitNops(Num);
927+
return;
928+
}
912929
case TargetOpcode::DBG_VALUE:
913930
llvm_unreachable("Should be handled target independently");
914931
case TargetOpcode::STACKMAP:
@@ -1780,7 +1797,7 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
17801797

17811798
switch (MI->getOpcode()) {
17821799
default:
1783-
return PPCAsmPrinter::emitInstruction(MI);
1800+
break;
17841801
case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
17851802
// .begin:
17861803
// b .end # lis 0, FuncId[16..32]
@@ -1793,6 +1810,9 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
17931810
//
17941811
// Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
17951812
// of instructions change.
1813+
// XRAY is only supported on PPC Linux little endian.
1814+
if (!MAI->isLittleEndian())
1815+
break;
17961816
MCSymbol *BeginOfSled = OutContext.createTempSymbol();
17971817
MCSymbol *EndOfSled = OutContext.createTempSymbol();
17981818
OutStreamer->emitLabel(BeginOfSled);
@@ -1909,6 +1929,7 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
19091929
llvm_unreachable("Tail call is handled in the normal case. See comments "
19101930
"around this assert.");
19111931
}
1932+
return PPCAsmPrinter::emitInstruction(MI);
19121933
}
19131934

19141935
void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; RUN: llc -mtriple=powerpc %s -o - | FileCheck %s --check-prefixes=CHECK,PPC32
2+
; RUN: llc -mtriple=powerpc64 %s -o - | FileCheck %s --check-prefixes=CHECK,PPC64
3+
4+
@a = global i32 0, align 4
5+
6+
define void @f0() {
7+
; CHECK-LABEL: f0:
8+
; CHECK-NOT: nop
9+
; CHECK: # %bb.0:
10+
; CHECK-NEXT: blr
11+
; CHECK-NOT: .section __patchable_function_entries
12+
ret void
13+
}
14+
15+
define void @f1() "patchable-function-entry"="0" {
16+
; CHECK-LABEL: f1:
17+
; CHECK-NOT: nop
18+
; CHECK: # %bb.0:
19+
; CHECK-NEXT: blr
20+
; CHECK-NOT: .section __patchable_function_entries
21+
ret void
22+
}
23+
24+
define void @f2() "patchable-function-entry"="1" {
25+
; CHECK-LABEL: f2:
26+
; CHECK-LABEL-NEXT: .Lfunc_begin2:
27+
; CHECK: # %bb.0:
28+
; CHECK-NEXT: nop
29+
; CHECK-NEXT: blr
30+
; CHECK: .section __patchable_function_entries
31+
; PPC32: .p2align 2, 0x0
32+
; PPC64: .p2align 3, 0x0
33+
; PPC32-NEXT: .long .Lfunc_begin2
34+
; PPC64-NEXT: .quad .Lfunc_begin2
35+
ret void
36+
}
37+
38+
define i32 @f3() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
39+
; CHECK-LABEL: .Ltmp0:
40+
; CHECK-COUNT-2: nop
41+
; CHECK-LABEL: f3:
42+
; CHECK: # %bb.0:
43+
; CHECK-NEXT: nop
44+
; PPC32: lis 3, a@ha
45+
; PPC32-NEXT: lwz 3, a@l(3)
46+
; PPC64: addis 3, 2, .LC0@toc@ha
47+
; PPC64-NEXT: ld 3, .LC0@toc@l(3)
48+
; PPC64-NEXT: lwz 3, 0(3)
49+
; CHECK: blr
50+
; CHECK: .section __patchable_function_entries
51+
; PPC32: .p2align 2, 0x0
52+
; PPC64: .p2align 3, 0x0
53+
; PPC32-NEXT: .long .Ltmp0
54+
; PPC64-NEXT: .quad .Ltmp0
55+
entry:
56+
%0 = load i32, ptr @a, align 4
57+
ret i32 %0
58+
}

0 commit comments

Comments
 (0)