diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-04-19 05:24:47 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-04-19 05:24:47 +0000 |
commit | c0441c29df6498257eca59d41d9ccaf6d5a9adf3 (patch) | |
tree | 50847e0c84b62a0efe0b8078f1ff6ca9b1c97d11 /llvm/lib/CodeGen | |
parent | 28d8d0465733b4363461c27cbf58721e1163d763 (diff) | |
download | bcm5719-llvm-c0441c29df6498257eca59d41d9ccaf6d5a9adf3.tar.gz bcm5719-llvm-c0441c29df6498257eca59d41d9ccaf6d5a9adf3.zip |
Introduce a "patchable-function" function attribute
Summary:
The `"patchable-function"` attribute can be used by an LLVM client to
influence LLVM's code generation in ways that makes the generated code
easily patchable at runtime (for instance, to redirect control).
Right now only one patchability scheme is supported,
`"prologue-short-redirect"`, but this can be expanded in the future.
Reviewers: joker.eph, rnk, echristo, dberris
Subscribers: joker.eph, echristo, mcrosier, llvm-commits
Differential Revision: http://reviews.llvm.org/D19046
llvm-svn: 266715
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/CodeGen.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/Passes.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/PatchableFunction.cpp | 70 |
4 files changed, 74 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 596a2d9907e..cb646d5717f 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -76,6 +76,7 @@ add_llvm_library(LLVMCodeGen MachineSSAUpdater.cpp MachineTraceMetrics.cpp MachineVerifier.cpp + PatchableFunction.cpp MIRPrinter.cpp MIRPrintingPass.cpp OptimizePHIs.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 3c2dc85df59..2613f5e4eda 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -55,6 +55,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeMachineSchedulerPass(Registry); initializeMachineSinkingPass(Registry); initializeMachineVerifierPassPass(Registry); + initializePatchableFunctionPass(Registry); initializeOptimizePHIsPass(Registry); initializePEIPass(Registry); initializePHIEliminationPass(Registry); diff --git a/llvm/lib/CodeGen/Passes.cpp b/llvm/lib/CodeGen/Passes.cpp index fa5c58df0c0..94b42089060 100644 --- a/llvm/lib/CodeGen/Passes.cpp +++ b/llvm/lib/CodeGen/Passes.cpp @@ -602,6 +602,8 @@ void TargetPassConfig::addMachinePasses() { addPass(&StackMapLivenessID, false); addPass(&LiveDebugValuesID, false); + addPass(&PatchableFunctionID, false); + AddingMachinePasses = false; } diff --git a/llvm/lib/CodeGen/PatchableFunction.cpp b/llvm/lib/CodeGen/PatchableFunction.cpp new file mode 100644 index 00000000000..ca345dfaf2b --- /dev/null +++ b/llvm/lib/CodeGen/PatchableFunction.cpp @@ -0,0 +1,70 @@ +//===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements edits function bodies in place to support the +// "patchable-function" attribute. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +using namespace llvm; + +namespace { +struct PatchableFunction : public MachineFunctionPass { + static char ID; // Pass identification, replacement for typeid + PatchableFunction() : MachineFunctionPass(ID) { + initializePatchableFunctionPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &F) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } +}; +} + +bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) { + if (!MF.getFunction()->hasFnAttribute("patchable-function")) + return false; + +#ifndef NDEBUG + Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function"); + StringRef PatchType = PatchAttr.getValueAsString(); + assert(PatchType == "prologue-short-redirect" && "Only possibility today!"); +#endif + + auto &FirstMBB = *MF.begin(); + auto &FirstMI = *FirstMBB.begin(); + + auto *TII = MF.getSubtarget().getInstrInfo(); + auto MIB = BuildMI(FirstMBB, FirstMBB.begin(), FirstMI.getDebugLoc(), + TII->get(TargetOpcode::PATCHABLE_OP)) + .addImm(2) + .addImm(FirstMI.getOpcode()); + + for (auto &MO : FirstMI.operands()) + MIB.addOperand(MO); + + FirstMI.eraseFromParent(); + MF.ensureAlignment(4); + return true; +} + +char PatchableFunction::ID = 0; +char &llvm::PatchableFunctionID = PatchableFunction::ID; +INITIALIZE_PASS(PatchableFunction, "patchable-function", "", false, false) |