PatchableFunction.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. using namespace llvm;
  21. namespace {
  22. struct PatchableFunction : public MachineFunctionPass {
  23. static char ID; // Pass identification, replacement for typeid
  24. PatchableFunction() : MachineFunctionPass(ID) {
  25. initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
  26. }
  27. bool runOnMachineFunction(MachineFunction &F) override;
  28. MachineFunctionProperties getRequiredProperties() const override {
  29. return MachineFunctionProperties().set(
  30. MachineFunctionProperties::Property::NoVRegs);
  31. }
  32. };
  33. }
  34. /// Returns true if instruction \p MI will not result in actual machine code
  35. /// instructions.
  36. static bool doesNotGeneratecode(const MachineInstr &MI) {
  37. // TODO: Introduce an MCInstrDesc flag for this
  38. switch (MI.getOpcode()) {
  39. default: return false;
  40. case TargetOpcode::IMPLICIT_DEF:
  41. case TargetOpcode::KILL:
  42. case TargetOpcode::CFI_INSTRUCTION:
  43. case TargetOpcode::EH_LABEL:
  44. case TargetOpcode::GC_LABEL:
  45. case TargetOpcode::DBG_VALUE:
  46. case TargetOpcode::DBG_LABEL:
  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.add(MO);
  69. FirstActualI->eraseFromParent();
  70. MF.ensureAlignment(llvm::Align(16));
  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)