<div dir="ltr">Thanks for that Reid!<div><br></div><div>I didn't see any bot failures - did I miss an email?</div><div><br></div><div>I'm curious to see what the failures looked like - If I can recognize an obvious failure to save some state in the re-entry function I may be able to fix them by inspection. Anything more intricate than that would have to wait for now.</div><div><br></div><div>- Lang. </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 10, 2016 at 11:00 AM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I disabled the lazy orc jit tests on windows in r260405.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Feb 9, 2016 at 5:02 PM, Lang Hames via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lhames<br>
Date: Tue Feb 9 19:02:33 2016<br>
New Revision: 260338<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=260338&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=260338&view=rev</a><br>
Log:<br>
[Orc] Add lazy-JITting support for i386.<br>
<br>
This patch adds a new class, OrcI386, which contains the hooks needed to<br>
support lazy-JITing on i386 (currently only for Pentium 2 or above, as the JIT<br>
re-entry code uses the FXSAVE/FXRSTOR instructions).<br>
<br>
Support for i386 is enabled in the LLI lazy JIT and the Orc C API, and<br>
regression and unit tests are enabled for this architecture.<br>
<br>
<br>
Modified:<br>
llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h<br>
llvm/trunk/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp<br>
llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp<br>
llvm/trunk/test/ExecutionEngine/OrcLazy/lit.local.cfg<br>
llvm/trunk/tools/lli/OrcLazyJIT.cpp<br>
llvm/trunk/unittests/ExecutionEngine/Orc/OrcTestCommon.h<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h?rev=260338&r1=260337&r2=260338&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h?rev=260338&r1=260337&r2=260338&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h Tue Feb 9 19:02:33 2016<br>
@@ -145,6 +145,42 @@ public:<br>
void *InitialPtrVal);<br>
};<br>
<br>
+/// @brief I386 support.<br>
+///<br>
+/// I386 supports lazy JITing.<br>
+class OrcI386 {<br>
+public:<br>
+ static const unsigned PointerSize = 4;<br>
+ static const unsigned TrampolineSize = 8;<br>
+ static const unsigned ResolverCodeSize = 0x66;<br>
+<br>
+ typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;<br>
+<br>
+ typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);<br>
+<br>
+ /// @brief Write the resolver code into the given memory. The user is be<br>
+ /// responsible for allocating the memory and setting permissions.<br>
+ static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,<br>
+ void *CallbackMgr);<br>
+<br>
+ /// @brief Write the requsted number of trampolines into the given memory,<br>
+ /// which must be big enough to hold 1 pointer, plus NumTrampolines<br>
+ /// trampolines.<br>
+ static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,<br>
+ unsigned NumTrampolines);<br>
+<br>
+ /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to<br>
+ /// the nearest page size.<br>
+ ///<br>
+ /// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k<br>
+ /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513<br>
+ /// will return a block of 1024 (2-pages worth).<br>
+ static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,<br>
+ unsigned MinStubs,<br>
+ void *InitialPtrVal);<br>
+};<br>
+<br>
+<br>
} // End namespace orc.<br>
} // End namespace llvm.<br>
<br>
<br>
Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp?rev=260338&r1=260337&r2=260338&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp?rev=260338&r1=260337&r2=260338&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp (original)<br>
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp Tue Feb 9 19:02:33 2016<br>
@@ -165,5 +165,130 @@ std::error_code OrcX86_64::emitIndirectS<br>
return std::error_code();<br>
}<br>
<br>
+void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn,<br>
+ void *CallbackMgr) {<br>
+<br>
+ const uint8_t ResolverCode[] = {<br>
+ // resolver_entry:<br>
+ 0x55, // 0x00: pushl %ebp<br>
+ 0x89, 0xe5, // 0x01: movl %esp, %ebp<br>
+ 0x50, // 0x03: pushl %eax<br>
+ 0x53, // 0x04: pushl %ebx<br>
+ 0x51, // 0x05: pushl %ecx<br>
+ 0x52, // 0x06: pushl %edx<br>
+ 0x56, // 0x07: pushl %esi<br>
+ 0x57, // 0x08: pushl %edi<br>
+ 0x81, 0xec, 0x1C, 0x02, 0x00, 0x00, // 0x09: subl $0x21C, %esp<br>
+ 0x0f, 0xae, 0x44, 0x24, 0x10, // 0x0f: fxsave 0x10(%esp)<br>
+ 0x8b, 0x75, 0x04, // 0x14: movl 0x4(%ebp), %esi<br>
+ 0x83, 0xee, 0x05, // 0x17: subl $0x5, %esi<br>
+ 0x89, 0x74, 0x24, 0x04, // 0x1a: movl %esi, 0x4(%esp)<br>
+ 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, // 0x1e: movl <cbmgr>, (%esp)<br>
+ 0xb8, 0x00, 0x00, 0x00, 0x00, // 0x25: movl <reentry>, %eax<br>
+ 0xff, 0xd0, // 0x2a: calll *%eax<br>
+ 0x89, 0x45, 0x04, // 0x2c: movl %eax, 0x4(%ebp)<br>
+ 0x0f, 0xae, 0x4c, 0x24, 0x10, // 0x2f: fxrstor 0x10(%esp)<br>
+ 0x81, 0xc4, 0x1c, 0x02, 0x00, 0x00, // 0x34: addl $0x21C, %esp<br>
+ 0x5f, // 0x3a: popl %edi<br>
+ 0x5e, // 0x3b: popl %esi<br>
+ 0x5a, // 0x3c: popl %edx<br>
+ 0x59, // 0x3d: popl %ecx<br>
+ 0x5b, // 0x3e: popl %ebx<br>
+ 0x58, // 0x3f: popl %eax<br>
+ 0x5d, // 0x40: popl %ebp<br>
+ 0xc3 // 0x41: retl<br>
+ };<br>
+<br>
+ const unsigned ReentryFnAddrOffset = 0x26;<br>
+ const unsigned CallbackMgrAddrOffset = 0x21;<br>
+<br>
+ memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));<br>
+ memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn));<br>
+ memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,<br>
+ sizeof(CallbackMgr));<br>
+}<br>
+<br>
+void OrcI386::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,<br>
+ unsigned NumTrampolines) {<br>
+<br>
+ uint64_t CallRelImm = 0xF1C4C400000000e8;<br>
+ uint64_t Resolver = reinterpret_cast<uint64_t>(ResolverAddr);<br>
+ uint64_t ResolverRel =<br>
+ Resolver - reinterpret_cast<uint64_t>(TrampolineMem) - 5;<br>
+<br>
+ uint64_t *Trampolines = reinterpret_cast<uint64_t*>(TrampolineMem);<br>
+ for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize)<br>
+ Trampolines[I] = CallRelImm | (ResolverRel << 8);<br>
+}<br>
+<br>
+std::error_code OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,<br>
+ unsigned MinStubs,<br>
+ void *InitialPtrVal) {<br>
+ // Stub format is:<br>
+ //<br>
+ // .section __orc_stubs<br>
+ // stub1:<br>
+ // jmpq *ptr1<br>
+ // .byte 0xC4 ; <- Invalid opcode padding.<br>
+ // .byte 0xF1<br>
+ // stub2:<br>
+ // jmpq *ptr2<br>
+ //<br>
+ // ...<br>
+ //<br>
+ // .section __orc_ptrs<br>
+ // ptr1:<br>
+ // .quad 0x0<br>
+ // ptr2:<br>
+ // .quad 0x0<br>
+ //<br>
+ // ...<br>
+<br>
+ const unsigned StubSize = IndirectStubsInfo::StubSize;<br>
+<br>
+ // Emit at least MinStubs, rounded up to fill the pages allocated.<br>
+ unsigned PageSize = sys::Process::getPageSize();<br>
+ unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;<br>
+ unsigned NumStubs = (NumPages * PageSize) / StubSize;<br>
+<br>
+ // Allocate memory for stubs and pointers in one call.<br>
+ std::error_code EC;<br>
+ auto StubsMem =<br>
+ sys::OwningMemoryBlock(<br>
+ sys::Memory::allocateMappedMemory(2 * NumPages * PageSize, nullptr,<br>
+ sys::Memory::MF_READ |<br>
+ sys::Memory::MF_WRITE,<br>
+ EC));<br>
+<br>
+ if (EC)<br>
+ return EC;<br>
+<br>
+ // Create separate MemoryBlocks representing the stubs and pointers.<br>
+ sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);<br>
+ sys::MemoryBlock PtrsBlock(static_cast<char*>(StubsMem.base()) +<br>
+ NumPages * PageSize,<br>
+ NumPages * PageSize);<br>
+<br>
+ // Populate the stubs page stubs and mark it executable.<br>
+ uint64_t *Stub = reinterpret_cast<uint64_t*>(StubsBlock.base());<br>
+ uint64_t PtrAddr = reinterpret_cast<uint64_t>(PtrsBlock.base());<br>
+ for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4)<br>
+ Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16);<br>
+<br>
+ if (auto EC = sys::Memory::protectMappedMemory(StubsBlock,<br>
+ sys::Memory::MF_READ |<br>
+ sys::Memory::MF_EXEC))<br>
+ return EC;<br>
+<br>
+ // Initialize all pointers to point at FailureAddress.<br>
+ void **Ptr = reinterpret_cast<void**>(PtrsBlock.base());<br>
+ for (unsigned I = 0; I < NumStubs; ++I)<br>
+ Ptr[I] = InitialPtrVal;<br>
+<br>
+ StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));<br>
+<br>
+ return std::error_code();<br>
+}<br>
+<br>
} // End namespace orc.<br>
} // End namespace llvm.<br>
<br>
Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp?rev=260338&r1=260337&r2=260338&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp?rev=260338&r1=260337&r2=260338&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp (original)<br>
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp Tue Feb 9 19:02:33 2016<br>
@@ -22,6 +22,11 @@ OrcCBindingsStack::createCompileCallback<br>
switch (T.getArch()) {<br>
default: return nullptr;<br>
<br>
+ case Triple::x86: {<br>
+ typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;<br>
+ return llvm::make_unique<CCMgrT>(0);<br>
+ };<br>
+<br>
case Triple::x86_64: {<br>
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64> CCMgrT;<br>
return llvm::make_unique<CCMgrT>(0);<br>
@@ -34,6 +39,12 @@ OrcCBindingsStack::createIndirectStubsMg<br>
switch (T.getArch()) {<br>
default: return nullptr;<br>
<br>
+ case Triple::x86:<br>
+ return [](){<br>
+ return llvm::make_unique<<br>
+ orc::LocalIndirectStubsManager<orc::OrcI386>>();<br>
+ };<br>
+<br>
case Triple::x86_64:<br>
return [](){<br>
return llvm::make_unique<<br>
<br>
Modified: llvm/trunk/test/ExecutionEngine/OrcLazy/lit.local.cfg<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/OrcLazy/lit.local.cfg?rev=260338&r1=260337&r2=260338&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/OrcLazy/lit.local.cfg?rev=260338&r1=260337&r2=260338&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/ExecutionEngine/OrcLazy/lit.local.cfg (original)<br>
+++ llvm/trunk/test/ExecutionEngine/OrcLazy/lit.local.cfg Tue Feb 9 19:02:33 2016<br>
@@ -1,2 +1,2 @@<br>
-if config.root.host_arch not in ['x86_64']:<br>
+if config.root.host_arch not in ['i386', 'x86', 'x86_64', 'AMD64']:<br>
config.unsupported = True<br>
<br>
Modified: llvm/trunk/tools/lli/OrcLazyJIT.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/OrcLazyJIT.cpp?rev=260338&r1=260337&r2=260338&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/OrcLazyJIT.cpp?rev=260338&r1=260337&r2=260338&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/lli/OrcLazyJIT.cpp (original)<br>
+++ llvm/trunk/tools/lli/OrcLazyJIT.cpp Tue Feb 9 19:02:33 2016<br>
@@ -51,6 +51,11 @@ OrcLazyJIT::createCompileCallbackMgr(Tri<br>
switch (T.getArch()) {<br>
default: return nullptr;<br>
<br>
+ case Triple::x86: {<br>
+ typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;<br>
+ return llvm::make_unique<CCMgrT>(0);<br>
+ }<br>
+<br>
case Triple::x86_64: {<br>
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64> CCMgrT;<br>
return llvm::make_unique<CCMgrT>(0);<br>
@@ -63,6 +68,12 @@ OrcLazyJIT::createIndirectStubsMgrBuilde<br>
switch (T.getArch()) {<br>
default: return nullptr;<br>
<br>
+ case Triple::x86:<br>
+ return [](){<br>
+ return llvm::make_unique<<br>
+ orc::LocalIndirectStubsManager<orc::OrcI386>>();<br>
+ };<br>
+<br>
case Triple::x86_64:<br>
return [](){<br>
return llvm::make_unique<<br>
<br>
Modified: llvm/trunk/unittests/ExecutionEngine/Orc/OrcTestCommon.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/OrcTestCommon.h?rev=260338&r1=260337&r2=260338&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/OrcTestCommon.h?rev=260338&r1=260337&r2=260338&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ExecutionEngine/Orc/OrcTestCommon.h (original)<br>
+++ llvm/trunk/unittests/ExecutionEngine/Orc/OrcTestCommon.h Tue Feb 9 19:02:33 2016<br>
@@ -46,7 +46,9 @@ public:<br>
if (TM) {<br>
// If we found a TargetMachine, check that it's one that Orc supports.<br>
const Triple& TT = TM->getTargetTriple();<br>
- if (TT.getArch() != Triple::x86_64 || TT.isOSWindows())<br>
+<br>
+ if ((TT.getArch() != Triple::x86_64 && TT.getArch() != Triple::x86) ||<br>
+ TT.isOSWindows())<br>
TM = nullptr;<br>
}<br>
};<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>