[clang] db5dfec - [Clang][LoongArch] Implement patchable function entry
Weining Lu via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 15 18:34:19 PDT 2023
Author: WANG Xuerui
Date: 2023-03-16T09:33:58+08:00
New Revision: db5dfec9d4442c360e9712bbd71b3462cac427e9
URL: https://github.com/llvm/llvm-project/commit/db5dfec9d4442c360e9712bbd71b3462cac427e9
DIFF: https://github.com/llvm/llvm-project/commit/db5dfec9d4442c360e9712bbd71b3462cac427e9.diff
LOG: [Clang][LoongArch] Implement patchable function entry
Similar to D98610 for RISCV.
This is going to be required by the upcoming Linux/LoongArch
[[ https://git.kernel.org/linus/4733f09d88074 | support for dynamic ftrace ]].
Reviewed By: SixWeining, MaskRay
Differential Revision: https://reviews.llvm.org/D141785
Added:
llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/Driver/fpatchable-function-entry.c
clang/test/Sema/patchable-function-entry-attr.cpp
llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 09a3daee68872..1bcdfaec15fe0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -270,6 +270,9 @@ Windows Support
LoongArch Support
^^^^^^^^^^^^^^^^^
+- Patchable function entry (``-fpatchable-function-entry``) is now supported
+ on LoongArch.
+
RISC-V Support
^^^^^^^^^^^^^^
- Added ``-mrvv-vector-bits=`` option to give an upper and lower bound on vector
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 8858bb6bec850..89a62e83444a3 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -792,7 +792,8 @@ def XRayLogArgs : InheritableAttr {
def PatchableFunctionEntry
: InheritableAttr,
TargetSpecificAttr<TargetArch<
- ["aarch64", "aarch64_be", "riscv32", "riscv64", "x86", "x86_64"]>> {
+ ["aarch64", "aarch64_be", "loongarch32", "loongarch64", "riscv32",
+ "riscv64", "x86", "x86_64"]>> {
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 cbf28688a7408..e085e2735b208 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -5328,7 +5328,7 @@ 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/riscv32/riscv64/i386/x86-64 targets.
+aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64 targets.
}];
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 87862e028636f..2327086c91f1f 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6277,7 +6277,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
StringRef S0 = A->getValue(), S = S0;
unsigned Size, Offset = 0;
- if (!Triple.isAArch64() && !Triple.isRISCV() && !Triple.isX86())
+ if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() &&
+ !Triple.isX86())
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 da7370a4d87a7..4d0d609584c8d 100644
--- a/clang/test/Driver/fpatchable-function-entry.c
+++ b/clang/test/Driver/fpatchable-function-entry.c
@@ -2,6 +2,8 @@
// RUN: %clang -target x86_64 %s -fpatchable-function-entry=1 -c -### 2>&1 | FileCheck %s
// RUN: %clang -target aarch64 %s -fpatchable-function-entry=1 -c -### 2>&1 | FileCheck %s
// RUN: %clang -target aarch64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
+// RUN: %clang -target loongarch32 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
+// 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
// CHECK: "-fpatchable-function-entry=1"
diff --git a/clang/test/Sema/patchable-function-entry-attr.cpp b/clang/test/Sema/patchable-function-entry-attr.cpp
index 3dd0504987306..9134c851da588 100644
--- a/clang/test/Sema/patchable-function-entry-attr.cpp
+++ b/clang/test/Sema/patchable-function-entry-attr.cpp
@@ -2,6 +2,8 @@
// RUN: %clang_cc1 -triple aarch64_be -fsyntax-only -verify=silence %s
// RUN: %clang_cc1 -triple i386 -fsyntax-only -verify=silence %s
// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify=silence %s
+// RUN: %clang_cc1 -triple loongarch32 -fsyntax-only -verify=silence %s
+// 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 ppc64le -fsyntax-only -verify %s
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index 6d9cb5e174d9a..04fdd41d67730 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -35,6 +35,12 @@ void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {
if (emitPseudoExpansionLowering(*OutStreamer, MI))
return;
+ switch (MI->getOpcode()) {
+ case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
+ LowerPATCHABLE_FUNCTION_ENTER(*MI);
+ return;
+ }
+
MCInst TmpInst;
if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
EmitToStreamer(*OutStreamer, TmpInst);
@@ -110,6 +116,22 @@ bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
+void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
+ const MachineInstr &MI) {
+ const Function &F = MF->getFunction();
+ if (F.hasFnAttribute("patchable-function-entry")) {
+ unsigned Num;
+ if (F.getFnAttribute("patchable-function-entry")
+ .getValueAsString()
+ .getAsInteger(10, Num))
+ return;
+ emitNops(Num);
+ return;
+ }
+
+ // TODO: Emit sled here once we get support for XRay.
+}
+
bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
AsmPrinter::runOnMachineFunction(MF);
return true;
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
index 23e29354743e6..c8bf657f8de7c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -41,6 +41,8 @@ class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter {
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &OS) override;
+ void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
+
// tblgen'erated function.
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
const MachineInstr *MI);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index fbbb764b8be1b..3e19f3e2fe08e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -17,6 +17,7 @@
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "MCTargetDesc/LoongArchMatInt.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCInstBuilder.h"
using namespace llvm;
@@ -28,6 +29,13 @@ LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
LoongArch::ADJCALLSTACKUP),
STI(STI) {}
+MCInst LoongArchInstrInfo::getNop() const {
+ return MCInstBuilder(LoongArch::ANDI)
+ .addReg(LoongArch::R0)
+ .addReg(LoongArch::R0)
+ .addImm(0);
+}
+
void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DstReg,
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
index e2b80460fcaf5..cf83abf27a1e3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -27,6 +27,8 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo {
public:
explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
+ MCInst getNop() const override;
+
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
bool KillSrc) const override;
diff --git a/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll b/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
new file mode 100644
index 0000000000000..12d4bfb50a198
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
@@ -0,0 +1,63 @@
+;; Test the function attribute "patchable-function-entry".
+;; Adapted from the RISCV test case.
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @f0() "patchable-function-entry"="0" {
+; CHECK-LABEL: f0:
+; CHECK-NEXT: .Lfunc_begin0:
+; CHECK-NOT: nop
+; CHECK: ret
+; CHECK-NOT: .section __patchable_function_entries
+ ret void
+}
+
+define void @f1() "patchable-function-entry"="1" {
+; CHECK-LABEL: f1:
+; CHECK-NEXT: .Lfunc_begin1:
+; CHECK: nop
+; CHECK-NEXT: ret
+; CHECK: .section __patchable_function_entries,"awo", at progbits,f1{{$}}
+; LA32: .p2align 2
+; LA32-NEXT: .word .Lfunc_begin1
+; LA64: .p2align 3
+; LA64-NEXT: .dword .Lfunc_begin1
+ ret void
+}
+
+$f5 = comdat any
+define void @f5() "patchable-function-entry"="5" comdat {
+; CHECK-LABEL: f5:
+; CHECK-NEXT: .Lfunc_begin2:
+; CHECK-COUNT-5: nop
+; CHECK-NEXT: ret
+; CHECK: .section __patchable_function_entries,"aGwo", at progbits,f5,comdat,f5{{$}}
+; LA32: .p2align 2
+; LA32-NEXT: .word .Lfunc_begin2
+; LA64: .p2align 3
+; LA64-NEXT: .dword .Lfunc_begin2
+ ret void
+}
+
+;; -fpatchable-function-entry=3,2
+;; "patchable-function-prefix" emits data before the function entry label.
+define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
+; CHECK-LABEL: .type f3_2, at function
+; CHECK-NEXT: .Ltmp0: # @f3_2
+; CHECK-COUNT-2: nop
+; CHECK-NEXT: f3_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nop
+; LA32-NEXT: addi.w $sp, $sp, -16
+; LA64-NEXT: addi.d $sp, $sp, -16
+;; .size does not include the prefix.
+; CHECK: .Lfunc_end3:
+; CHECK-NEXT: .size f3_2, .Lfunc_end3-f3_2
+; CHECK: .section __patchable_function_entries,"awo", at progbits,f3_2{{$}}
+; LA32: .p2align 2
+; LA32-NEXT: .word .Ltmp0
+; LA64: .p2align 3
+; LA64-NEXT: .dword .Ltmp0
+ %frame = alloca i8, i32 16
+ ret void
+}
More information about the cfe-commits
mailing list