OrcTargetSupport.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "llvm/ADT/Triple.h"
  2. #include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
  3. #include <array>
  4. using namespace llvm::orc;
  5. namespace {
  6. uint64_t executeCompileCallback(JITCompileCallbackManagerBase *JCBM,
  7. TargetAddress CallbackID) {
  8. return JCBM->executeCompileCallback(CallbackID);
  9. }
  10. }
  11. namespace llvm {
  12. namespace orc {
  13. const char* OrcX86_64::ResolverBlockName = "orc_resolver_block";
  14. void OrcX86_64::insertResolverBlock(
  15. Module &M, JITCompileCallbackManagerBase &JCBM) {
  16. // Trampoline code-sequence length, used to get trampoline address from return
  17. // address.
  18. const unsigned X86_64_TrampolineLength = 6;
  19. // List of x86-64 GPRs to save. Note - RBP saved separately below.
  20. std::array<const char *, 14> GPRs = {{
  21. "rax", "rbx", "rcx", "rdx",
  22. "rsi", "rdi", "r8", "r9",
  23. "r10", "r11", "r12", "r13",
  24. "r14", "r15"
  25. }};
  26. // Address of the executeCompileCallback function.
  27. uint64_t CallbackAddr =
  28. static_cast<uint64_t>(
  29. reinterpret_cast<uintptr_t>(executeCompileCallback));
  30. std::ostringstream AsmStream;
  31. Triple TT(M.getTargetTriple());
  32. // Switch to text section.
  33. if (TT.getOS() == Triple::Darwin)
  34. AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
  35. << ".align 4, 0x90\n";
  36. else
  37. AsmStream << ".text\n"
  38. << ".align 16, 0x90\n";
  39. // Bake in a pointer to the callback manager immediately before the
  40. // start of the resolver function.
  41. AsmStream << "jit_callback_manager_addr:\n"
  42. << " .quad " << &JCBM << "\n";
  43. // Start the resolver function.
  44. AsmStream << ResolverBlockName << ":\n"
  45. << " pushq %rbp\n"
  46. << " movq %rsp, %rbp\n";
  47. // Store the GPRs.
  48. for (const auto &GPR : GPRs)
  49. AsmStream << " pushq %" << GPR << "\n";
  50. // Store floating-point state with FXSAVE.
  51. // Note: We need to keep the stack 16-byte aligned, so if we've emitted an odd
  52. // number of 64-bit pushes so far (GPRs.size() plus 1 for RBP) then add
  53. // an extra 64 bits of padding to the FXSave area.
  54. unsigned Padding = (GPRs.size() + 1) % 2 ? 8 : 0;
  55. unsigned FXSaveSize = 512 + Padding;
  56. AsmStream << " subq $" << FXSaveSize << ", %rsp\n"
  57. << " fxsave64 (%rsp)\n"
  58. // Load callback manager address, compute trampoline address, call JIT.
  59. << " lea jit_callback_manager_addr(%rip), %rdi\n"
  60. << " movq (%rdi), %rdi\n"
  61. << " movq 0x8(%rbp), %rsi\n"
  62. << " subq $" << X86_64_TrampolineLength << ", %rsi\n"
  63. << " movabsq $" << CallbackAddr << ", %rax\n"
  64. << " callq *%rax\n"
  65. // Replace the return to the trampoline with the return address of the
  66. // compiled function body.
  67. << " movq %rax, 0x8(%rbp)\n"
  68. // Restore the floating point state.
  69. << " fxrstor64 (%rsp)\n"
  70. << " addq $" << FXSaveSize << ", %rsp\n";
  71. for (const auto &GPR : make_range(GPRs.rbegin(), GPRs.rend()))
  72. AsmStream << " popq %" << GPR << "\n";
  73. // Restore original RBP and return to compiled function body.
  74. AsmStream << " popq %rbp\n"
  75. << " retq\n";
  76. M.appendModuleInlineAsm(AsmStream.str());
  77. }
  78. OrcX86_64::LabelNameFtor
  79. OrcX86_64::insertCompileCallbackTrampolines(Module &M,
  80. TargetAddress ResolverBlockAddr,
  81. unsigned NumCalls,
  82. unsigned StartIndex) {
  83. const char *ResolverBlockPtrName = "Lorc_resolve_block_addr";
  84. std::ostringstream AsmStream;
  85. Triple TT(M.getTargetTriple());
  86. if (TT.getOS() == Triple::Darwin)
  87. AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
  88. << ".align 4, 0x90\n";
  89. else
  90. AsmStream << ".text\n"
  91. << ".align 16, 0x90\n";
  92. AsmStream << ResolverBlockPtrName << ":\n"
  93. << " .quad " << ResolverBlockAddr << "\n";
  94. auto GetLabelName =
  95. [=](unsigned I) {
  96. std::ostringstream LabelStream;
  97. LabelStream << "orc_jcc_" << (StartIndex + I);
  98. return LabelStream.str();
  99. };
  100. for (unsigned I = 0; I < NumCalls; ++I)
  101. AsmStream << GetLabelName(I) << ":\n"
  102. << " callq *" << ResolverBlockPtrName << "(%rip)\n";
  103. M.appendModuleInlineAsm(AsmStream.str());
  104. return GetLabelName;
  105. }
  106. } // End namespace orc.
  107. } // End namespace llvm.