blob: 67861c34b32af9705f3b9831b7bd880d3faa13f4 [file] [log] [blame]
Lang Hames93de2a12015-01-23 21:25:00 +00001#include "llvm/ADT/Triple.h"
Lang Hames27547142015-02-17 01:18:38 +00002#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
Lang Hames93de2a12015-01-23 21:25:00 +00003#include <array>
4
Lang Hamese7380612015-02-21 20:44:36 +00005using namespace llvm::orc;
Lang Hames93de2a12015-01-23 21:25:00 +00006
7namespace {
8
Lang Hames8389b552015-03-25 02:45:50 +00009uint64_t executeCompileCallback(JITCompileCallbackManagerBase *JCBM,
Lang Hames27547142015-02-17 01:18:38 +000010 TargetAddress CallbackID) {
11 return JCBM->executeCompileCallback(CallbackID);
Lang Hames93de2a12015-01-23 21:25:00 +000012}
Lang Hames27547142015-02-17 01:18:38 +000013
Lang Hames93de2a12015-01-23 21:25:00 +000014}
15
16namespace llvm {
Lang Hamese7380612015-02-21 20:44:36 +000017namespace orc {
Lang Hames93de2a12015-01-23 21:25:00 +000018
Lang Hames27547142015-02-17 01:18:38 +000019const char* OrcX86_64::ResolverBlockName = "orc_resolver_block";
Lang Hames93de2a12015-01-23 21:25:00 +000020
Lang Hames27547142015-02-17 01:18:38 +000021void OrcX86_64::insertResolverBlock(
Lang Hames8389b552015-03-25 02:45:50 +000022 Module &M, JITCompileCallbackManagerBase &JCBM) {
Lang Hamese51ab6e2015-04-06 03:01:29 +000023
24 // Trampoline code-sequence length, used to get trampoline address from return
25 // address.
Lang Hamescd118e72015-03-24 04:27:02 +000026 const unsigned X86_64_TrampolineLength = 6;
Lang Hamese51ab6e2015-04-06 03:01:29 +000027
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.
32 }};
33
34 // Address of the executeCompileCallback function.
NAKAMURA Takumicd5a3672015-02-17 12:53:16 +000035 uint64_t CallbackAddr =
Lang Hamese51ab6e2015-04-06 03:01:29 +000036 static_cast<uint64_t>(
37 reinterpret_cast<uintptr_t>(executeCompileCallback));
Lang Hames93de2a12015-01-23 21:25:00 +000038
Lang Hames27547142015-02-17 01:18:38 +000039 std::ostringstream AsmStream;
Lang Hames93de2a12015-01-23 21:25:00 +000040 Triple TT(M.getTargetTriple());
41
Lang Hamese51ab6e2015-04-06 03:01:29 +000042 // Switch to text section.
Lang Hames93de2a12015-01-23 21:25:00 +000043 if (TT.getOS() == Triple::Darwin)
Lang Hames27547142015-02-17 01:18:38 +000044 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
45 << ".align 4, 0x90\n";
Lang Hames93de2a12015-01-23 21:25:00 +000046 else
Lang Hames27547142015-02-17 01:18:38 +000047 AsmStream << ".text\n"
48 << ".align 16, 0x90\n";
Lang Hames93de2a12015-01-23 21:25:00 +000049
Lang Hamese51ab6e2015-04-06 03:01:29 +000050 // Bake in a pointer to the callback manager immediately before the
51 // start of the resolver function.
Lang Hames27547142015-02-17 01:18:38 +000052 AsmStream << "jit_callback_manager_addr:\n"
Lang Hamese51ab6e2015-04-06 03:01:29 +000053 << " .quad " << &JCBM << "\n";
Lang Hames93de2a12015-01-23 21:25:00 +000054
Lang Hamese51ab6e2015-04-06 03:01:29 +000055 // Start the resolver function.
56 AsmStream << ResolverBlockName << ":\n"
57 << " pushq %rbp\n"
58 << " movq %rsp, %rbp\n";
Lang Hames93de2a12015-01-23 21:25:00 +000059
Lang Hamese51ab6e2015-04-06 03:01:29 +000060 // Store the GPRs.
61 for (const auto &GPR : GPRs)
62 AsmStream << " pushq %" << GPR << "\n";
63
64 // Store floating-point state with FXSAVE.
65 AsmStream << " subq $512, %rsp\n"
66 << " fxsave (%rsp)\n"
67
68 // Load callback manager address, compute trampoline address, call JIT.
69 << " lea jit_callback_manager_addr(%rip), %rdi\n"
Lang Hames27547142015-02-17 01:18:38 +000070 << " movq (%rdi), %rdi\n"
Lang Hamese51ab6e2015-04-06 03:01:29 +000071 << " movq 0x8(%rbp), %rsi\n"
Lang Hamescd118e72015-03-24 04:27:02 +000072 << " subq $" << X86_64_TrampolineLength << ", %rsi\n"
Lang Hames27547142015-02-17 01:18:38 +000073 << " movabsq $" << CallbackAddr << ", %rax\n"
74 << " callq *%rax\n"
Lang Hames93de2a12015-01-23 21:25:00 +000075
Lang Hamese51ab6e2015-04-06 03:01:29 +000076 // Replace the return to the trampoline with the return address of the
77 // compiled function body.
78 << " movq %rax, 0x8(%rbp)\n"
Lang Hames93de2a12015-01-23 21:25:00 +000079
Lang Hamese51ab6e2015-04-06 03:01:29 +000080 // Restore the floating point state.
81 << " fxrstor (%rsp)\n"
82 << " addq $512, %rsp\n";
83
84 for (const auto &GPR : make_range(GPRs.rbegin(), GPRs.rend()))
85 AsmStream << " popq %" << GPR << "\n";
86
87 // Restore original RBP and return to compiled function body.
88 AsmStream << " popq %rbp\n"
89 << " retq\n";
Lang Hames93de2a12015-01-23 21:25:00 +000090
Lang Hames27547142015-02-17 01:18:38 +000091 M.appendModuleInlineAsm(AsmStream.str());
Lang Hames93de2a12015-01-23 21:25:00 +000092}
Lang Hames27547142015-02-17 01:18:38 +000093
94OrcX86_64::LabelNameFtor
95OrcX86_64::insertCompileCallbackTrampolines(Module &M,
96 TargetAddress ResolverBlockAddr,
97 unsigned NumCalls,
98 unsigned StartIndex) {
99 const char *ResolverBlockPtrName = "Lorc_resolve_block_addr";
100
101 std::ostringstream AsmStream;
102 Triple TT(M.getTargetTriple());
103
104 if (TT.getOS() == Triple::Darwin)
105 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
106 << ".align 4, 0x90\n";
107 else
108 AsmStream << ".text\n"
109 << ".align 16, 0x90\n";
110
111 AsmStream << ResolverBlockPtrName << ":\n"
112 << " .quad " << ResolverBlockAddr << "\n";
113
114 auto GetLabelName =
115 [=](unsigned I) {
116 std::ostringstream LabelStream;
117 LabelStream << "orc_jcc_" << (StartIndex + I);
118 return LabelStream.str();
119 };
120
121 for (unsigned I = 0; I < NumCalls; ++I)
122 AsmStream << GetLabelName(I) << ":\n"
123 << " callq *" << ResolverBlockPtrName << "(%rip)\n";
124
125 M.appendModuleInlineAsm(AsmStream.str());
126
127 return GetLabelName;
128}
129
Lang Hamese7380612015-02-21 20:44:36 +0000130} // End namespace orc.
131} // End namespace llvm.