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 Andricstatic 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 Andricbool 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