diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -380,6 +380,9 @@ void emitPatchableFunctionEntries(); + /// Emit a simple NOP sled. + virtual void emitPatchableNOPSled(unsigned Num); + //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. //===------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1711,6 +1711,25 @@ case TargetOpcode::MEMBARRIER: OutStreamer->emitRawComment("MEMBARRIER"); break; + + // patchable-function-entry=N is a simple NOP sled. + case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { + const Function &F = MF->getFunction(); + if (F.hasFnAttribute("patchable-function-entry")) { + unsigned Num; + if (F.getFnAttribute("patchable-function-entry") + .getValueAsString() + .getAsInteger(10, Num)) { + // This is garbage, do nothing. + break; + } + emitPatchableNOPSled(Num); + } else { + emitInstruction(&MI); + } + break; + } + default: emitInstruction(&MI); if (CanDoExtraAnalysis) { @@ -4104,6 +4123,11 @@ } } +void AsmPrinter::emitPatchableNOPSled(unsigned Num) { + // For most architectures, we just emit a set number of NOPs. + emitNops(Num); +} + uint16_t AsmPrinter::getDwarfVersion() const { return OutStreamer->getContext().getDwarfVersion(); } diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -262,17 +262,6 @@ void AArch64AsmPrinter::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; - } - emitSled(MI, SledKind::FUNCTION_ENTER); } diff --git a/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp b/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp --- a/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp +++ b/llvm/lib/Target/RISCV/RISCVMCInstLower.cpp @@ -227,19 +227,6 @@ } 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( diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -158,6 +158,8 @@ bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override { return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags; } + + void emitPatchableNOPSled(unsigned Num) override; }; } // end namespace llvm diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1760,16 +1760,6 @@ NoAutoPaddingScope NoPadScope(*OutStreamer); - const Function &F = MF->getFunction(); - if (F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; - if (F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num)) - return; - emitX86Nops(*OutStreamer, Num, Subtarget); - return; - } // We want to emit the following pattern: // // .p2align 1, ... @@ -2759,3 +2749,7 @@ EmitAndCountInstruction(TmpInst); } + +void X86AsmPrinter::emitPatchableNOPSled(unsigned Num) { + emitX86Nops(*OutStreamer, Num, Subtarget); +} \ No newline at end of file diff --git a/llvm/test/CodeGen/ARM/patchable-function-entry.ll b/llvm/test/CodeGen/ARM/patchable-function-entry.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/patchable-function-entry.ll @@ -0,0 +1,25 @@ +; RUN: llc -mtriple=arm-linux-gnueabi -verify-machineinstrs < %s | FileCheck %s + +define void @f0() "patchable-function-entry"="0" { +; CHECK-LABEL: f0: +; CHECK-NOT: mov r0, r0 +; CHECK: mov pc, lr + ret void +} + +define void @f1() "patchable-function-entry"="1" { +; CHECK-LABEL: f1: +; CHECK: mov r0, r0 +; CHECK-NOT: mov r0, r0 +; CHECK: mov pc, lr + ret void +} + +define void @f2() "patchable-function-entry"="2" { +; CHECK-LABEL: f2: +; CHECK: mov r0, r0 +; CHECK: mov r0, r0 +; CHECK-NOT: mov r0, r0 +; CHECK: mov pc, lr + ret void +} diff --git a/llvm/test/CodeGen/Hexagon/patchable-function-entry.ll b/llvm/test/CodeGen/Hexagon/patchable-function-entry.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/patchable-function-entry.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s + +define void @f0() "patchable-function-entry"="0" { +; CHECK-LABEL: f0: +; CHECK-NOT: nop +; CHECK: jumpr r31 + ret void +} + +define void @f1() "patchable-function-entry"="1" { +; CHECK-LABEL: f1: +; CHECK: nop +; CHECK-NOT: nop +; CHECK: jumpr r31 + ret void +} + +define void @f2() "patchable-function-entry"="2" { +; CHECK-LABEL: f2: +; CHECK: nop +; CHECK: nop +; CHECK-NOT: nop +; CHECK: jumpr r31 + ret void +}