1 #include "llvm/ADT/Triple.h"
2 #include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
5 using namespace llvm::orc;
9 uint64_t executeCompileCallback(JITCompileCallbackManagerBase *JCBM,
10 TargetAddress CallbackID) {
11 return JCBM->executeCompileCallback(CallbackID);
19 const char* OrcX86_64::ResolverBlockName = "orc_resolver_block";
21 void OrcX86_64::insertResolverBlock(
22 Module &M, JITCompileCallbackManagerBase &JCBM) {
24 // Trampoline code-sequence length, used to get trampoline address from return
26 const unsigned X86_64_TrampolineLength = 6;
28 // List of x86-64 GPRs to save.
29 std::array<const char *, 11> GPRs = {{
30 "rbx", "r12", "r13", "r14", "r15", // Callee saved (rbp preserved below).
31 "rdi", "rsi", "rdx", "rcx", "r8", "r9", // Int args.
34 // Address of the executeCompileCallback function.
35 uint64_t CallbackAddr =
36 static_cast<uint64_t>(
37 reinterpret_cast<uintptr_t>(executeCompileCallback));
39 std::ostringstream AsmStream;
40 Triple TT(M.getTargetTriple());
42 // Switch to text section.
43 if (TT.getOS() == Triple::Darwin)
44 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
45 << ".align 4, 0x90\n";
47 AsmStream << ".text\n"
48 << ".align 16, 0x90\n";
50 // Bake in a pointer to the callback manager immediately before the
51 // start of the resolver function.
52 AsmStream << "jit_callback_manager_addr:\n"
53 << " .quad " << &JCBM << "\n";
55 // Start the resolver function.
56 AsmStream << ResolverBlockName << ":\n"
58 << " movq %rsp, %rbp\n";
61 for (const auto &GPR : GPRs)
62 AsmStream << " pushq %" << GPR << "\n";
64 // Store floating-point state with FXSAVE.
65 AsmStream << " subq $512, %rsp\n"
68 // Load callback manager address, compute trampoline address, call JIT.
69 << " lea jit_callback_manager_addr(%rip), %rdi\n"
70 << " movq (%rdi), %rdi\n"
71 << " movq 0x8(%rbp), %rsi\n"
72 << " subq $" << X86_64_TrampolineLength << ", %rsi\n"
73 << " movabsq $" << CallbackAddr << ", %rax\n"
76 // Replace the return to the trampoline with the return address of the
77 // compiled function body.
78 << " movq %rax, 0x8(%rbp)\n"
80 // Restore the floating point state.
81 << " fxrstor (%rsp)\n"
82 << " addq $512, %rsp\n";
84 for (const auto &GPR : make_range(GPRs.rbegin(), GPRs.rend()))
85 AsmStream << " popq %" << GPR << "\n";
87 // Restore original RBP and return to compiled function body.
88 AsmStream << " popq %rbp\n"
91 M.appendModuleInlineAsm(AsmStream.str());
94 OrcX86_64::LabelNameFtor
95 OrcX86_64::insertCompileCallbackTrampolines(Module &M,
96 TargetAddress ResolverBlockAddr,
98 unsigned StartIndex) {
99 const char *ResolverBlockPtrName = "Lorc_resolve_block_addr";
101 std::ostringstream AsmStream;
102 Triple TT(M.getTargetTriple());
104 if (TT.getOS() == Triple::Darwin)
105 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
106 << ".align 4, 0x90\n";
108 AsmStream << ".text\n"
109 << ".align 16, 0x90\n";
111 AsmStream << ResolverBlockPtrName << ":\n"
112 << " .quad " << ResolverBlockAddr << "\n";
116 std::ostringstream LabelStream;
117 LabelStream << "orc_jcc_" << (StartIndex + I);
118 return LabelStream.str();
121 for (unsigned I = 0; I < NumCalls; ++I)
122 AsmStream << GetLabelName(I) << ":\n"
123 << " callq *" << ResolverBlockPtrName << "(%rip)\n";
125 M.appendModuleInlineAsm(AsmStream.str());
130 } // End namespace orc.
131 } // End namespace llvm.