Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ca06985

Browse files
dominik-steenkendyung
authored andcommitted
[SystemZ] Enable -fpatchable-function-entry=M,N (#178191)
This PR enables the option `-fpatchable-function-entry` for SystemZ. It utilizes existing common code and just adds the emission of nops after the function label in the backend. SystemZ provides multiple nop options of varying length, making the semantics of this option somewhat ambiguous. In order to align with what `gcc` does with that same option, we#re choosing `nopr` as the canoonical nop for this purpose. For test, this adapts an existing test file from aarch64. (cherry picked from commit 355898a)
1 parent 0d37e79 commit ca06985

7 files changed

Lines changed: 136 additions & 5 deletions

File tree

clang/include/clang/Basic/Attr.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -967,9 +967,10 @@ def XRayLogArgs : InheritableAttr {
967967

968968
def PatchableFunctionEntry
969969
: InheritableAttr,
970-
TargetSpecificAttr<TargetArch<
971-
["aarch64", "aarch64_be", "loongarch32", "loongarch64", "riscv32",
972-
"riscv64", "x86", "x86_64", "ppc", "ppc64", "ppc64le"]>> {
970+
TargetSpecificAttr<
971+
TargetArch<["aarch64", "aarch64_be", "loongarch32", "loongarch64",
972+
"riscv32", "riscv64", "x86", "x86_64", "ppc", "ppc64",
973+
"ppc64le", "systemz"]>> {
973974
let Spellings = [GCC<"patchable_function_entry">];
974975
let Subjects = SubjectList<[Function, ObjCMethod]>;
975976
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>,

clang/include/clang/Basic/AttrDocs.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6749,7 +6749,7 @@ if omitted.``Section`` defaults to the ``-fpatchable-function-entry`` section n
67496749
set, or to ``__patchable_function_entries`` otherwise.
67506750

67516751
This attribute is only supported on
6752-
aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64/ppc64le targets.
6752+
aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64/ppc64le/s390x targets.
67536753
For ppc/ppc64 targets, AIX is still not supported.
67546754
}];
67556755
}

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6777,7 +6777,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
67776777
StringRef S0 = A->getValue(), S = S0;
67786778
unsigned Size, Offset = 0;
67796779
if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() &&
6780-
!Triple.isX86() &&
6780+
!Triple.isX86() && !Triple.isSystemZ() &&
67816781
!(!Triple.isOSAIX() && (Triple.getArch() == llvm::Triple::ppc ||
67826782
Triple.getArch() == llvm::Triple::ppc64 ||
67836783
Triple.getArch() == llvm::Triple::ppc64le)))

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,27 @@ void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
901901

902902
void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
903903
const MachineInstr &MI, SystemZMCInstLower &Lower) {
904+
905+
const MachineFunction &MF = *(MI.getParent()->getParent());
906+
const Function &F = MF.getFunction();
907+
908+
// If patchable-function-entry is set, emit in-function nops here.
909+
if (F.hasFnAttribute("patchable-function-entry")) {
910+
unsigned Num;
911+
// get M-N from function attribute (CodeGenFunction subtracts N
912+
// from M to yield the correct patchable-function-entry).
913+
if (F.getFnAttribute("patchable-function-entry")
914+
.getValueAsString()
915+
.getAsInteger(10, Num))
916+
return;
917+
// Emit M-N 2-byte nops. Use getNop() here instead of emitNops()
918+
// to keep it aligned with the common code implementation emitting
919+
// the prefix nops.
920+
for (unsigned I = 0; I < Num; ++I)
921+
EmitToStreamer(*OutStreamer, MF.getSubtarget().getInstrInfo()->getNop());
922+
return;
923+
}
924+
// Otherwise, emit xray sled.
904925
// .begin:
905926
// j .end # -> stmg %r2, %r15, 16(%r15)
906927
// nop

llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "llvm/CodeGen/TargetOpcodes.h"
3434
#include "llvm/CodeGen/TargetSubtargetInfo.h"
3535
#include "llvm/CodeGen/VirtRegMap.h"
36+
#include "llvm/MC/MCInstBuilder.h"
3637
#include "llvm/MC/MCInstrDesc.h"
3738
#include "llvm/MC/MCRegisterInfo.h"
3839
#include "llvm/Support/BranchProbability.h"
@@ -2378,3 +2379,7 @@ SystemZInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
23782379
{MO_ADA_DIRECT_FUNC_DESC, "systemz-ada-directfuncdesc"}};
23792380
return ArrayRef(TargetFlags);
23802381
}
2382+
2383+
MCInst SystemZInstrInfo::getNop() const {
2384+
return MCInstBuilder(SystemZ::NOPR).addReg(0);
2385+
}

llvm/lib/Target/SystemZ/SystemZInstrInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
391391

392392
ArrayRef<std::pair<unsigned, const char *>>
393393
getSerializableDirectMachineOperandTargetFlags() const override;
394+
395+
MCInst getNop() const override;
394396
};
395397

