summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2016-04-19 05:24:47 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2016-04-19 05:24:47 +0000
commitc0441c29df6498257eca59d41d9ccaf6d5a9adf3 (patch)
tree50847e0c84b62a0efe0b8078f1ff6ca9b1c97d11 /llvm/lib/CodeGen
parent28d8d0465733b4363461c27cbf58721e1163d763 (diff)
downloadbcm5719-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.txt1
-rw-r--r--llvm/lib/CodeGen/CodeGen.cpp1
-rw-r--r--llvm/lib/CodeGen/Passes.cpp2
-rw-r--r--llvm/lib/CodeGen/PatchableFunction.cpp70
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)
OpenPOWER on IntegriCloud