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/Passes.h" 163ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 173ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 183ca95b02SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 193ca95b02SDimitry Andric #include "llvm/Target/TargetFrameLowering.h" 203ca95b02SDimitry Andric #include "llvm/Target/TargetInstrInfo.h" 213ca95b02SDimitry Andric #include "llvm/Target/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 283ca95b02SDimitry Andric PatchableFunction() : MachineFunctionPass(ID) { 293ca95b02SDimitry Andric initializePatchableFunctionPass(*PassRegistry::getPassRegistry()); 303ca95b02SDimitry Andric } 313ca95b02SDimitry Andric 323ca95b02SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 333ca95b02SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 343ca95b02SDimitry Andric return MachineFunctionProperties().set( 353ca95b02SDimitry Andric MachineFunctionProperties::Property::AllVRegsAllocated); 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. 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: 523ca95b02SDimitry Andric return true; 533ca95b02SDimitry Andric } 543ca95b02SDimitry Andric } 553ca95b02SDimitry Andric 563ca95b02SDimitry Andric bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) { 573ca95b02SDimitry Andric if (!MF.getFunction()->hasFnAttribute("patchable-function")) 583ca95b02SDimitry Andric return false; 593ca95b02SDimitry Andric 603ca95b02SDimitry Andric #ifndef NDEBUG 613ca95b02SDimitry Andric Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function"); 623ca95b02SDimitry Andric StringRef PatchType = PatchAttr.getValueAsString(); 633ca95b02SDimitry Andric assert(PatchType == "prologue-short-redirect" && "Only possibility today!"); 643ca95b02SDimitry Andric #endif 653ca95b02SDimitry Andric 663ca95b02SDimitry Andric auto &FirstMBB = *MF.begin(); 673ca95b02SDimitry Andric MachineBasicBlock::iterator FirstActualI = FirstMBB.begin(); 683ca95b02SDimitry Andric for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI) 693ca95b02SDimitry Andric assert(FirstActualI != FirstMBB.end()); 703ca95b02SDimitry Andric 713ca95b02SDimitry Andric auto *TII = MF.getSubtarget().getInstrInfo(); 723ca95b02SDimitry Andric auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(), 733ca95b02SDimitry Andric TII->get(TargetOpcode::PATCHABLE_OP)) 743ca95b02SDimitry Andric .addImm(2) 753ca95b02SDimitry Andric .addImm(FirstActualI->getOpcode()); 763ca95b02SDimitry Andric 773ca95b02SDimitry Andric for (auto &MO : FirstActualI->operands()) 783ca95b02SDimitry Andric MIB.addOperand(MO); 793ca95b02SDimitry Andric 803ca95b02SDimitry Andric FirstActualI->eraseFromParent(); 813ca95b02SDimitry Andric MF.ensureAlignment(4); 823ca95b02SDimitry Andric return true; 833ca95b02SDimitry Andric } 843ca95b02SDimitry Andric 853ca95b02SDimitry Andric char PatchableFunction::ID = 0; 863ca95b02SDimitry Andric char &llvm::PatchableFunctionID = PatchableFunction::ID; 873ca95b02SDimitry Andric INITIALIZE_PASS(PatchableFunction, "patchable-function", 883ca95b02SDimitry Andric "Implement the 'patchable-function' attribute", false, false) 89