1 #include "llvm/ADT/Triple.h" 2 #include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h" 3 #include <array> 4 5 using namespace llvm::orc; 6 7 namespace { 8 9 uint64_t executeCompileCallback(JITCompileCallbackManagerBase *JCBM, 10 TargetAddress CallbackID) { 11 return JCBM->executeCompileCallback(CallbackID); 12 } 13 14 } 15 16 namespace llvm { 17 namespace orc { 18 19 const char* OrcX86_64::ResolverBlockName = "orc_resolver_block"; 20 21 void OrcX86_64::insertResolverBlock( 22 Module &M, JITCompileCallbackManagerBase &JCBM) { 23 24 // Trampoline code-sequence length, used to get trampoline address from return 25 // address. 26 const unsigned X86_64_TrampolineLength = 6; 27 28 // 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" 34 }}; 35 36 // Address of the executeCompileCallback function. 37 uint64_t CallbackAddr = 38 static_cast<uint64_t>( 39 reinterpret_cast<uintptr_t>(executeCompileCallback)); 40 41 std::ostringstream AsmStream; 42 Triple TT(M.getTargetTriple()); 43 44 // Switch to text section. 45 if (TT.getOS() == Triple::Darwin) 46 AsmStream << ".section __TEXT,__text,regular,pure_instructions\n" 47 << ".align 4, 0x90\n"; 48 else 49 AsmStream << ".text\n" 50 << ".align 16, 0x90\n"; 51 52 // Bake in a pointer to the callback manager immediately before the 53 // start of the resolver function. 54 AsmStream << "jit_callback_manager_addr:\n" 55 << " .quad " << &JCBM << "\n"; 56 57 // Start the resolver function. 58 AsmStream << ResolverBlockName << ":\n" 59 << " pushq %rbp\n" 60 << " movq %rsp, %rbp\n"; 61 62 // Store the GPRs. 63 for (const auto &GPR : GPRs) 64 AsmStream << " pushq %" << GPR << "\n"; 65 66 // Store floating-point state with FXSAVE. 67 // 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" 73 << " fxsave (%rsp)\n" 74 75 // Load callback manager address, compute trampoline address, call JIT. 76 << " lea jit_callback_manager_addr(%rip), %rdi\n" 77 << " movq (%rdi), %rdi\n" 78 << " movq 0x8(%rbp), %rsi\n" 79 << " subq $" << X86_64_TrampolineLength << ", %rsi\n" 80 << " movabsq $" << CallbackAddr << ", %rax\n" 81 << " callq *%rax\n" 82 83 // Replace the return to the trampoline with the return address of the 84 // compiled function body. 85 << " movq %rax, 0x8(%rbp)\n" 86 87 // Restore the floating point state. 88 << " fxrstor (%rsp)\n" 89 << " addq $" << FXSaveSize << ", %rsp\n"; 90 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"; 97 98 M.appendModuleInlineAsm(AsmStream.str()); 99 } 100 101 OrcX86_64::LabelNameFtor 102 OrcX86_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 137 } // End namespace orc. 138 } // End namespace llvm. 139