blob: a8466396f9b8925e14850e8626b3f14a5c6d6354 [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 Song50a3ff32020-01-23 14:46:28 -080061 if (FirstMBB.empty()) {
62 BuildMI(&FirstMBB, DebugLoc(),
63 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
64 } else {
65 MachineInstr &FirstMI = *FirstMBB.begin();
66 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
67 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
68 }
Fangrui Song4d1e23e2020-01-03 00:35:47 -080069 return true;
70 }
71
Matthias Braunf1caa282017-12-15 22:22:58 +000072 if (!MF.getFunction().hasFnAttribute("patchable-function"))
Sanjoy Dasc0441c22016-04-19 05:24:47 +000073 return false;
74
Charles Davise9c32c72016-08-08 21:20:15 +000075#ifndef NDEBUG
Matthias Braunf1caa282017-12-15 22:22:58 +000076 Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
Sanjoy Dasc0441c22016-04-19 05:24:47 +000077 StringRef PatchType = PatchAttr.getValueAsString();
Charles Davise9c32c72016-08-08 21:20:15 +000078 assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
79#endif
Sanjoy Dasc0441c22016-04-19 05:24:47 +000080
81 auto &FirstMBB = *MF.begin();
Matthias Braun512424f2016-07-13 16:37:29 +000082 MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
83 for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
84 assert(FirstActualI != FirstMBB.end());
Sanjoy Dasc0441c22016-04-19 05:24:47 +000085
Charles Davise9c32c72016-08-08 21:20:15 +000086 auto *TII = MF.getSubtarget().getInstrInfo();
87 auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
88 TII->get(TargetOpcode::PATCHABLE_OP))
89 .addImm(2)
90 .addImm(FirstActualI->getOpcode());
Sanjoy Dasc0441c22016-04-19 05:24:47 +000091
Charles Davise9c32c72016-08-08 21:20:15 +000092 for (auto &MO : FirstActualI->operands())
Diana Picus116bbab2017-01-13 09:58:52 +000093 MIB.add(MO);
Charles Davise9c32c72016-08-08 21:20:15 +000094
95 FirstActualI->eraseFromParent();
Guillaume Chatelet18f805a2019-09-27 12:54:21 +000096 MF.ensureAlignment(Align(16));
Sanjoy Dasc0441c22016-04-19 05:24:47 +000097 return true;
98}
99
100char PatchableFunction::ID = 0;
101char &llvm::PatchableFunctionID = PatchableFunction::ID;
Sanjoy Das4519ff72016-04-19 06:25:02 +0000102INITIALIZE_PASS(PatchableFunction, "patchable-function",
103 "Implement the 'patchable-function' attribute", false, false)