1 //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements edits function bodies in place to support the
10 // "patchable-function" attribute.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/MachineFunction.h"
15 #include "llvm/CodeGen/MachineFunctionPass.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/CodeGen/Passes.h"
18 #include "llvm/CodeGen/TargetFrameLowering.h"
19 #include "llvm/CodeGen/TargetInstrInfo.h"
20 #include "llvm/CodeGen/TargetSubtargetInfo.h"
25 struct PatchableFunction
: public MachineFunctionPass
{
26 static char ID
; // Pass identification, replacement for typeid
27 PatchableFunction() : MachineFunctionPass(ID
) {
28 initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
31 bool runOnMachineFunction(MachineFunction
&F
) override
;
32 MachineFunctionProperties
getRequiredProperties() const override
{
33 return MachineFunctionProperties().set(
34 MachineFunctionProperties::Property::NoVRegs
);
39 /// Returns true if instruction \p MI will not result in actual machine code
41 static bool doesNotGeneratecode(const MachineInstr
&MI
) {
42 // TODO: Introduce an MCInstrDesc flag for this
43 switch (MI
.getOpcode()) {
44 default: return false;
45 case TargetOpcode::IMPLICIT_DEF
:
46 case TargetOpcode::KILL
:
47 case TargetOpcode::CFI_INSTRUCTION
:
48 case TargetOpcode::EH_LABEL
:
49 case TargetOpcode::GC_LABEL
:
50 case TargetOpcode::DBG_VALUE
:
51 case TargetOpcode::DBG_LABEL
:
56 bool PatchableFunction::runOnMachineFunction(MachineFunction
&MF
) {
57 if (!MF
.getFunction().hasFnAttribute("patchable-function"))
61 Attribute PatchAttr
= MF
.getFunction().getFnAttribute("patchable-function");
62 StringRef PatchType
= PatchAttr
.getValueAsString();
63 assert(PatchType
== "prologue-short-redirect" && "Only possibility today!");
66 auto &FirstMBB
= *MF
.begin();
67 MachineBasicBlock::iterator FirstActualI
= FirstMBB
.begin();
68 for (; doesNotGeneratecode(*FirstActualI
); ++FirstActualI
)
69 assert(FirstActualI
!= FirstMBB
.end());
71 auto *TII
= MF
.getSubtarget().getInstrInfo();
72 auto MIB
= BuildMI(FirstMBB
, FirstActualI
, FirstActualI
->getDebugLoc(),
73 TII
->get(TargetOpcode::PATCHABLE_OP
))
75 .addImm(FirstActualI
->getOpcode());
77 for (auto &MO
: FirstActualI
->operands())
80 FirstActualI
->eraseFromParent();
81 MF
.ensureAlignment(Align(16));
85 char PatchableFunction::ID
= 0;
86 char &llvm::PatchableFunctionID
= PatchableFunction::ID
;
87 INITIALIZE_PASS(PatchableFunction
, "patchable-function",
88 "Implement the 'patchable-function' attribute", false, false)