blob: fc56e67b85c58d29b7e97bf80d7dd8b06d5e1042 [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
Lang Hamesed96cb72015-04-07 06:12:21 +000028 // List of x86-64 GPRs to save. Note - RBP saved separately below.
29 std::array<const char *, 14> GPRs = {{
30 "rax", "rbx", "rcx", "rdx",
31 "rsi", "rdi", "r8", "r9",
32 "r10", "r11", "r12", "r13",
33 "r14", "r15"
Lang Hamese51ab6e2015-04-06 03:01:29 +000034 }};
35
36 // Address of the executeCompileCallback function.
NAKAMURA Takumicd5a3672015-02-17 12:53:16 +000037 uint64_t CallbackAddr =
Lang Hamese51ab6e2015-04-06 03:01:29 +000038 static_cast<uint64_t>(
39 reinterpret_cast<uintptr_t>(executeCompileCallback));
Lang Hames93de2a12015-01-23 21:25:00 +000040
Lang Hames27547142015-02-17 01:18:38 +000041 std::ostringstream AsmStream;
Lang Hames93de2a12015-01-23 21:25:00 +000042 Triple TT(M.getTargetTriple());
43
Lang Hamese51ab6e2015-04-06 03:01:29 +000044 // Switch to text section.
Lang Hames93de2a12015-01-23 21:25:00 +000045 if (TT.getOS() == Triple::Darwin)
Lang Hames27547142015-02-17 01:18:38 +000046 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
47 << ".align 4, 0x90\n";
Lang Hames93de2a12015-01-23 21:25:00 +000048 else
Lang Hames27547142015-02-17 01:18:38 +000049 AsmStream << ".text\n"
50 << ".align 16, 0x90\n";
Lang Hames93de2a12015-01-23 21:25:00 +000051
Lang Hamese51ab6e2015-04-06 03:01:29 +000052 // Bake in a pointer to the callback manager immediately before the
53 // start of the resolver function.
Lang Hames27547142015-02-17 01:18:38 +000054 AsmStream << "jit_callback_manager_addr:\n"
Lang Hamese51ab6e2015-04-06 03:01:29 +000055 << " .quad " << &JCBM << "\n";
Lang Hames93de2a12015-01-23 21:25:00 +000056
Lang Hamese51ab6e2015-04-06 03:01:29 +000057 // Start the resolver function.
58 AsmStream << ResolverBlockName << ":\n"
59 << " pushq %rbp\n"
60 << " movq %rsp, %rbp\n";
Lang Hames93de2a12015-01-23 21:25:00 +000061
Lang Hamese51ab6e2015-04-06 03:01:29 +000062 // Store the GPRs.
63 for (const auto &GPR : GPRs)
64 AsmStream << " pushq %" << GPR << "\n";
65
66 // Store floating-point state with FXSAVE.
Lang Hamesed96cb72015-04-07 06:12:21 +000067 // Note: We need to keep the stack 16-byte aligned, so if we've emitted an odd
68 // number of 64-bit pushes so far (GPRs.size() plus 1 for RBP) then add
69 // an extra 64 bits of padding to the FXSave area.
70 unsigned Padding = (GPRs.size() + 1) % 2 ? 8 : 0;
71 unsigned FXSaveSize = 512 + Padding;
72 AsmStream << " subq $" << FXSaveSize << ", %rsp\n"
Lang Hamese51ab6e2015-04-06 03:01:29 +000073 << " fxsave (%rsp)\n"
74
75 // Load callback manager address, compute trampoline address, call JIT.
76 << " lea jit_callback_manager_addr(%rip), %rdi\n"
Lang Hames27547142015-02-17 01:18:38 +000077 << " movq (%rdi), %rdi\n"
Lang Hamese51ab6e2015-04-06 03:01:29 +000078 << " movq 0x8(%rbp), %rsi\n"
Lang Hamescd118e72015-03-24 04:27:02 +000079 << " subq $" << X86_64_TrampolineLength << ", %rsi\n"
Lang Hames27547142015-02-17 01:18:38 +000080 << " movabsq $" << CallbackAddr << ", %rax\n"
81 << " callq *%rax\n"
Lang Hames93de2a12015-01-23 21:25:00 +000082
Lang Hamese51ab6e2015-04-06 03:01:29 +000083 // Replace the return to the trampoline with the return address of the
84 // compiled function body.
85 << " movq %rax, 0x8(%rbp)\n"
Lang Hames93de2a12015-01-23 21:25:00 +000086
Lang Hamese51ab6e2015-04-06 03:01:29 +000087 // Restore the floating point state.
88 << " fxrstor (%rsp)\n"
Lang Hamesed96cb72015-04-07 06:12:21 +000089 << " addq $" << FXSaveSize << ", %rsp\n";
Lang Hamese51ab6e2015-04-06 03:01:29 +000090
91 for (const auto &GPR : make_range(GPRs.rbegin(), GPRs.rend()))
92 AsmStream << " popq %" << GPR << "\n";
93
94 // Restore original RBP and return to compiled function body.
95 AsmStream << " popq %rbp\n"
96 << " retq\n";
Lang Hames93de2a12015-01-23 21:25:00 +000097
Lang Hames27547142015-02-17 01:18:38 +000098 M.appendModuleInlineAsm(AsmStream.str());
Lang Hames93de2a12015-01-23 21:25:00 +000099}
Lang Hames27547142015-02-17 01:18:38 +0000100
101OrcX86_64::LabelNameFtor
102OrcX86_64::insertCompileCallbackTrampolines(Module &M,
103 TargetAddress ResolverBlockAddr,
104 unsigned NumCalls,
105 unsigned StartIndex) {
106 const char *ResolverBlockPtrName = "Lorc_resolve_block_addr";
107
108 std::ostringstream AsmStream;
109 Triple TT(M.getTargetTriple());
110
111 if (TT.getOS() == Triple::Darwin)
112 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n"
113 << ".align 4, 0x90\n";
114 else
115 AsmStream << ".text\n"
116 << ".align 16, 0x90\n";
117
118 AsmStream << ResolverBlockPtrName << ":\n"
119 << " .quad " << ResolverBlockAddr << "\n";
120
121 auto GetLabelName =
122 [=](unsigned I) {
123 std::ostringstream LabelStream;
124 LabelStream << "orc_jcc_" << (StartIndex + I);
125 return LabelStream.str();
126 };
127
128 for (unsigned I = 0; I < NumCalls; ++I)
129 AsmStream << GetLabelName(I) << ":\n"
130 << " callq *" << ResolverBlockPtrName << "(%rip)\n";
131
132 M.appendModuleInlineAsm(AsmStream.str());
133
134 return GetLabelName;
135}
136
Lang Hamese7380612015-02-21 20:44:36 +0000137} // End namespace orc.
138} // End namespace llvm.