1 //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements edits function bodies in place to support the
11 // "patchable-function" attribute.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/Target/TargetFrameLowering.h"
20 #include "llvm/Target/TargetInstrInfo.h"
21 #include "llvm/Target/TargetSubtargetInfo.h"
22 
23 using namespace llvm;
24 
25 namespace {
26 struct PatchableFunction : public MachineFunctionPass {
27   static char ID; // Pass identification, replacement for typeid
28   PatchableFunction() : MachineFunctionPass(ID) {
29     initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
30   }
31 
32   bool runOnMachineFunction(MachineFunction &F) override;
33    MachineFunctionProperties getRequiredProperties() const override {
34     return MachineFunctionProperties().set(
35         MachineFunctionProperties::Property::AllVRegsAllocated);
36   }
37 };
38 }
39 
40 bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
41   if (!MF.getFunction()->hasFnAttribute("patchable-function"))
42     return false;
43 
44 #ifndef NDEBUG
45   Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
46   StringRef PatchType = PatchAttr.getValueAsString();
47   assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
48 #endif
49 
50   auto &FirstMBB = *MF.begin();
51   auto &FirstMI = *FirstMBB.begin();
52 
53   auto *TII = MF.getSubtarget().getInstrInfo();
54   auto MIB = BuildMI(FirstMBB, FirstMBB.begin(), FirstMI.getDebugLoc(),
55                      TII->get(TargetOpcode::PATCHABLE_OP))
56                  .addImm(2)
57                  .addImm(FirstMI.getOpcode());
58 
59   for (auto &MO : FirstMI.operands())
60     MIB.addOperand(MO);
61 
62   FirstMI.eraseFromParent();
63   MF.ensureAlignment(4);
64   return true;
65 }
66 
67 char PatchableFunction::ID = 0;
68 char &llvm::PatchableFunctionID = PatchableFunction::ID;
69 INITIALIZE_PASS(PatchableFunction, "patchable-function",
70                 "Implement the 'patchable-function' attribute", false, false)
71