Skip to content

Commit

Permalink
[PowerPC] Support -fpatchable-function-entry
Browse files Browse the repository at this point in the history
For now only PPC big endian Linux is supported.
PPC little endian Linux has XRAY support for 64-bit.
PPC AIX has different patchable function entry implementations.

Fixes llvm#63220
Fixes llvm#57031
  • Loading branch information
Chen Zheng committed May 22, 2024
1 parent 203232f commit 7bbd096
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 7 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ def PatchableFunctionEntry
: InheritableAttr,
TargetSpecificAttr<TargetArch<
["aarch64", "aarch64_be", "loongarch32", "loongarch64", "riscv32",
"riscv64", "x86", "x86_64"]>> {
"riscv64", "x86", "x86_64", "ppc", "ppc64"]>> {
let Spellings = [GCC<"patchable_function_entry">];
let Subjects = SubjectList<[Function, ObjCMethod]>;
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -5799,7 +5799,8 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M``
``M`` defaults to 0 if omitted.

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

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3470,7 +3470,7 @@ def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "

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

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

def err_tls_var_aligned_over_maximum : Error<
"alignment (%0) of thread-local variable %1 is greater than the maximum supported "
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6681,7 +6681,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StringRef S0 = A->getValue(), S = S0;
unsigned Size, Offset = 0;
if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() &&
!Triple.isX86())
!Triple.isX86() &&
!(!Triple.isOSAIX() && (Triple.getArch() == llvm::Triple::ppc ||
Triple.getArch() == llvm::Triple::ppc64)))
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
else if (S.consumeInteger(10, Size) ||
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5922,6 +5922,10 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
if (S.Context.getTargetInfo().getTriple().isOSAIX()) {
S.Diag(AL.getLoc(), diag::err_aix_attr_unsupported) << AL;
return;
}
uint32_t Count = 0, Offset = 0;
if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true))
return;
Expand Down
9 changes: 7 additions & 2 deletions clang/test/Driver/fpatchable-function-entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@
// RUN: %clang -target loongarch64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
// RUN: %clang -target riscv32 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
// 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
// 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
// 11: "-fpatchable-function-entry=1" "-fpatchable-function-entry-offset=1"
// RUN: %clang -target aarch64 -fsyntax-only %s -fpatchable-function-entry=2,1 -c -### 2>&1 | FileCheck --check-prefix=21 %s
// 21: "-fpatchable-function-entry=2" "-fpatchable-function-entry-offset=1"

// RUN: not %clang -target ppc64 -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=TARGET %s
// TARGET: error: unsupported option '-fpatchable-function-entry=1' for target 'ppc64'
// RUN: not %clang -target powerpc64-ibm-aix-xcoff -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=AIX64 %s
// AIX64: error: unsupported option '-fpatchable-function-entry=1' for target 'powerpc64-ibm-aix-xcoff'

// RUN: not %clang -target powerpc-ibm-aix-xcoff -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=AIX32 %s
// AIX32: error: unsupported option '-fpatchable-function-entry=1' for target 'powerpc-ibm-aix-xcoff'

// RUN: not %clang -target x86_64 -fsyntax-only %s -fpatchable-function-entry=1,0, 2>&1 | FileCheck --check-prefix=EXCESS %s
// EXCESS: error: invalid argument '1,0,' to -fpatchable-function-entry=
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Sema/patchable-function-entry-attr-aix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify %s

// expected-error@+1 {{'patchable_function_entry' attribute is not yet supported on AIX}}
__attribute__((patchable_function_entry(0))) void f();
2 changes: 2 additions & 0 deletions clang/test/Sema/patchable-function-entry-attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// RUN: %clang_cc1 -triple loongarch64 -fsyntax-only -verify=silence %s
// RUN: %clang_cc1 -triple riscv32 -fsyntax-only -verify=silence %s
// 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

// silence-no-diagnostics
Expand Down
24 changes: 23 additions & 1 deletion llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,24 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
// Lower multi-instruction pseudo operations.
switch (MI->getOpcode()) {
default: break;
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 = MI->getParent()->getParent()->getFunction();
if (F.hasFnAttribute("patchable-function-entry")) {
unsigned Num = 0;
if (F.getFnAttribute("patchable-function-entry")
.getValueAsString()
.getAsInteger(10, Num))
return;
emitNops(Num);
return;
}
}
case TargetOpcode::DBG_VALUE:
llvm_unreachable("Should be handled target independently");
case TargetOpcode::STACKMAP:
Expand Down Expand Up @@ -1781,7 +1799,7 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {

switch (MI->getOpcode()) {
default:
return PPCAsmPrinter::emitInstruction(MI);
break;
case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
// .begin:
// b .end # lis 0, FuncId[16..32]
Expand All @@ -1794,6 +1812,9 @@ 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())
break;
MCSymbol *BeginOfSled = OutContext.createTempSymbol();
MCSymbol *EndOfSled = OutContext.createTempSymbol();
OutStreamer->emitLabel(BeginOfSled);
Expand Down Expand Up @@ -1910,6 +1931,7 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
llvm_unreachable("Tail call is handled in the normal case. See comments "
"around this assert.");
}
return PPCAsmPrinter::emitInstruction(MI);
}

void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
Expand Down
49 changes: 49 additions & 0 deletions llvm/test/CodeGen/PowerPC/patchable-function-entry.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
; RUN: llc -mtriple=powerpc-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,PPC32
; RUN: llc -mtriple=powerpc64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,PPC64

define void @f0() {
; CHECK-LABEL: f0:
; CHECK-NOT: nop
; CHECK: # %bb.0:
; CHECK-NEXT: blr
; CHECK-NOT: .section __patchable_function_entries
ret void
}

define void @f1() "patchable-function-entry"="0" {
; CHECK-LABEL: f1:
; CHECK-NOT: nop
; CHECK: # %bb.0:
; CHECK-NEXT: blr
; CHECK-NOT: .section __patchable_function_entries
ret void
}

define void @f2() "patchable-function-entry"="1" {
; CHECK-LABEL: f2:
; CHECK-LABEL-NEXT: .Lfunc_begin2:
; CHECK: # %bb.0:
; CHECK-NEXT: nop
; CHECK-NEXT: blr
; CHECK: .section __patchable_function_entries
; PPC32: .p2align 2, 0x0
; PPC64: .p2align 3, 0x0
; PPC32-NEXT: .long .Lfunc_begin2
; PPC64-NEXT: .quad .Lfunc_begin2
ret void
}

define void @f3() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
; CHECK-LABEL: .Ltmp0:
; CHECK-COUNT-2: nop
; CHECK-LABEL: f3:
; CHECK: # %bb.0:
; CHECK-NEXT: nop
; CHECK-NEXT: blr
; CHECK: .section __patchable_function_entries
; PPC32: .p2align 2, 0x0
; PPC64: .p2align 3, 0x0
; PPC32-NEXT: .long .Ltmp0
; PPC64-NEXT: .quad .Ltmp0
ret void
}

0 comments on commit 7bbd096

Please sign in to comment.