<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>