396398
} // end namespace llvm
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
; RUN: llc -mtriple=s390x-ibm-linux %s -o - | FileCheck %s
2+
; RUN: llc -mtriple=s390x-ibm-linux -function-sections %s -o - | FileCheck %s
3+
; RUN: llc -mtriple=s390x-ibm-linux -function-sections %s -o - | FileCheck %s
4+
; RUN: llc -mtriple=s390x-ibm-linux -no-integrated-as -binutils-version=2.35 %s -o - | FileCheck --check-prefix=NOLINK %s
5+
; RUN: llc -mtriple=s390x-ibm-linux -no-integrated-as -binutils-version=2.36 %s -o - | FileCheck %s
6+
7+
;; GNU ld < 2.36 did not support mixed SHF_LINK_ORDER and non-SHF_LINK_ORDER sections.
8+
; NOLINK-NOT: "awo"
9+
10+
define i32 @f0() "patchable-function-entry"="0" {
11+
; CHECK-LABEL: f0:
12+
; CHECK-NEXT: .Lfunc_begin0:
13+
; CHECK-NOT: nopr
14+
; CHECK: lhi %r2, 0
15+
; CHECK-NOT: .section __patchable_function_entries
16+
ret i32 0
17+
}
18+
19+
define i32 @f1() "patchable-function-entry"="1" {
20+
; CHECK-LABEL: f1:
21+
; CHECK-NEXT: .Lfunc_begin1:
22+
; CHECK: nopr
23+
; CHECK-NEXT: lhi %r2, 0
24+
; CHECK: .section __patchable_function_entries,"awo",@progbits,f1{{$}}
25+
; CHECK-NEXT: .p2align 3, 0x0
26+
; CHECK-NEXT: .quad .Lfunc_begin1
27+
ret i32 0
28+
}
29+
30+
;; Without -function-sections, f2 is in the same text section as f1.
31+
;; They share the __patchable_function_entries section.
32+
;; With -function-sections, f1 and f2 are in different text sections.
33+
;; Use separate __patchable_function_entries.
34+
define void @f2() "patchable-function-entry"="2" {
35+
; CHECK-LABEL: f2:
36+
; CHECK-NEXT: .Lfunc_begin2:
37+
; CHECK-COUNT-2: nopr
38+
; CHECK-NEXT: br %r14
39+
; CHECK: .section __patchable_function_entries,"awo",@progbits,f2{{$}}
40+
; CHECK-NEXT: .p2align 3, 0x0
41+
; CHECK-NEXT: .quad .Lfunc_begin2
42+
ret void
43+
}
44+
45+
$f3 = comdat any
46+
define void @f3() "patchable-function-entry"="3" comdat {
47+
; CHECK-LABEL: f3:
48+
; CHECK-NEXT: .Lfunc_begin3:
49+
; CHECK-COUNT-3: nopr
50+
; CHECK-NEXT: br %r14
51+
; CHECK: .section __patchable_function_entries,"awoG",@progbits,f3,f3,comdat{{$}}
52+
; CHECK-NEXT: .p2align 3, 0x0
53+
; CHECK-NEXT: .quad .Lfunc_begin3
54+
ret void
55+
}
56+
57+
$f5 = comdat any
58+
define void @f5() "patchable-function-entry"="5" comdat {
59+
; CHECK-LABEL: f5:
60+
; CHECK-NEXT: .Lfunc_begin4:
61+
; CHECK-COUNT-5: nopr
62+
; CHECK-NEXT: aghi %r15, -176
63+
; CHECK: .section __patchable_function_entries,"awoG",@progbits,f5,f5,comdat{{$}}
64+
; CHECK: .p2align 3, 0x0
65+
; CHECK-NEXT: .quad .Lfunc_begin4
66+
%frame = alloca i8, i32 16
67+
ret void
68+
}
69+
70+
;; -fpatchable-function-entry=3,2
71+
;; "patchable-function-prefix" emits data before the function entry label.
72+
define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
73+
; CHECK-LABEL: .type f3_2,@function
74+
; CHECK-NEXT: .Ltmp0:
75+
; CHECK-NEXT: nopr
76+
; CHECK-NEXT: nopr
77+
; CHECK-NEXT: f3_2: # @f3_2
78+
; CHECK: # %bb.0:
79+
; CHECK-NEXT: nopr
80+
; CHECK-NEXT: br %r14
81+
;; .size does not include the prefix.
82+
; CHECK: .Lfunc_end5:
83+
; CHECK-NEXT: .size f3_2, .Lfunc_end5-f3_2
84+
; CHECK: .section __patchable_function_entries,"awo",@progbits,f3_2{{$}}
85+
; CHECK: .p2align 3, 0x0
86+
; CHECK-NEXT: .quad .Ltmp0
87+
ret void
88+
}
89+
90+
;; When prefix data is used, arbitrarily place noprs after prefix data.
91+
define void @prefix() "patchable-function-entry"="0" "patchable-function-prefix"="1" prefix i32 1 {
92+
; CHECK-LABEL: .type prefix,@function
93+
; CHECK-NEXT: .long 1 # 0x1
94+
; CHECK: .Ltmp1:
95+
; CHECK: nopr
96+
; CHECK-NEXT: prefix: # @prefix
97+
;; Emit a __patchable_function_entries entry even if "patchable-function-entry" is 0.
98+
; CHECK: .section __patchable_function_entries,"awo",@progbits,prefix{{$}}
99+
; CHECK: .p2align 3, 0x0
100+
; CHECK-NEXT: .quad .Ltmp1
101+
ret void
102+
}

0 commit comments

Comments
 (0)