mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 14:20:17 +00:00
[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
This commit is contained in:
parent
929ad8bc7c
commit
db5dfec9d4
@ -270,6 +270,9 @@ Windows Support
|
|||||||
LoongArch Support
|
LoongArch Support
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Patchable function entry (``-fpatchable-function-entry``) is now supported
|
||||||
|
on LoongArch.
|
||||||
|
|
||||||
RISC-V Support
|
RISC-V Support
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
- Added ``-mrvv-vector-bits=`` option to give an upper and lower bound on vector
|
- Added ``-mrvv-vector-bits=`` option to give an upper and lower bound on vector
|
||||||
|
@ -792,7 +792,8 @@ def XRayLogArgs : InheritableAttr {
|
|||||||
def PatchableFunctionEntry
|
def PatchableFunctionEntry
|
||||||
: InheritableAttr,
|
: InheritableAttr,
|
||||||
TargetSpecificAttr<TargetArch<
|
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 Spellings = [GCC<"patchable_function_entry">];
|
||||||
let Subjects = SubjectList<[Function, ObjCMethod]>;
|
let Subjects = SubjectList<[Function, ObjCMethod]>;
|
||||||
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];
|
let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];
|
||||||
|
@ -5328,7 +5328,7 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M``
|
|||||||
``M`` defaults to 0 if omitted.
|
``M`` defaults to 0 if omitted.
|
||||||
|
|
||||||
This attribute is only supported on
|
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.
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6277,7 +6277,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
|
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
|
||||||
StringRef S0 = A->getValue(), S = S0;
|
StringRef S0 = A->getValue(), S = S0;
|
||||||
unsigned Size, Offset = 0;
|
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)
|
D.Diag(diag::err_drv_unsupported_opt_for_target)
|
||||||
<< A->getAsString(Args) << TripleStr;
|
<< A->getAsString(Args) << TripleStr;
|
||||||
else if (S.consumeInteger(10, Size) ||
|
else if (S.consumeInteger(10, Size) ||
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// RUN: %clang -target x86_64 %s -fpatchable-function-entry=1 -c -### 2>&1 | FileCheck %s
|
// 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 -c -### 2>&1 | FileCheck %s
|
||||||
// RUN: %clang -target aarch64 %s -fpatchable-function-entry=1,0 -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 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 riscv64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s
|
||||||
// CHECK: "-fpatchable-function-entry=1"
|
// CHECK: "-fpatchable-function-entry=1"
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// RUN: %clang_cc1 -triple aarch64_be -fsyntax-only -verify=silence %s
|
// 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 i386 -fsyntax-only -verify=silence %s
|
||||||
// RUN: %clang_cc1 -triple x86_64 -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 riscv32 -fsyntax-only -verify=silence %s
|
||||||
// RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s
|
// RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s
|
||||||
// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s
|
||||||
|
@ -35,6 +35,12 @@ void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {
|
|||||||
if (emitPseudoExpansionLowering(*OutStreamer, MI))
|
if (emitPseudoExpansionLowering(*OutStreamer, MI))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
|
case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
|
||||||
|
LowerPATCHABLE_FUNCTION_ENTER(*MI);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MCInst TmpInst;
|
MCInst TmpInst;
|
||||||
if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
|
if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
|
||||||
EmitToStreamer(*OutStreamer, TmpInst);
|
EmitToStreamer(*OutStreamer, TmpInst);
|
||||||
@ -110,6 +116,22 @@ bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
|||||||
return false;
|
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) {
|
bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||||
AsmPrinter::runOnMachineFunction(MF);
|
AsmPrinter::runOnMachineFunction(MF);
|
||||||
return true;
|
return true;
|
||||||
|
@ -41,6 +41,8 @@ public:
|
|||||||
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
const char *ExtraCode, raw_ostream &OS) override;
|
const char *ExtraCode, raw_ostream &OS) override;
|
||||||
|
|
||||||
|
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
|
||||||
|
|
||||||
// tblgen'erated function.
|
// tblgen'erated function.
|
||||||
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
|
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
|
||||||
const MachineInstr *MI);
|
const MachineInstr *MI);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
|
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
|
||||||
#include "MCTargetDesc/LoongArchMatInt.h"
|
#include "MCTargetDesc/LoongArchMatInt.h"
|
||||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
|
#include "llvm/MC/MCInstBuilder.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -28,6 +29,13 @@ LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
|
|||||||
LoongArch::ADJCALLSTACKUP),
|
LoongArch::ADJCALLSTACKUP),
|
||||||
STI(STI) {}
|
STI(STI) {}
|
||||||
|
|
||||||
|
MCInst LoongArchInstrInfo::getNop() const {
|
||||||
|
return MCInstBuilder(LoongArch::ANDI)
|
||||||
|
.addReg(LoongArch::R0)
|
||||||
|
.addReg(LoongArch::R0)
|
||||||
|
.addImm(0);
|
||||||
|
}
|
||||||
|
|
||||||
void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator MBBI,
|
MachineBasicBlock::iterator MBBI,
|
||||||
const DebugLoc &DL, MCRegister DstReg,
|
const DebugLoc &DL, MCRegister DstReg,
|
||||||
|
@ -27,6 +27,8 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo {
|
|||||||
public:
|
public:
|
||||||
explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
|
explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
|
||||||
|
|
||||||
|
MCInst getNop() const override;
|
||||||
|
|
||||||
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
|
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
|
||||||
bool KillSrc) const override;
|
bool KillSrc) const override;
|
||||||
|
63
llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
Normal file
63
llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
Normal file
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user