xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/PatchableFunction.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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