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/Analysis.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/Target/TargetFrameLowering.h"
21 #include "llvm/Target/TargetInstrInfo.h"
22 #include "llvm/Target/TargetSubtargetInfo.h"
23 
24 using namespace llvm;
25 
26 namespace {
27 struct PatchableFunction : public MachineFunctionPass {
28   static char ID; // Pass identification, replacement for typeid
29   PatchableFunction() : MachineFunctionPass(ID) {
30     initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
31   }
32 
33   bool runOnMachineFunction(MachineFunction &F) override;
34    MachineFunctionProperties getRequiredProperties() const override {
35     return MachineFunctionProperties().set(
36         MachineFunctionProperties::Property::AllVRegsAllocated);
37   }
38 };
39 }
40 
41 bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
42   if (!MF.getFunction()->hasFnAttribute("patchable-function"))
43     return false;
44 
45 #ifndef NDEBUG
46   Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
47   StringRef PatchType = PatchAttr.getValueAsString();
48   assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
49 #endif
50 
51   auto &FirstMBB = *MF.begin();
52   auto &FirstMI = *FirstMBB.begin();
53 
54   auto *TII = MF.getSubtarget().getInstrInfo();
55   auto MIB = BuildMI(FirstMBB, FirstMBB.begin(), FirstMI.getDebugLoc(),
56                      TII->get(TargetOpcode::PATCHABLE_OP))
57                  .addImm(2)
58                  .addImm(FirstMI.getOpcode());
59 
60   for (auto &MO : FirstMI.operands())
61     MIB.addOperand(MO);
62 
63   FirstMI.eraseFromParent();
64   MF.ensureAlignment(4);
65   return true;
66 }
67 
68 char PatchableFunction::ID = 0;
69 char &llvm::PatchableFunctionID = PatchableFunction::ID;
70 INITIALIZE_PASS(PatchableFunction, "patchable-function",
71                 "Implement the 'patchable-function' attribute", false, false)
72