10b57cec5SDimitry Andric //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements edits function bodies in place to support the
100b57cec5SDimitry Andric // "patchable-function" attribute.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
19480093f4SDimitry Andric #include "llvm/InitializePasses.h"
2081ad6265SDimitry Andric #include "llvm/Pass.h"
2181ad6265SDimitry Andric #include "llvm/PassRegistry.h"
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric namespace {
260b57cec5SDimitry Andric struct PatchableFunction : public MachineFunctionPass {
270b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid
PatchableFunction__anone11953700111::PatchableFunction280b57cec5SDimitry Andric PatchableFunction() : MachineFunctionPass(ID) {
290b57cec5SDimitry Andric initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override;
getRequiredProperties__anone11953700111::PatchableFunction330b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override {
340b57cec5SDimitry Andric return MachineFunctionProperties().set(
350b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs);
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric };
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)400b57cec5SDimitry Andric bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
41480093f4SDimitry Andric MachineBasicBlock &FirstMBB = *MF.begin();
42*7a6dacacSDimitry Andric
43*7a6dacacSDimitry Andric if (MF.getFunction().hasFnAttribute("patchable-function-entry")) {
44480093f4SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
455ffd83dbSDimitry Andric // The initial .loc covers PATCHABLE_FUNCTION_ENTER.
465ffd83dbSDimitry Andric BuildMI(FirstMBB, FirstMBB.begin(), DebugLoc(),
4755e4f9d5SDimitry Andric TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
48480093f4SDimitry Andric return true;
49*7a6dacacSDimitry Andric } else if (MF.getFunction().hasFnAttribute("patchable-function")) {
500b57cec5SDimitry Andric #ifndef NDEBUG
510b57cec5SDimitry Andric Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
520b57cec5SDimitry Andric StringRef PatchType = PatchAttr.getValueAsString();
530b57cec5SDimitry Andric assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
540b57cec5SDimitry Andric #endif
550b57cec5SDimitry Andric auto *TII = MF.getSubtarget().getInstrInfo();
56*7a6dacacSDimitry Andric BuildMI(FirstMBB, FirstMBB.begin(), DebugLoc(),
57*7a6dacacSDimitry Andric TII->get(TargetOpcode::PATCHABLE_OP))
58*7a6dacacSDimitry Andric .addImm(2);
59bdd1243dSDimitry Andric MF.ensureAlignment(Align(16));
60bdd1243dSDimitry Andric return true;
61bdd1243dSDimitry Andric }
62*7a6dacacSDimitry Andric return false;
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric char PatchableFunction::ID = 0;
660b57cec5SDimitry Andric char &llvm::PatchableFunctionID = PatchableFunction::ID;
670b57cec5SDimitry Andric INITIALIZE_PASS(PatchableFunction, "patchable-function",
680b57cec5SDimitry Andric "Implement the 'patchable-function' attribute", false, false)
69