1303231Sdim//===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim// 9303231Sdim// This file implements edits function bodies in place to support the 10303231Sdim// "patchable-function" attribute. 11303231Sdim// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14303231Sdim#include "llvm/CodeGen/MachineFunction.h" 15303231Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 16303231Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 17321369Sdim#include "llvm/CodeGen/Passes.h" 18327952Sdim#include "llvm/CodeGen/TargetFrameLowering.h" 19327952Sdim#include "llvm/CodeGen/TargetInstrInfo.h" 20327952Sdim#include "llvm/CodeGen/TargetSubtargetInfo.h" 21360784Sdim#include "llvm/InitializePasses.h" 22303231Sdim 23303231Sdimusing namespace llvm; 24303231Sdim 25303231Sdimnamespace { 26303231Sdimstruct PatchableFunction : public MachineFunctionPass { 27303231Sdim static char ID; // Pass identification, replacement for typeid 28303231Sdim PatchableFunction() : MachineFunctionPass(ID) { 29303231Sdim initializePatchableFunctionPass(*PassRegistry::getPassRegistry()); 30303231Sdim } 31303231Sdim 32303231Sdim bool runOnMachineFunction(MachineFunction &F) override; 33303231Sdim MachineFunctionProperties getRequiredProperties() const override { 34303231Sdim return MachineFunctionProperties().set( 35314564Sdim MachineFunctionProperties::Property::NoVRegs); 36303231Sdim } 37303231Sdim}; 38303231Sdim} 39303231Sdim 40303231Sdim/// Returns true if instruction \p MI will not result in actual machine code 41303231Sdim/// instructions. 42303231Sdimstatic bool doesNotGeneratecode(const MachineInstr &MI) { 43303231Sdim // TODO: Introduce an MCInstrDesc flag for this 44303231Sdim switch (MI.getOpcode()) { 45303231Sdim default: return false; 46303231Sdim case TargetOpcode::IMPLICIT_DEF: 47303231Sdim case TargetOpcode::KILL: 48303231Sdim case TargetOpcode::CFI_INSTRUCTION: 49303231Sdim case TargetOpcode::EH_LABEL: 50303231Sdim case TargetOpcode::GC_LABEL: 51303231Sdim case TargetOpcode::DBG_VALUE: 52341825Sdim case TargetOpcode::DBG_LABEL: 53303231Sdim return true; 54303231Sdim } 55303231Sdim} 56303231Sdim 57303231Sdimbool PatchableFunction::runOnMachineFunction(MachineFunction &MF) { 58360784Sdim if (MF.getFunction().hasFnAttribute("patchable-function-entry")) { 59360784Sdim MachineBasicBlock &FirstMBB = *MF.begin(); 60360784Sdim const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 61360784Sdim if (FirstMBB.empty()) { 62360784Sdim BuildMI(&FirstMBB, DebugLoc(), 63360784Sdim TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER)); 64360784Sdim } else { 65360784Sdim MachineInstr &FirstMI = *FirstMBB.begin(); 66360784Sdim BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(), 67360784Sdim TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER)); 68360784Sdim } 69360784Sdim return true; 70360784Sdim } 71360784Sdim 72327952Sdim if (!MF.getFunction().hasFnAttribute("patchable-function")) 73303231Sdim return false; 74303231Sdim 75303231Sdim#ifndef NDEBUG 76327952Sdim Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function"); 77303231Sdim StringRef PatchType = PatchAttr.getValueAsString(); 78303231Sdim assert(PatchType == "prologue-short-redirect" && "Only possibility today!"); 79303231Sdim#endif 80303231Sdim 81303231Sdim auto &FirstMBB = *MF.begin(); 82303231Sdim MachineBasicBlock::iterator FirstActualI = FirstMBB.begin(); 83303231Sdim for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI) 84303231Sdim assert(FirstActualI != FirstMBB.end()); 85303231Sdim 86303231Sdim auto *TII = MF.getSubtarget().getInstrInfo(); 87303231Sdim auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(), 88303231Sdim TII->get(TargetOpcode::PATCHABLE_OP)) 89303231Sdim .addImm(2) 90303231Sdim .addImm(FirstActualI->getOpcode()); 91303231Sdim 92303231Sdim for (auto &MO : FirstActualI->operands()) 93321369Sdim MIB.add(MO); 94303231Sdim 95303231Sdim FirstActualI->eraseFromParent(); 96360784Sdim MF.ensureAlignment(Align(16)); 97303231Sdim return true; 98303231Sdim} 99303231Sdim 100303231Sdimchar PatchableFunction::ID = 0; 101303231Sdimchar &llvm::PatchableFunctionID = PatchableFunction::ID; 102303231SdimINITIALIZE_PASS(PatchableFunction, "patchable-function", 103303231Sdim "Implement the 'patchable-function' attribute", false, false) 104