PatchableFunction.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. #include "llvm/CodeGen/Passes.h"
  15. #include "llvm/CodeGen/MachineFunction.h"
  16. #include "llvm/CodeGen/MachineFunctionPass.h"
  17. #include "llvm/CodeGen/MachineInstrBuilder.h"
  18. #include "llvm/Target/TargetFrameLowering.h"
  19. #include "llvm/Target/TargetInstrInfo.h"
  20. #include "llvm/Target/TargetSubtargetInfo.h"
  21. using namespace llvm;
  22. namespace {
  23. struct PatchableFunction : public MachineFunctionPass {
  24. static char ID; // Pass identification, replacement for typeid
  25. PatchableFunction() : MachineFunctionPass(ID) {
  26. initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
  27. }
  28. bool runOnMachineFunction(MachineFunction &F) override;
  29. MachineFunctionProperties getRequiredProperties() const override {
  30. return MachineFunctionProperties().set(
  31. MachineFunctionProperties::Property::AllVRegsAllocated);
  32. }
  33. };
  34. }
  35. /// Returns true if instruction \p MI will not result in actual machine code
  36. /// instructions.
  37. static bool doesNotGeneratecode(const MachineInstr &MI) {
  38. // TODO: Introduce an MCInstrDesc flag for this
  39. switch (MI.getOpcode()) {
  40. default: return false;
  41. case TargetOpcode::IMPLICIT_DEF:
  42. case TargetOpcode::KILL:
  43. case TargetOpcode::CFI_INSTRUCTION:
  44. case TargetOpcode::EH_LABEL:
  45. case TargetOpcode::GC_LABEL:
  46. case TargetOpcode::DBG_VALUE:
  47. return true;
  48. }
  49. }
  50. bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
  51. if (!MF.getFunction()->hasFnAttribute("patchable-function"))
  52. return false;
  53. #ifndef NDEBUG
  54. Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
  55. StringRef PatchType = PatchAttr.getValueAsString();
  56. assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
  57. #endif
  58. auto &FirstMBB = *MF.begin();
  59. MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
  60. for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
  61. assert(FirstActualI != FirstMBB.end());
  62. auto *TII = MF.getSubtarget().getInstrInfo();
  63. auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
  64. TII->get(TargetOpcode::PATCHABLE_OP))
  65. .addImm(2)
  66. .addImm(FirstActualI->getOpcode());
  67. for (auto &MO : FirstActualI->operands())
  68. MIB.addOperand(MO);
  69. FirstActualI->eraseFromParent();
  70. MF.ensureAlignment(4);
  71. return true;
  72. }
  73. char PatchableFunction::ID = 0;
  74. char &llvm::PatchableFunctionID = PatchableFunction::ID;
  75. INITIALIZE_PASS(PatchableFunction, "patchable-function",
  76. "Implement the 'patchable-function' attribute", false, false)