blob: 9d7605f078f97557bf7faab2e9a7bf81c6d219e1 [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"
Sanjoy Dasc0441c22016-04-19 05:24:47 +000021
22using namespace llvm;
23
24namespace {
25struct PatchableFunction : public MachineFunctionPass {
26 static char ID; // Pass identification, replacement for typeid
27 PatchableFunction() : MachineFunctionPass(ID) {
28 initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
29 }
30
31 bool runOnMachineFunction(MachineFunction &F) override;
Charles Davise9c32c72016-08-08 21:20:15 +000032 MachineFunctionProperties getRequiredProperties() const override {
Sanjoy Dasc0441c22016-04-19 05:24:47 +000033 return MachineFunctionProperties().set(
Matthias Braun1eb47362016-08-25 01:27:13 +000034 MachineFunctionProperties::Property::NoVRegs);
Sanjoy Dasc0441c22016-04-19 05:24:47 +000035 }
36};
37}
38
Matthias Braun512424f2016-07-13 16:37:29 +000039/// Returns true if instruction \p MI will not result in actual machine code
40/// instructions.
41static bool doesNotGeneratecode(const MachineInstr &MI) {
42 // TODO: Introduce an MCInstrDesc flag for this
43 switch (MI.getOpcode()) {
44 default: return false;
45 case TargetOpcode::IMPLICIT_DEF:
46 case TargetOpcode::KILL:
47 case TargetOpcode::CFI_INSTRUCTION:
48 case TargetOpcode::EH_LABEL:
49 case TargetOpcode::GC_LABEL:
50 case TargetOpcode::DBG_VALUE:
Shiva Chencd070cd2018-05-09 02:41:08 +000051 case TargetOpcode::DBG_LABEL:
Matthias Braun512424f2016-07-13 16:37:29 +000052 return true;
53 }
54}
55
Sanjoy Dasc0441c22016-04-19 05:24:47 +000056bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
Matthias Braunf1caa282017-12-15 22:22:58 +000057 if (!MF.getFunction().hasFnAttribute("patchable-function"))
Sanjoy Dasc0441c22016-04-19 05:24:47 +000058 return false;
59
Charles Davise9c32c72016-08-08 21:20:15 +000060#ifndef NDEBUG
Matthias Braunf1caa282017-12-15 22:22:58 +000061 Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
Sanjoy Dasc0441c22016-04-19 05:24:47 +000062 StringRef PatchType = PatchAttr.getValueAsString();
Charles Davise9c32c72016-08-08 21:20:15 +000063 assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
64#endif
Sanjoy Dasc0441c22016-04-19 05:24:47 +000065
66 auto &FirstMBB = *MF.begin();
Matthias Braun512424f2016-07-13 16:37:29 +000067 MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
68 for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
69 assert(FirstActualI != FirstMBB.end());
Sanjoy Dasc0441c22016-04-19 05:24:47 +000070
Charles Davise9c32c72016-08-08 21:20:15 +000071 auto *TII = MF.getSubtarget().getInstrInfo();
72 auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
73 TII->get(TargetOpcode::PATCHABLE_OP))
74 .addImm(2)
75 .addImm(FirstActualI->getOpcode());
Sanjoy Dasc0441c22016-04-19 05:24:47 +000076
Charles Davise9c32c72016-08-08 21:20:15 +000077 for (auto &MO : FirstActualI->operands())
Diana Picus116bbab2017-01-13 09:58:52 +000078 MIB.add(MO);
Charles Davise9c32c72016-08-08 21:20:15 +000079
80 FirstActualI->eraseFromParent();
Guillaume Chatelet48904e92019-09-11 11:16:48 +000081 MF.ensureAlignment(llvm::Align(16));
Sanjoy Dasc0441c22016-04-19 05:24:47 +000082 return true;
83}
84
85char PatchableFunction::ID = 0;
86char &llvm::PatchableFunctionID = PatchableFunction::ID;
Sanjoy Das4519ff72016-04-19 06:25:02 +000087INITIALIZE_PASS(PatchableFunction, "patchable-function",
88 "Implement the 'patchable-function' attribute", false, false)