Line data Source code
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/MachineFunction.h"
16 : #include "llvm/CodeGen/MachineFunctionPass.h"
17 : #include "llvm/CodeGen/MachineInstrBuilder.h"
18 : #include "llvm/CodeGen/Passes.h"
19 : #include "llvm/CodeGen/TargetFrameLowering.h"
20 : #include "llvm/CodeGen/TargetInstrInfo.h"
21 : #include "llvm/CodeGen/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 24656 : PatchableFunction() : MachineFunctionPass(ID) {
29 24656 : initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
30 24656 : }
31 :
32 : bool runOnMachineFunction(MachineFunction &F) override;
33 24489 : MachineFunctionProperties getRequiredProperties() const override {
34 24489 : return MachineFunctionProperties().set(
35 24489 : MachineFunctionProperties::Property::NoVRegs);
36 : }
37 : };
38 : }
39 :
40 : /// Returns true if instruction \p MI will not result in actual machine code
41 : /// instructions.
42 : static bool doesNotGeneratecode(const MachineInstr &MI) {
43 : // TODO: Introduce an MCInstrDesc flag for this
44 12 : switch (MI.getOpcode()) {
45 : default: return false;
46 : case TargetOpcode::IMPLICIT_DEF:
47 : case TargetOpcode::KILL:
48 : case TargetOpcode::CFI_INSTRUCTION:
49 : case TargetOpcode::EH_LABEL:
50 : case TargetOpcode::GC_LABEL:
51 : case TargetOpcode::DBG_VALUE:
52 : case TargetOpcode::DBG_LABEL:
53 : return true;
54 : }
55 : }
56 :
57 379341 : bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
58 379341 : if (!MF.getFunction().hasFnAttribute("patchable-function"))
59 : return false;
60 :
61 : #ifndef NDEBUG
62 : Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
63 : StringRef PatchType = PatchAttr.getValueAsString();
64 : assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
65 : #endif
66 :
67 : auto &FirstMBB = *MF.begin();
68 : MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
69 : for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
70 : assert(FirstActualI != FirstMBB.end());
71 :
72 10 : auto *TII = MF.getSubtarget().getInstrInfo();
73 : auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
74 20 : TII->get(TargetOpcode::PATCHABLE_OP))
75 : .addImm(2)
76 20 : .addImm(FirstActualI->getOpcode());
77 :
78 38 : for (auto &MO : FirstActualI->operands())
79 : MIB.add(MO);
80 :
81 10 : FirstActualI->eraseFromParent();
82 : MF.ensureAlignment(4);
83 : return true;
84 : }
85 :
86 : char PatchableFunction::ID = 0;
87 : char &llvm::PatchableFunctionID = PatchableFunction::ID;
88 109803 : INITIALIZE_PASS(PatchableFunction, "patchable-function",
89 : "Implement the 'patchable-function' attribute", false, false)
|