Home | History | Annotate | Download | only in CodeGen
      1 //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements edits function bodies in place to support the
     11 // "patchable-function" attribute.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/CodeGen/Passes.h"
     16 #include "llvm/CodeGen/MachineFunction.h"
     17 #include "llvm/CodeGen/MachineFunctionPass.h"
     18 #include "llvm/CodeGen/MachineInstrBuilder.h"
     19 #include "llvm/Target/TargetFrameLowering.h"
     20 #include "llvm/Target/TargetInstrInfo.h"
     21 #include "llvm/Target/TargetSubtargetInfo.h"
     22 
     23 using namespace llvm;
     24 
     25 namespace {
     26 struct PatchableFunction : public MachineFunctionPass {
     27   static char ID; // Pass identification, replacement for typeid
     28   PatchableFunction() : MachineFunctionPass(ID) {
     29     initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
     30   }
     31 
     32   bool runOnMachineFunction(MachineFunction &F) override;
     33    MachineFunctionProperties getRequiredProperties() const override {
     34     return MachineFunctionProperties().set(
     35         MachineFunctionProperties::Property::AllVRegsAllocated);
     36   }
     37 };
     38 }
     39 
     40 /// Returns true if instruction \p MI will not result in actual machine code
     41 /// instructions.
     42 static bool doesNotGeneratecode(const MachineInstr &MI) {
     43   // TODO: Introduce an MCInstrDesc flag for this
     44   switch (MI.getOpcode()) {
     45   default: return false;
     46   case TargetOpcode::IMPLICIT_DEF:
     47   case TargetOpcode::KILL:
     48   case TargetOpcode::CFI_INSTRUCTION:
     49   case TargetOpcode::EH_LABEL:
     50   case TargetOpcode::GC_LABEL:
     51   case TargetOpcode::DBG_VALUE:
     52     return true;
     53   }
     54 }
     55 
     56 bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
     57   if (!MF.getFunction()->hasFnAttribute("patchable-function"))
     58     return false;
     59 
     60 #ifndef NDEBUG
     61   Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
     62   StringRef PatchType = PatchAttr.getValueAsString();
     63   assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
     64 #endif
     65 
     66   auto &FirstMBB = *MF.begin();
     67   MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
     68   for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
     69     assert(FirstActualI != FirstMBB.end());
     70 
     71   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());
     76 
     77   for (auto &MO : FirstActualI->operands())
     78     MIB.addOperand(MO);
     79 
     80   FirstActualI->eraseFromParent();
     81   MF.ensureAlignment(4);
     82   return true;
     83 }
     84 
     85 char PatchableFunction::ID = 0;
     86 char &llvm::PatchableFunctionID = PatchableFunction::ID;
     87 INITIALIZE_PASS(PatchableFunction, "patchable-function",
     88                 "Implement the 'patchable-function' attribute", false, false)
     89