13ca95b02SDimitry Andric //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric //                     The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric //
103ca95b02SDimitry Andric // This file implements edits function bodies in place to support the
113ca95b02SDimitry Andric // "patchable-function" attribute.
123ca95b02SDimitry Andric //
133ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
143ca95b02SDimitry Andric 
153ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
163ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
173ca95b02SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
18db17bf38SDimitry Andric #include "llvm/CodeGen/Passes.h"
192cab237bSDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
202cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
212cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
223ca95b02SDimitry Andric 
233ca95b02SDimitry Andric using namespace llvm;
243ca95b02SDimitry Andric 
253ca95b02SDimitry Andric namespace {
263ca95b02SDimitry Andric struct PatchableFunction : public MachineFunctionPass {
273ca95b02SDimitry Andric   static char ID; // Pass identification, replacement for typeid
PatchableFunction__anon04ef29230111::PatchableFunction283ca95b02SDimitry Andric   PatchableFunction() : MachineFunctionPass(ID) {
293ca95b02SDimitry Andric     initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
303ca95b02SDimitry Andric   }
313ca95b02SDimitry Andric 
323ca95b02SDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
getRequiredProperties__anon04ef29230111::PatchableFunction333ca95b02SDimitry Andric    MachineFunctionProperties getRequiredProperties() const override {
343ca95b02SDimitry Andric     return MachineFunctionProperties().set(
35d88c1a5aSDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
363ca95b02SDimitry Andric   }
373ca95b02SDimitry Andric };
383ca95b02SDimitry Andric }
393ca95b02SDimitry Andric 
403ca95b02SDimitry Andric /// Returns true if instruction \p MI will not result in actual machine code
413ca95b02SDimitry Andric /// instructions.
doesNotGeneratecode(const MachineInstr & MI)423ca95b02SDimitry Andric static bool doesNotGeneratecode(const MachineInstr &MI) {
433ca95b02SDimitry Andric   // TODO: Introduce an MCInstrDesc flag for this
443ca95b02SDimitry Andric   switch (MI.getOpcode()) {
453ca95b02SDimitry Andric   default: return false;
463ca95b02SDimitry Andric   case TargetOpcode::IMPLICIT_DEF:
473ca95b02SDimitry Andric   case TargetOpcode::KILL:
483ca95b02SDimitry Andric   case TargetOpcode::CFI_INSTRUCTION:
493ca95b02SDimitry Andric   case TargetOpcode::EH_LABEL:
503ca95b02SDimitry Andric   case TargetOpcode::GC_LABEL:
513ca95b02SDimitry Andric   case TargetOpcode::DBG_VALUE:
52*4ba319b5SDimitry Andric   case TargetOpcode::DBG_LABEL:
533ca95b02SDimitry Andric     return true;
543ca95b02SDimitry Andric   }
553ca95b02SDimitry Andric }
563ca95b02SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)573ca95b02SDimitry Andric bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
582cab237bSDimitry Andric   if (!MF.getFunction().hasFnAttribute("patchable-function"))
593ca95b02SDimitry Andric     return false;
603ca95b02SDimitry Andric 
613ca95b02SDimitry Andric #ifndef NDEBUG
622cab237bSDimitry Andric   Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
633ca95b02SDimitry Andric   StringRef PatchType = PatchAttr.getValueAsString();
643ca95b02SDimitry Andric   assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
653ca95b02SDimitry Andric #endif
663ca95b02SDimitry Andric 
673ca95b02SDimitry Andric   auto &FirstMBB = *MF.begin();
683ca95b02SDimitry Andric   MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
693ca95b02SDimitry Andric   for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
703ca95b02SDimitry Andric     assert(FirstActualI != FirstMBB.end());
713ca95b02SDimitry Andric 
723ca95b02SDimitry Andric   auto *TII = MF.getSubtarget().getInstrInfo();
733ca95b02SDimitry Andric   auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
743ca95b02SDimitry Andric                      TII->get(TargetOpcode::PATCHABLE_OP))
753ca95b02SDimitry Andric                  .addImm(2)
763ca95b02SDimitry Andric                  .addImm(FirstActualI->getOpcode());
773ca95b02SDimitry Andric 
783ca95b02SDimitry Andric   for (auto &MO : FirstActualI->operands())
797a7e6055SDimitry Andric     MIB.add(MO);
803ca95b02SDimitry Andric 
813ca95b02SDimitry Andric   FirstActualI->eraseFromParent();
823ca95b02SDimitry Andric   MF.ensureAlignment(4);
833ca95b02SDimitry Andric   return true;
843ca95b02SDimitry Andric }
853ca95b02SDimitry Andric 
863ca95b02SDimitry Andric char PatchableFunction::ID = 0;
873ca95b02SDimitry Andric char &llvm::PatchableFunctionID = PatchableFunction::ID;
883ca95b02SDimitry Andric INITIALIZE_PASS(PatchableFunction, "patchable-function",
893ca95b02SDimitry Andric                 "Implement the 'patchable-function' attribute", false, false)
90