1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

[RISCV] Support clang -fpatchable-function-entry && GNU function attribute 'patchable_function_entry'

Similar to D72215 (AArch64) and D72220 (x86).

```
% clang -target riscv32 -march=rv64g -c -fpatchable-function-entry=2 a.c && llvm-objdump -dr a.o
...
0000000000000000 <main>:
       0: 13 00 00 00   nop
       4: 13 00 00 00   nop

% clang -target riscv32 -march=rv64gc -c -fpatchable-function-entry=2 a.c && llvm-objdump -dr a.o
...
00000002 <main>:
       2: 01 00         nop
       4: 01 00         nop
```

Recently the mainline kernel started to use -fpatchable-function-entry=8 for riscv (https://git.kernel.org/linus/afc76b8b80112189b6f11e67e19cf58301944814).

Differential Revision: https://reviews.llvm.org/D98610
This commit is contained in:
Fangrui Song 2021-03-16 10:02:35 -07:00
parent 59b63b74d5
commit 7a78fa03a9
6 changed files with 111 additions and 15 deletions

View File

@ -30,8 +30,8 @@ class MachineInstr;
class MachineOperand;
class PassRegistry;
void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
const AsmPrinter &AP);
bool lowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP);
bool LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
MCOperand &MCOp, const AsmPrinter &AP);

View File

@ -93,8 +93,8 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
return;
MCInst TmpInst;
LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
EmitToStreamer(*OutStreamer, TmpInst);
if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this))
EmitToStreamer(*OutStreamer, TmpInst);
}
bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

View File

@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
@ -49,6 +50,15 @@ RISCVInstrInfo::RISCVInstrInfo(RISCVSubtarget &STI)
: RISCVGenInstrInfo(RISCV::ADJCALLSTACKDOWN, RISCV::ADJCALLSTACKUP),
STI(STI) {}
MCInst RISCVInstrInfo::getNop() const {
if (STI.getFeatureBits()[RISCV::FeatureStdExtC])
return MCInstBuilder(RISCV::C_NOP);
return MCInstBuilder(RISCV::ADDI)
.addReg(RISCV::X0)
.addReg(RISCV::X0)
.addImm(0);
}
unsigned RISCVInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
switch (MI.getOpcode()) {

View File

@ -29,6 +29,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
public:
explicit RISCVInstrInfo(RISCVSubtarget &STI);
MCInst getNop() const override;
unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
unsigned isStoreToStackSlot(const MachineInstr &MI,

View File

@ -204,10 +204,10 @@ static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI,
return true;
}
void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
const AsmPrinter &AP) {
bool llvm::lowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP) {
if (lowerRISCVVMachineInstrToMCInst(MI, OutMI))
return;
return false;
OutMI.setOpcode(MI->getOpcode());
@ -217,19 +217,32 @@ void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
OutMI.addOperand(MCOp);
}
if (OutMI.getOpcode() == RISCV::PseudoReadVLENB) {
switch (OutMI.getOpcode()) {
case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
const Function &F = MI->getParent()->getParent()->getFunction();
if (F.hasFnAttribute("patchable-function-entry")) {
unsigned Num;
if (F.getFnAttribute("patchable-function-entry")
.getValueAsString()
.getAsInteger(10, Num))
return false;
AP.emitNops(Num);
return true;
}
break;
}
case RISCV::PseudoReadVLENB:
OutMI.setOpcode(RISCV::CSRRS);
OutMI.addOperand(MCOperand::createImm(
RISCVSysReg::lookupSysRegByName("VLENB")->Encoding));
OutMI.addOperand(MCOperand::createReg(RISCV::X0));
return;
}
if (OutMI.getOpcode() == RISCV::PseudoReadVL) {
break;
case RISCV::PseudoReadVL:
OutMI.setOpcode(RISCV::CSRRS);
OutMI.addOperand(MCOperand::createImm(
RISCVSysReg::lookupSysRegByName("VL")->Encoding));
OutMI.addOperand(
MCOperand::createImm(RISCVSysReg::lookupSysRegByName("VL")->Encoding));
OutMI.addOperand(MCOperand::createReg(RISCV::X0));
return;
break;
}
return false;
}

View File

@ -0,0 +1,71 @@
;; Test the function attribute "patchable-function-entry".
; RUN: llc -mtriple=riscv32 --riscv-no-aliases < %s | FileCheck %s --check-prefixes=CHECK,RV32,NORVC
; RUN: llc -mtriple=riscv64 --riscv-no-aliases < %s | FileCheck %s --check-prefixes=CHECK,RV64,NORVC
; RUN: llc -mtriple=riscv32 -mattr=+c --riscv-no-aliases < %s | FileCheck %s --check-prefixes=CHECK,RV32,RVC
; RUN: llc -mtriple=riscv64 -mattr=+c --riscv-no-aliases < %s | FileCheck %s --check-prefixes=CHECK,RV64,RVC
define void @f0() "patchable-function-entry"="0" {
; CHECK-LABEL: f0:
; CHECK-NEXT: .Lfunc_begin0:
; CHECK-NOT: {{addi|c.nop}}
; NORVC: jalr zero, 0(ra)
; RVC: c.jr ra
; CHECK-NOT: .section __patchable_function_entries
ret void
}
define void @f1() "patchable-function-entry"="1" {
; CHECK-LABEL: f1:
; CHECK-NEXT: .Lfunc_begin1:
; NORVC: addi zero, zero, 0
; NORVC-NEXT: jalr zero, 0(ra)
; RVC: c.nop
; RVC-NEXT: c.jr ra
; CHECK: .section __patchable_function_entries,"awo",@progbits,f1{{$}}
; 32: .p2align 2
; 32-NEXT: .word .Lfunc_begin1
; 64: .p2align 3
; 64-NEXT: .quad .Lfunc_begin1
ret void
}
$f5 = comdat any
define void @f5() "patchable-function-entry"="5" comdat {
; CHECK-LABEL: f5:
; CHECK-NEXT: .Lfunc_begin2:
; NORVC-COUNT-5: addi zero, zero, 0
; NORVC-NEXT: jalr zero, 0(ra)
; RVC-COUNT-5: c.nop
; RVC-NEXT: c.jr ra
; CHECK: .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5{{$}}
; RV32: .p2align 2
; RV32-NEXT: .word .Lfunc_begin2
; RV64: .p2align 3
; RV64-NEXT: .quad .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
; NORVC-COUNT-2: addi zero, zero, 0
; RVC-COUNT-2: c.nop
; CHECK-NEXT: f3_2:
; CHECK: # %bb.0:
; NORVC-NEXT: addi zero, zero, 0
; NORVC-NEXT: addi sp, sp, -16
; RVC-NEXT: c.nop
; RVC-NEXT: c.addi 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{{$}}
; RV32: .p2align 2
; RV32-NEXT: .word .Ltmp0
; RV64: .p2align 3
; RV64-NEXT: .quad .Ltmp0
%frame = alloca i8, i32 16
ret void
}