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",@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",@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,@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",@progbits,f3_2{{$}} +; LA32: .p2align 2 +; LA32-NEXT: .word .Ltmp0 +; LA64: .p2align 3 +; LA64-NEXT: .dword .Ltmp0 + %frame = alloca i8, i32 16 + ret void +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits