[llvm] r260338 - [Orc] Add lazy-JITting support for i386.

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 10 12:52:23 PST 2016


There was existing breakage so there was no green/red transition or
notification:
http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/6282
before
http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/6283
after

I took a shot at debugging this, but it didn't seem like an easy fix. One
of two things happened on any given run:
1. crash on 'fxsave [esp+10h]' in JITed code
2. crash on RuntimeDyldCOFFI386.cpp:136 due to SectionA being -1.

I have no idea why fxsave was faulting with an access violation. The memory
operand appeared to be valid. I guess this is the resolver code that you
added.

Here's the relevant code for the second crash:
    case COFF::IMAGE_REL_I386_DIR32NB: {
      // The target's 32-bit RVA.
      // NOTE: use Section[0].getLoadAddress() as an approximation of
ImageBase
      uint64_t Result =

Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
          Sections[0].getLoadAddress();

The case above handles the case where SectionA is -1, but this one doesn't.
I'm not sure what the correct behavior here is.

On Wed, Feb 10, 2016 at 11:55 AM, Lang Hames <lhames at gmail.com> wrote:

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


More information about the llvm-commits mailing list