blob: ca44b7a539823362d406f98be5457eb60830a6c1 [file] [log] [blame]
Sanjoy Dasc0441c22016-04-19 05:24:47 +00001//===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Sanjoy Dasc0441c22016-04-19 05:24:47 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements edits function bodies in place to support the
10// "patchable-function" attribute.
11//
12//===----------------------------------------------------------------------===//
13
Sanjoy Dasc0441c22016-04-19 05:24:47 +000014#include "llvm/CodeGen/MachineFunction.h"
15#include "llvm/CodeGen/MachineFunctionPass.h"
Charles Davise9c32c72016-08-08 21:20:15 +000016#include "llvm/CodeGen/MachineInstrBuilder.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000017#include "llvm/CodeGen/Passes.h"
David Blaikie1be62f02017-11-03 22:32:11 +000018#include "llvm/CodeGen/TargetFrameLowering.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000019#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000020#include "llvm/CodeGen/TargetSubtargetInfo.h"
Reid Kleckner05da2fe2019-11-13 13:15:01 -080021#include "llvm/InitializePasses.h"
Sanjoy Dasc0441c22016-04-19 05:24:47 +000022
23using namespace llvm;
24
25namespace {
26struct 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;
Charles Davise9c32c72016-08-08 21:20:15 +000033 MachineFunctionProperties getRequiredProperties() const override {
Sanjoy Dasc0441c22016-04-19 05:24:47 +000034 return MachineFunctionProperties().set(
Matthias Braun1eb47362016-08-25 01:27:13 +000035 MachineFunctionProperties::Property::NoVRegs);
Sanjoy Dasc0441c22016-04-19 05:24:47 +000036 }
37};
38}
39
Matthias Braun512424f2016-07-13 16:37:29 +000040/// Returns true if instruction \p MI will not result in actual machine code
41/// instructions.
42static bool doesNotGeneratecode(const MachineInstr &MI) {
43 // TODO: Introduce an MCInstrDesc flag for this
44 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:
Shiva Chencd070cd2018-05-09 02:41:08 +000052 case TargetOpcode::DBG_LABEL:
Matthias Braun512424f2016-07-13 16:37:29 +000053 return true;
54 }
55}
56
Sanjoy Dasc0441c22016-04-19 05:24:47 +000057bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
Fangrui Song4d1e23e2020-01-03 00:35:47 -080058 if (MF.getFunction().hasFnAttribute("patchable-function-entry")) {
59 MachineBasicBlock &FirstMBB = *MF.begin();
Fangrui Song4d1e23e2020-01-03 00:35:47 -080060 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
Fangrui Song5932f7b2020-02-01 13:28:19 -080061 // The initial .loc covers PATCHABLE_FUNCTION_ENTER.
62 BuildMI(FirstMBB, FirstMBB.begin(), DebugLoc(),
63 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
Fangrui Song4d1e23e2020-01-03 00:35:47 -080064 return true;
65 }
66
Matthias Braunf1caa282017-12-15 22:22:58 +000067 if (!MF.getFunction().hasFnAttribute("patchable-function"))
Sanjoy Dasc0441c22016-04-19 05:24:47 +000068 return false;
69
Charles Davise9c32c72016-08-08 21:20:15 +000070#ifndef NDEBUG
Matthias Braunf1caa282017-12-15 22:22:58 +000071 Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
Sanjoy Dasc0441c22016-04-19 05:24:47 +000072 StringRef PatchType = PatchAttr.getValueAsString();
Charles Davise9c32c72016-08-08 21:20:15 +000073 assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
74#endif
Sanjoy Dasc0441c22016-04-19 05:24:47 +000075
76 auto &FirstMBB = *MF.begin();
Matthias Braun512424f2016-07-13 16:37:29 +000077 MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
78 for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
79 assert(FirstActualI != FirstMBB.end());
Sanjoy Dasc0441c22016-04-19 05:24:47 +000080
Charles Davise9c32c72016-08-08 21:20:15 +000081 auto *TII = MF.getSubtarget().getInstrInfo();
82 auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
83 TII->get(TargetOpcode::PATCHABLE_OP))
84 .addImm(2)
85 .addImm(FirstActualI->getOpcode());
Sanjoy Dasc0441c22016-04-19 05:24:47 +000086
Charles Davise9c32c72016-08-08 21:20:15 +000087 for (auto &MO : FirstActualI->operands())
Diana Picus116bbab2017-01-13 09:58:52 +000088 MIB.add(MO);
Charles Davise9c32c72016-08-08 21:20:15 +000089
90 FirstActualI->eraseFromParent();
Guillaume Chatelet18f805a2019-09-27 12:54:21 +000091 MF.ensureAlignment(Align(16));
Sanjoy Dasc0441c22016-04-19 05:24:47 +000092 return true;
93}
94
95char PatchableFunction::ID = 0;
96char &llvm::PatchableFunctionID = PatchableFunction::ID;
Sanjoy Das4519ff72016-04-19 06:25:02 +000097INITIALIZE_PASS(PatchableFunction, "patchable-function",
98 "Implement the 'patchable-function' attribute", false, false)