PatchableFunction.cpp 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //===-- PatchableFunction.cpp - Patchable prologues for LLVM -------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements edits function bodies in place to support the
  10. // "patchable-function" attribute.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/CodeGen/MachineFunction.h"
  14. #include "llvm/CodeGen/MachineFunctionPass.h"
  15. #include "llvm/CodeGen/MachineInstrBuilder.h"
  16. #include "llvm/CodeGen/Passes.h"
  17. #include "llvm/CodeGen/TargetFrameLowering.h"
  18. #include "llvm/CodeGen/TargetInstrInfo.h"
  19. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  20. #include "llvm/InitializePasses.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::NoVRegs);
  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. case TargetOpcode::DBG_LABEL:
  48. return true;
  49. }
  50. }
  51. bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
  52. if (MF.getFunction().hasFnAttribute("patchable-function-entry")) {
  53. MachineBasicBlock &FirstMBB = *MF.begin();
  54. const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
  55. // The initial .loc covers PATCHABLE_FUNCTION_ENTER.
  56. BuildMI(FirstMBB, FirstMBB.begin(), DebugLoc(),
  57. TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
  58. return true;
  59. }
  60. if (!MF.getFunction().hasFnAttribute("patchable-function"))
  61. return false;
  62. #ifndef NDEBUG
  63. Attribute PatchAttr = MF.getFunction().getFnAttribute("patchable-function");
  64. StringRef PatchType = PatchAttr.getValueAsString();
  65. assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
  66. #endif
  67. auto &FirstMBB = *MF.begin();
  68. MachineBasicBlock::iterator FirstActualI = FirstMBB.begin();
  69. for (; doesNotGeneratecode(*FirstActualI); ++FirstActualI)
  70. assert(FirstActualI != FirstMBB.end());
  71. auto *TII = MF.getSubtarget().getInstrInfo();
  72. auto MIB = BuildMI(FirstMBB, FirstActualI, FirstActualI->getDebugLoc(),
  73. TII->get(TargetOpcode::PATCHABLE_OP))
  74. .addImm(2)
  75. .addImm(FirstActualI->getOpcode());
  76. for (auto &MO : FirstActualI->operands())
  77. MIB.add(MO);
  78. FirstActualI->eraseFromParent();
  79. MF.ensureAlignment(Align(16));
  80. return true;
  81. }
  82. char PatchableFunction::ID = 0;
  83. char &llvm::PatchableFunctionID = PatchableFunction::ID;
  84. INITIALIZE_PASS(PatchableFunction, "patchable-function",
  85. "Implement the 'patchable-function' attribute", false, false)