<div dir="ltr">I couldn't reproduce the issue on my local work tree. I have to stop the builder to reproduce.<div><br></div><div>The builder is configured;</div><div>- clang built by gcc-4.8</div><div>- Release w/o Asserts</div><div>- Just-built libc++ and libc++abi</div><div>- -fmodules</div><div><br></div><div>-fmodules might be dubious. I'll investigate in my afternoon.</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Sep 7, 2017 at 2:32 AM Lang Hames <<a href="mailto:lhames@gmail.com">lhames@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Takumi,<div><br></div><div>This looks like a possible standard library bug. Thread 2 is blocked trying to re-lock a recursive mutex, but that should be safe. (Thread 1 is just waiting for data from Thread 2, so it's not interesting here).</div><div><br></div><div>How reproducible is this?</div><div><br></div><div>Cheers,</div><div>Lang.</div><div> </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 6, 2017 at 8:57 AM, Lang Hames <span dir="ltr"><<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.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">Hi Takumi,<div><br></div><div>I'll look in to it now.</div><div><br></div><div>Cheers,</div><div>Lang.</div></div><div class="m_-2684236302260965259HOEnZb"><div class="m_-2684236302260965259h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 6, 2017 at 8:11 AM, NAKAMURA Takumi <span dir="ltr"><<a href="mailto:geek4civic@gmail.com" target="_blank">geek4civic@gmail.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">Lang, this hangs up to me.<div><br></div><div><a href="http://bb.pgr.jp/builders/bootstrap-clang-libcxx-lld-i686-linux/builds/1309" target="_blank">http://bb.pgr.jp/builders/bootstrap-clang-libcxx-lld-i686-linux/builds/1309</a><br></div><div>(Note, this isn't i686, but x86-64)</div><div><br></div><div>I can reproduce the issue just on this tree with Debug/Release. Do you know how I can investigate further?</div><div><br></div><div>As far as I investigated,</div><div><br></div><div><div>Thread 2 (Thread 0x7ffff6784700 (LWP 44601)):</div><div>#0  __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135</div><div>#1  0x00007ffff7bc6649 in _L_lock_909 () from /lib/x86_64-linux-gnu/libpthread.so.0</div><div>#2  0x00007ffff7bc6470 in __GI___pthread_mutex_lock (mutex=0x294c080 <llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>) at ../nptl/pthread_mutex_lock.c:79</div><div>#3  0x00000000010ba243 in __gthread_mutex_lock (__mutex=0x294c080 <llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8/bits/gthr-default.h:748</div><div>#4  0x00000000010ba215 in __gthread_recursive_mutex_lock (__mutex=0x294c080 <llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8/bits/gthr-default.h:810</div><div>#5  0x00000000010d77d5 in std::recursive_mutex::lock (this=0x294c080 <llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/mutex:175</div><div>#6  0x00000000010d74d3 in std::lock_guard<std::recursive_mutex>::lock_guard (this=0x7ffff6783888, __m=...) at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/mutex:414</div><div>#7  0x00000000010eb461 in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&) (C=...,</div><div>    Err=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x31a25d>)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:375</div><div>#8  0x00000000010ebabd in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serializeAsStringError (C=..., EIB=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:415</div><div>#9  0x00000000010eb9b6 in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}::operator()(llvm::ErrorInfoBase const&) const (this=0x7ffff6783af8, EIB=...) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:384</div><div>#10 0x00000000010eb91d in llvm::ErrorHandlerTraits<llvm::Error (&)(llvm::ErrorInfoBase&)>::apply<llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}>(llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}&&, std::unique_ptr<llvm::ErrorInfoBase, std::default_delete<llvm::ErrorInfoBase> >) (</div><div>    H=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x31a33f>, E=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/Support/Error.h:752</div><div>#11 0x00000000010eb82b in llvm::handleErrorImpl<llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}>(std::unique_ptr<llvm::ErrorInfoBase, std::default_delete<llvm::ErrorInfoBase> >, llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}&&) (Payload=..., Handler=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x284ec1>)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/Support/Error.h:844</div><div>#12 0x00000000010eb740 in llvm::handleErrors<llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}>(llvm::Error, llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&)::{lambda(llvm::ErrorInfoBase const&)#1}&&) (E=...,</div><div>    Hs=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x284dec>)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/Support/Error.h:873</div><div>#13 0x00000000010eb4d7 in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rpc::RawByteChannel&, llvm::Error&&) (C=...,</div><div>    Err=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x31a25d>)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:380</div><div>#14 0x00000000010eb41f in llvm::orc::rpc::SequenceSerialization<llvm::orc::rpc::RawByteChannel, llvm::Error>::serialize<llvm::Error>(llvm::orc::rpc::RawByteChannel&, llvm::Error&&) (C=...,</div><div>    CArg=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x31a221>)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:277</div><div>#15 0x00000000010eb3bf in llvm::orc::rpc::serializeSeq<llvm::orc::rpc::RawByteChannel, llvm::Error>(llvm::orc::rpc::RawByteChannel&, llvm::Error&&) (C=...,</div><div>    Args=<unknown type in /home/bb/bootstrap-clang-libcxx-lld-i686-linux/builds/stagen/unittests/ExecutionEngine/Orc/OrcJITTests, CU 0x234b90, DIE 0x239991>)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:319</div><div>#16 0x00000000010eb284 in llvm::orc::rpc::detail::RespondHelper<true>::sendResult<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> (C=..., ResponseId=@0x7fffffffdcd8: 1, SeqNo=0, Err=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:426</div><div>#17 0x00000000010ea480 in llvm::orc::rpc::detail::respond<llvm::Error, llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> (C=..., ResponseId=@0x7fffffffdcd8: 1, SeqNo=0, Err=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:489</div><div>#18 0x00000000010be795 in std::function<llvm::Error (llvm::orc::rpc::RawByteChannel&, unsigned int)> llvm::orc::rpc::detail::RPCEndpointBase<llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::wrapHandler<llvm::orc::RemoteObjectLayerAPI::RemoveObject, llvm::orc::rpc::detail::MemberFnWrapper<llvm::orc::RemoteObjectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long> >(llvm::orc::rpc::detail::MemberFnWrapper<llvm::orc::RemoteObjectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long>)::{lambda(llvm::orc::rpc::RawByteChannel&, unsigned int)#1}::operator()(llvm::orc::rpc::RawByteChannel&, unsigned int) (this=0x2bd0960, Channel=..., SeqNo=0) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:1342</div><div>#19 0x00000000010be497 in std::_Function_handler<llvm::Error (llvm::orc::rpc::RawByteChannel&, unsigned int), std::function<llvm::Error (llvm::orc::rpc::RawByteChannel&, unsigned int)> llvm::orc::rpc::detail::RPCEndpointBase<llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::wrapHandler<llvm::orc::RemoteObjectLayerAPI::RemoveObject, llvm::orc::rpc::detail::MemberFnWrapper<llvm::orc::RemoteObjectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long> >(llvm::orc::rpc::detail::MemberFnWrapper<llvm::orc::RemoteObjectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long>)::{lambda(llvm::orc::rpc::RawByteChannel&, unsigned int)#1}>::_M_invoke(std::_Any_data const&, llvm::orc::rpc::RawByteChannel&, unsigned int) (__functor=..., __args=0, __args=0)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2056</div><div>#20 0x00000000010fbddd in std::function<llvm::Error (llvm::orc::rpc::RawByteChannel&, unsigned int)>::operator()(llvm::orc::rpc::RawByteChannel&, unsigned int) const (this=0x2bd09b8, __args=0, __args=0)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2471</div><div>#21 0x00000000010f5984 in llvm::orc::rpc::detail::RPCEndpointBase<llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::handleOne (this=0x7fffffffdcc8) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:1140</div><div>#22 0x00000000010c9782 in (anonymous namespace)::RemoteObjectLayer_RemoveObjectFailure_Test::TestBody()::$_16::operator()() const (this=0x2b66398)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp:309</div><div>#23 0x00000000010c9715 in std::_Bind_simple<(anonymous namespace)::RemoteObjectLayer_RemoveObjectFailure_Test::TestBody()::$_16 ()>::_M_invoke<>(std::_Index_tuple<>) (this=0x2b66398)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1731</div><div>#24 0x00000000010c96e5 in std::_Bind_simple<(anonymous namespace)::RemoteObjectLayer_RemoveObjectFailure_Test::TestBody()::$_16 ()>::operator()() (this=0x2b66398)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1720</div><div>#25 0x00000000010c95a9 in std::thread::_Impl<std::_Bind_simple<(anonymous namespace)::RemoteObjectLayer_RemoveObjectFailure_Test::TestBody()::$_16 ()> >::_M_run() (this=0x2b66380)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:115</div><div>#26 0x00007ffff6e15a40 in std::(anonymous namespace)::execute_native_thread_routine (__p=<optimized out>) at ../../../../../src/libstdc++-v3/src/c++11/thread.cc:84</div><div>#27 0x00007ffff7bc4184 in start_thread (arg=0x7ffff6784700) at pthread_create.c:312</div><div>#28 0x00007ffff6882ffd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111</div><div><br></div><div>Thread 1 (Thread 0x7ffff7fe8780 (LWP 44597)):</div><div>#0  pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185</div><div>#1  0x00007ffff6e124bc in __gthread_cond_wait (__mutex=<optimized out>, __cond=<optimized out>) at /build/buildd/gcc-4.8-4.8.4/build/x86_64-linux-gnu/libstdc++-v3/include/x86_64-linux-gnu/bits/gthr-default.h:864</div><div>#2  std::condition_variable::wait (this=<optimized out>, __lock=...) at ../../../../../src/libstdc++-v3/src/c++11/condition_variable.cc:52</div><div>#3  0x00000000010e109d in llvm::QueueChannel::readBytes (this=0x2b5d920, Dst=0x7fffffffd718 "", Size=8) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/unittests/ExecutionEngine/Orc/QueueChannel.h:90</div><div>#4  0x00000000010d8bc4 in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, unsigned long, unsigned long, void>::deserialize (C=..., V=@0x7fffffffd718: 0)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RawByteChannel.h:105</div><div>#5  0x00000000010d8b74 in llvm::orc::rpc::SequenceSerialization<llvm::orc::rpc::RawByteChannel, unsigned long>::deserialize<unsigned long> (C=..., CArg=@0x7fffffffd718: 0)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:284</div><div>#6  0x00000000010d8b44 in llvm::orc::rpc::deserializeSeq<llvm::orc::rpc::RawByteChannel, unsigned long> (C=..., Args=@0x7fffffffd718: 0)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:325</div><div>#7  0x00000000010d8a57 in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, std::string, std::string, void>::deserialize (C=..., S=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RawByteChannel.h:174</div><div>#8  0x00000000010d8a14 in llvm::orc::rpc::SequenceSerialization<llvm::orc::rpc::RawByteChannel, std::string>::deserialize<std::string> (C=..., CArg=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:284</div><div>#9  0x00000000010d88f4 in llvm::orc::rpc::deserializeSeq<llvm::orc::rpc::RawByteChannel, std::string> (C=..., Args=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:325</div><div>#10 0x00000000010f997f in llvm::orc::rpc::SerializationTraits<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::deserialize (C=..., Err=...)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCSerialization.h:393</div><div>#11 0x000000000110ed4d in llvm::orc::rpc::detail::ResponseHandlerImpl<llvm::orc::rpc::RawByteChannel, llvm::Error, llvm::orc::rpc::detail::ResultTraits<llvm::Error>::ErrorReturnType llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::callB<llvm::orc::RemoteObjectLayerAPI::RemoveObject, unsigned long, llvm::Error>(unsigned long const&)::{lambda(llvm::Error)#1}>::handleResponse(llvm::orc::rpc::RawByteChannel&) (</div><div>    this=0x2b80950, C=...) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:808</div><div>#12 0x00000000010fbc25 in llvm::orc::rpc::detail::RPCEndpointBase<llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::handleResponse (this=0x7fffffffdee0, SeqNo=0) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:1262</div><div>#13 0x00000000010f5916 in llvm::orc::rpc::detail::RPCEndpointBase<llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::handleOne (this=0x7fffffffdee0) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:1137</div><div>#14 0x000000000110e280 in llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int>::callB<llvm::orc::RemoteObjectLayerAPI::RemoveObject, unsigned long, llvm::Error> (this=0x7fffffffdee0,</div><div>    Args=@0x7fffffffda30: 1) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h:1588</div><div>#15 0x000000000110d0aa in llvm::orc::RemoteObjectClientLayer<llvm::orc::rpc::SingleThreadedRPCEndpoint<llvm::orc::rpc::RawByteChannel, unsigned int, unsigned int> >::removeObject (this=0x7fffffffde38, H=1)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h:317</div><div>#16 0x00000000010c7bda in (anonymous namespace)::RemoteObjectLayer_RemoveObjectFailure_Test::TestBody (this=0x2b519c0)</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp:315</div><div>#17 0x00000000019e58ce in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (object=0x2b519c0, method=&virtual testing::Test::TestBody(), location=0x3e1861 "the test body")</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2402</div><div>#18 0x00000000019d7012 in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=0x2b519c0, method=&virtual testing::Test::TestBody(), location=0x3e1861 "the test body")</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2455</div><div>#19 0x00000000019c53e6 in testing::Test::Run (this=0x2b519c0) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2474</div><div>#20 0x00000000019c5c2d in testing::TestInfo::Run (this=0x2b33550) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2656</div><div>#21 0x00000000019c617c in testing::TestCase::Run (this=0x2b32f00) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2774</div><div>#22 0x00000000019cb6b1 in testing::internal::UnitTestImpl::RunAllTests (this=0x2b31210) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:4649</div><div>#23 0x00000000019e7f0e in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x2b31210,</div><div>    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x19cb3d0 <testing::internal::UnitTestImpl::RunAllTests()>, location=0x3e1fdc "auxiliary test code (environments or event listeners)")</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2402</div><div>#24 0x00000000019d8a22 in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x2b31210,</div><div>    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x19cb3d0 <testing::internal::UnitTestImpl::RunAllTests()>, location=0x3e1fdc "auxiliary test code (environments or event listeners)")</div><div>    at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:2455</div><div>#25 0x00000000019cb3a2 in testing::UnitTest::Run (this=0x2b1be30 <testing::UnitTest::GetInstance()::instance>) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/src/gtest.cc:4257</div><div>#26 0x00000000019bdcb1 in RUN_ALL_TESTS () at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/googletest/include/gtest/gtest.h:2233</div><div>#27 0x00000000019bdc41 in main (argc=1, argv=0x7fffffffe618) at /home/bb/bootstrap-clang-libcxx-lld-i686-linux/llvm-project/llvm/utils/unittest/UnitTestMain/TestMain.cpp:51</div></div><div><br></div><div><br></div></div><div class="m_-2684236302260965259m_-3452541299801939580HOEnZb"><div class="m_-2684236302260965259m_-3452541299801939580h5"><br><div class="gmail_quote"><div dir="ltr">On Tue, Sep 5, 2017 at 12:35 PM Lang Hames via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lhames<br>
Date: Mon Sep  4 20:34:09 2017<br>
New Revision: 312511<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=312511&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=312511&view=rev</a><br>
Log:<br>
[ORC] Add a pair of ORC layers that forward object-layer operations via RPC.<br>
<br>
This patch introduces RemoteObjectClientLayer and RemoteObjectServerLayer,<br>
which can be used to forward ORC object-layer operations from a JIT stack in<br>
the client to a JIT stack (consisting only of object-layers) in the server.<br>
<br>
This is a new way to support remote-JITing in LLVM. The previous approach<br>
(supported by OrcRemoteTargetClient and OrcRemoteTargetServer) used a<br>
remote-mapping memory manager that sat "beneath" the JIT stack and sent<br>
fully-relocated binary blobs to the server. The main advantage of the new<br>
approach is that relocatable objects can be cached on the server and re-used<br>
(if the code that they represent hasn't changed), whereas fully-relocated blobs<br>
can not (since the addresses they have been permanently bound to will change<br>
from run to run).<br>
<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h<br>
    llvm/trunk/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp<br>
Modified:<br>
    llvm/trunk/include/llvm/ExecutionEngine/JITSymbol.h<br>
    llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcError.h<br>
    llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h<br>
    llvm/trunk/lib/ExecutionEngine/Orc/OrcError.cpp<br>
    llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/JITSymbol.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITSymbol.h?rev=312511&r1=312510&r2=312511&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITSymbol.h?rev=312511&r1=312510&r2=312511&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/JITSymbol.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/JITSymbol.h Mon Sep  4 20:34:09 2017<br>
@@ -89,9 +89,15 @@ public:<br>
   /// @brief Implicitly convert to the underlying flags type.<br>
   operator UnderlyingType&() { return Flags; }<br>
<br>
+  /// @brief Implicitly convert to the underlying flags type.<br>
+  operator const UnderlyingType&() const { return Flags; }<br>
+<br>
   /// @brief Return a reference to the target-specific flags.<br>
   TargetFlagsType& getTargetFlags() { return TargetFlags; }<br>
<br>
+  /// @brief Return a reference to the target-specific flags.<br>
+  const TargetFlagsType& getTargetFlags() const { return TargetFlags; }<br>
+<br>
   /// Construct a JITSymbolFlags value based on the flags of the given global<br>
   /// value.<br>
   static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcError.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcError.h?rev=312511&r1=312510&r2=312511&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcError.h?rev=312511&r1=312510&r2=312511&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcError.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcError.h Mon Sep  4 20:34:09 2017<br>
@@ -33,7 +33,8 @@ enum class OrcErrorCode : int {<br>
   RPCResponseAbandoned,<br>
   UnexpectedRPCCall,<br>
   UnexpectedRPCResponse,<br>
-  UnknownErrorCodeFromRemote<br>
+  UnknownErrorCodeFromRemote,<br>
+  UnknownResourceHandle<br>
 };<br>
<br>
 std::error_code orcError(OrcErrorCode ErrCode);<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h?rev=312511&r1=312510&r2=312511&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h?rev=312511&r1=312510&r2=312511&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h Mon Sep  4 20:34:09 2017<br>
@@ -25,6 +25,37 @@ namespace orc {<br>
<br>
 namespace remote {<br>
<br>
+/// Template error for missing resources.<br>
+template <typename ResourceIdT><br>
+class ResourceNotFound<br>
+  : public ErrorInfo<ResourceNotFound<ResourceIdT>> {<br>
+public:<br>
+  static char ID;<br>
+<br>
+  ResourceNotFound(ResourceIdT ResourceId,<br>
+                   std::string ResourceDescription = "")<br>
+    : ResourceId(std::move(ResourceId)),<br>
+      ResourceDescription(std::move(ResourceDescription)) {}<br>
+<br>
+  std::error_code convertToErrorCode() const override {<br>
+    return orcError(OrcErrorCode::UnknownResourceHandle);<br>
+  }<br>
+<br>
+  void log(raw_ostream &OS) const override {<br>
+    OS << (ResourceDescription.empty()<br>
+             ? "Remote resource with id "<br>
+               : ResourceDescription)<br>
+       << " " << ResourceId << " not found";<br>
+  }<br>
+<br>
+private:<br>
+  ResourceIdT ResourceId;<br>
+  std::string ResourceDescription;<br>
+};<br>
+<br>
+template <typename ResourceIdT><br>
+char ResourceNotFound<ResourceIdT>::ID = 0;<br>
+<br>
 class DirectBufferWriter {<br>
 public:<br>
   DirectBufferWriter() = default;<br>
@@ -45,6 +76,32 @@ private:<br>
<br>
 namespace rpc {<br>
<br>
+template <><br>
+class RPCTypeName<JITSymbolFlags> {<br>
+public:<br>
+  static const char *getName() { return "JITSymbolFlags"; }<br>
+};<br>
+<br>
+template <typename ChannelT><br>
+class SerializationTraits<ChannelT, JITSymbolFlags> {<br>
+public:<br>
+<br>
+  static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) {<br>
+    return serializeSeq(C, static_cast<JITSymbolFlags::UnderlyingType>(Flags),<br>
+                        Flags.getTargetFlags());<br>
+  }<br>
+<br>
+  static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) {<br>
+    JITSymbolFlags::UnderlyingType JITFlags;<br>
+    JITSymbolFlags::TargetFlagsType TargetFlags;<br>
+    if (auto Err = deserializeSeq(C, JITFlags, TargetFlags))<br>
+      return Err;<br>
+    Flags = JITSymbolFlags(static_cast<JITSymbolFlags::FlagNames>(JITFlags),<br>
+                           TargetFlags);<br>
+    return Error::success();<br>
+  }<br>
+};<br>
+<br>
 template <> class RPCTypeName<remote::DirectBufferWriter> {<br>
 public:<br>
   static const char *getName() { return "DirectBufferWriter"; }<br>
<br>
Added: llvm/trunk/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h?rev=312511&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h?rev=312511&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h (added)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h Mon Sep  4 20:34:09 2017<br>
@@ -0,0 +1,498 @@<br>
+//===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Forwards objects to a remote object layer via RPC.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H<br>
+#define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H<br>
+<br>
+#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"<br>
+#include "llvm/Object/ObjectFile.h"<br>
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"<br>
+#include <map><br>
+<br>
+namespace llvm {<br>
+namespace orc {<br>
+<br>
+/// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.<br>
+class RemoteObjectLayerAPI {<br>
+public:<br>
+<br>
+  using ObjHandleT = remote::ResourceIdMgr::ResourceId;<br>
+<br>
+protected:<br>
+<br>
+  using RemoteSymbolId = remote::ResourceIdMgr::ResourceId;<br>
+  using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;<br>
+<br>
+public:<br>
+<br>
+  using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>;<br>
+  using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>;<br>
+<br>
+protected:<br>
+<br>
+  static const ObjHandleT InvalidObjectHandleId = 0;<br>
+  static const RemoteSymbolId NullSymbolId = 0;<br>
+<br>
+  class AddObject<br>
+    : public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> {<br>
+  public:<br>
+    static const char *getName() { return "AddObject"; }<br>
+  };<br>
+<br>
+  class RemoveObject<br>
+    : public rpc::Function<RemoveObject, Error(ObjHandleT)> {<br>
+  public:<br>
+    static const char *getName() { return "RemoveObject"; }<br>
+  };<br>
+<br>
+  class FindSymbol<br>
+    : public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string,<br>
+                                                              bool)> {<br>
+  public:<br>
+    static const char *getName() { return "FindSymbol"; }<br>
+  };<br>
+<br>
+  class FindSymbolIn<br>
+    : public rpc::Function<FindSymbolIn,<br>
+                           Expected<RemoteSymbol>(ObjHandleT, std::string,<br>
+                                                  bool)> {<br>
+  public:<br>
+    static const char *getName() { return "FindSymbolIn"; }<br>
+  };<br>
+<br>
+  class EmitAndFinalize<br>
+    : public rpc::Function<EmitAndFinalize,<br>
+                           Error(ObjHandleT)> {<br>
+  public:<br>
+    static const char *getName() { return "EmitAndFinalize"; }<br>
+  };<br>
+<br>
+  class Lookup<br>
+    : public rpc::Function<Lookup,<br>
+                           Expected<RemoteSymbol>(ObjHandleT, std::string)> {<br>
+  public:<br>
+    static const char *getName() { return "Lookup"; }<br>
+  };<br>
+<br>
+  class LookupInLogicalDylib<br>
+    : public rpc::Function<LookupInLogicalDylib,<br>
+                           Expected<RemoteSymbol>(ObjHandleT, std::string)> {<br>
+  public:<br>
+    static const char *getName() { return "LookupInLogicalDylib"; }<br>
+  };<br>
+<br>
+  class ReleaseRemoteSymbol<br>
+    : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {<br>
+  public:<br>
+    static const char *getName() { return "ReleaseRemoteSymbol"; }<br>
+  };<br>
+<br>
+  class MaterializeRemoteSymbol<br>
+    : public rpc::Function<MaterializeRemoteSymbol,<br>
+                           Expected<JITTargetAddress>(RemoteSymbolId)> {<br>
+  public:<br>
+    static const char *getName() { return "MaterializeRemoteSymbol"; }<br>
+  };<br>
+};<br>
+<br>
+/// Base class containing common utilities for RemoteObjectClientLayer and<br>
+/// RemoteObjectServerLayer.<br>
+template <typename RPCEndpoint><br>
+class RemoteObjectLayer : public RemoteObjectLayerAPI {<br>
+public:<br>
+<br>
+  RemoteObjectLayer(RPCEndpoint &Remote,<br>
+                    std::function<void(Error)> ReportError)<br>
+      : Remote(Remote), ReportError(std::move(ReportError)),<br>
+        SymbolIdMgr(NullSymbolId + 1) {<br>
+    using ThisT = RemoteObjectLayer<RPCEndpoint>;<br>
+    Remote.template addHandler<ReleaseRemoteSymbol>(<br>
+             *this, &ThisT::handleReleaseRemoteSymbol);<br>
+    Remote.template addHandler<MaterializeRemoteSymbol>(<br>
+             *this, &ThisT::handleMaterializeRemoteSymbol);<br>
+  }<br>
+<br>
+protected:<br>
+<br>
+  class RemoteSymbolMaterializer {<br>
+  public:<br>
+<br>
+    RemoteSymbolMaterializer(RemoteObjectLayer &C,<br>
+                             RemoteSymbolId Id)<br>
+      : C(C), Id(Id) {}<br>
+<br>
+    RemoteSymbolMaterializer(const RemoteSymbolMaterializer &Other)<br>
+      : C(Other.C), Id(Other.Id) {<br>
+      // FIXME: This is a horrible, auto_ptr-style, copy-as-move operation.<br>
+      //        It should be removed as soon as LLVM has C++14's generalized<br>
+      //        lambda capture (at which point the materializer can be moved<br>
+      //        into the lambda in remoteToJITSymbol below).<br>
+      const_cast<RemoteSymbolMaterializer&>(Other).Id = 0;<br>
+    }<br>
+<br>
+    RemoteSymbolMaterializer&<br>
+    operator=(const RemoteSymbolMaterializer&) = delete;<br>
+<br>
+    ~RemoteSymbolMaterializer() {<br>
+      if (Id)<br>
+        C.releaseRemoteSymbol(Id);<br>
+    }<br>
+<br>
+    Expected<JITTargetAddress> materialize() {<br>
+      auto Addr = C.materializeRemoteSymbol(Id);<br>
+      Id = 0;<br>
+      return Addr;<br>
+    }<br>
+<br>
+  private:<br>
+    RemoteObjectLayer &C;<br>
+    RemoteSymbolId Id;<br>
+  };<br>
+<br>
+  RemoteSymbol nullRemoteSymbol() {<br>
+    return RemoteSymbol(0, JITSymbolFlags());<br>
+  }<br>
+<br>
+  // Creates a StringError that contains a copy of Err's log message, then<br>
+  // sends that StringError to ReportError.<br>
+  //<br>
+  // This allows us to locally log error messages for errors that will actually<br>
+  // be delivered to the remote.<br>
+  Error teeLog(Error Err) {<br>
+    return handleErrors(std::move(Err),<br>
+                        [this](std::unique_ptr<ErrorInfoBase> EIB) {<br>
+                          ReportError(make_error<StringError>(<br>
+                                        EIB->message(),<br>
+                                        EIB->convertToErrorCode()));<br>
+                          return Error(std::move(EIB));<br>
+                        });<br>
+  }<br>
+<br>
+  Error badRemoteSymbolIdError(RemoteSymbolId Id) {<br>
+    return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");<br>
+  }<br>
+<br>
+  Error badObjectHandleError(ObjHandleT H) {<br>
+    return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(<br>
+             H, "Bad object handle");<br>
+  }<br>
+<br>
+  Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {<br>
+    if (Sym) {<br>
+      auto Id = SymbolIdMgr.getNext();<br>
+      auto Flags = Sym.getFlags();<br>
+      assert(!InUseSymbols.count(Id) && "Symbol id already in use");<br>
+      InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));<br>
+      return RemoteSymbol(Id, Flags);<br>
+    } else if (auto Err = Sym.takeError())<br>
+      return teeLog(std::move(Err));<br>
+    // else...<br>
+    return nullRemoteSymbol();<br>
+  }<br>
+<br>
+  JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {<br>
+    if (RemoteSymOrErr) {<br>
+      auto &RemoteSym = *RemoteSymOrErr;<br>
+      RemoteSymbolMaterializer RSM(*this, RemoteSym.first);<br>
+      auto Sym =<br>
+        JITSymbol([RSM]() mutable { return RSM.materialize(); },<br>
+                  RemoteSym.second);<br>
+      return Sym;<br>
+    } else<br>
+      return RemoteSymOrErr.takeError();<br>
+  }<br>
+<br>
+  template <typename Func, typename... ArgTs><br>
+  using CallBResult = decltype(foldRemoteERror(<br>
+                                 std::declval<RPCEndpoint>()<br>
+                                   .template callB<Func>(<br>
+                                     std::declval<const ArgTs&>()...)));<br>
+<br>
+  /// API checked callB function.<br>
+  template <typename Func, typename... ArgTs><br>
+  CallBResult<Func> callB(const ArgTs &... Args) {<br>
+    return foldRemoteError(Remote.template callB<Func>(Args...));<br>
+  }<br>
+<br>
+  RPCEndpoint &Remote;<br>
+  std::function<void(Error)> ReportError;<br>
+<br>
+private:<br>
+<br>
+  void releaseRemoteSymbol(RemoteSymbolId Id) {<br>
+    if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))<br>
+      ReportError(std::move(Err));<br>
+  }<br>
+<br>
+  Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {<br>
+    return Remote.template callB<MaterializeRemoteSymbol>(Id);<br>
+  }<br>
+<br>
+  Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {<br>
+    auto SI = InUseSymbols.find(Id);<br>
+    if (SI != InUseSymbols.end()) {<br>
+      InUseSymbols.erase(SI);<br>
+      return Error::success();<br>
+    } else<br>
+      return teeLog(badRemoteSymbolIdError(Id));<br>
+  }<br>
+<br>
+  Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {<br>
+    auto SI = InUseSymbols.find(Id);<br>
+    if (SI != InUseSymbols.end()) {<br>
+      auto AddrOrErr = SI->second.getAddress();<br>
+      InUseSymbols.erase(SI);<br>
+      SymbolIdMgr.release(Id);<br>
+      if (AddrOrErr)<br>
+        return *AddrOrErr;<br>
+      else<br>
+        return teeLog(AddrOrErr.takeError());<br>
+    } else {<br>
+      return teeLog(badRemoteSymbolIdError(Id));<br>
+    }<br>
+  }<br>
+<br>
+  remote::ResourceIdMgr SymbolIdMgr;<br>
+  std::map<RemoteSymbolId, JITSymbol> InUseSymbols;<br>
+};<br>
+<br>
+template <typename RPCEndpoint><br>
+class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {<br>
+private:<br>
+<br>
+  using AddObject = RemoteObjectLayerAPI::AddObject;<br>
+  using RemoveObject = RemoteObjectLayerAPI::RemoveObject;<br>
+  using FindSymbol = RemoteObjectLayerAPI::FindSymbol;<br>
+  using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;<br>
+  using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;<br>
+  using Lookup = RemoteObjectLayerAPI::Lookup;<br>
+  using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;<br>
+<br>
+  using RemoteObjectLayer<RPCEndpoint>::teeLog;<br>
+  using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;<br>
+  using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;<br>
+<br>
+public:<br>
+<br>
+  using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;<br>
+  using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;<br>
+<br>
+  using ObjectPtr =<br>
+    std::shared_ptr<object::OwningBinary<object::ObjectFile>>;<br>
+<br>
+  RemoteObjectClientLayer(RPCEndpoint &Remote,<br>
+                          std::function<void(Error)> ReportError)<br>
+      : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {<br>
+    using ThisT = RemoteObjectClientLayer<RPCEndpoint>;<br>
+    Remote.template addHandler<Lookup>(*this, &ThisT::lookup);<br>
+    Remote.template addHandler<LookupInLogicalDylib>(<br>
+            *this, &ThisT::lookupInLogicalDylib);<br>
+  }<br>
+<br>
+  Expected<ObjHandleT><br>
+  addObject(ObjectPtr Object, std::shared_ptr<JITSymbolResolver> Resolver) {<br>
+    StringRef ObjBuffer = Object->getBinary()->getData();<br>
+    if (auto HandleOrErr =<br>
+          this->Remote.template callB<AddObject>(ObjBuffer)) {<br>
+      auto &Handle = *HandleOrErr;<br>
+      // FIXME: Return an error for this:<br>
+      assert(!Resolvers.count(Handle) && "Handle already in use?");<br>
+      Resolvers[Handle] = std::move(Resolver);<br>
+      return Handle;<br>
+    } else<br>
+      return HandleOrErr.takeError();<br>
+  }<br>
+<br>
+  Error removeObject(ObjHandleT H) {<br>
+    return this->Remote.template callB<RemoveObject>(H);<br>
+  }<br>
+<br>
+  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {<br>
+    return remoteToJITSymbol(<br>
+             this->Remote.template callB<FindSymbol>(Name,<br>
+                                                     ExportedSymbolsOnly));<br>
+  }<br>
+<br>
+  JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {<br>
+    return remoteToJITSymbol(<br>
+             this->Remote.template callB<FindSymbolIn>(H, Name,<br>
+                                                       ExportedSymbolsOnly));<br>
+  }<br>
+<br>
+  Error emitAndFinalize(ObjHandleT H) {<br>
+    return this->Remote.template callB<EmitAndFinalize>(H);<br>
+  }<br>
+<br>
+private:<br>
+<br>
+  Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {<br>
+    auto RI = Resolvers.find(H);<br>
+    if (RI != Resolvers.end()) {<br>
+      return this->jitSymbolToRemote(RI->second->findSymbol(Name));<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H));<br>
+  }<br>
+<br>
+  Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,<br>
+                                              const std::string &Name) {<br>
+    auto RI = Resolvers.find(H);<br>
+    if (RI != Resolvers.end())<br>
+      return this->jitSymbolToRemote(<br>
+               RI->second->findSymbolInLogicalDylib(Name));<br>
+    else<br>
+      return teeLog(badObjectHandleError(H));<br>
+  }<br>
+<br>
+  std::map<remote::ResourceIdMgr::ResourceId,<br>
+           std::shared_ptr<JITSymbolResolver>> Resolvers;<br>
+};<br>
+<br>
+template <typename BaseLayerT, typename RPCEndpoint><br>
+class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {<br>
+private:<br>
+<br>
+  using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;<br>
+  using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;<br>
+<br>
+  using AddObject = RemoteObjectLayerAPI::AddObject;<br>
+  using RemoveObject = RemoteObjectLayerAPI::RemoveObject;<br>
+  using FindSymbol = RemoteObjectLayerAPI::FindSymbol;<br>
+  using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;<br>
+  using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;<br>
+  using Lookup = RemoteObjectLayerAPI::Lookup;<br>
+  using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;<br>
+<br>
+  using RemoteObjectLayer<RPCEndpoint>::teeLog;<br>
+  using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;<br>
+  using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;<br>
+<br>
+public:<br>
+<br>
+  RemoteObjectServerLayer(BaseLayerT &BaseLayer,<br>
+                          RPCEndpoint &Remote,<br>
+                          std::function<void(Error)> ReportError)<br>
+    : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),<br>
+      BaseLayer(BaseLayer), HandleIdMgr(1) {<br>
+    using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;<br>
+<br>
+    Remote.template addHandler<AddObject>(*this, &ThisT::addObject);<br>
+    Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);<br>
+    Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);<br>
+    Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);<br>
+    Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);<br>
+  }<br>
+<br>
+private:<br>
+<br>
+  class StringMemoryBuffer : public MemoryBuffer {<br>
+  public:<br>
+    StringMemoryBuffer(std::string Buffer)<br>
+      : Buffer(std::move(Buffer)) {<br>
+      init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),<br>
+           false);<br>
+    }<br>
+<br>
+    BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }<br>
+  private:<br>
+    std::string Buffer;<br>
+  };<br>
+<br>
+  JITSymbol lookup(ObjHandleT Id, const std::string &Name) {<br>
+    return remoteToJITSymbol(<br>
+             this->Remote.template callB<Lookup>(Id, Name));<br>
+  }<br>
+<br>
+  JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {<br>
+    return remoteToJITSymbol(<br>
+             this->Remote.template callB<LookupInLogicalDylib>(Id, Name));<br>
+  }<br>
+<br>
+  Expected<ObjHandleT> addObject(std::string ObjBuffer) {<br>
+    auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));<br>
+    if (auto ObjectOrErr =<br>
+          object::ObjectFile::createObjectFile(Buffer->getMemBufferRef())) {<br>
+      auto Object =<br>
+        std::make_shared<object::OwningBinary<object::ObjectFile>>(<br>
+          std::move(*ObjectOrErr), std::move(Buffer));<br>
+<br>
+      auto Id = HandleIdMgr.getNext();<br>
+      assert(!BaseLayerHandles.count(Id) && "Id already in use?");<br>
+<br>
+      auto Resolver =<br>
+        createLambdaResolver(<br>
+          [this, Id](const std::string &Name) { return lookup(Id, Name); },<br>
+          [this, Id](const std::string &Name) {<br>
+            return lookupInLogicalDylib(Id, Name);<br>
+          });<br>
+<br>
+      if (auto HandleOrErr =<br>
+          BaseLayer.addObject(std::move(Object), std::move(Resolver))) {<br>
+        BaseLayerHandles[Id] = std::move(*HandleOrErr);<br>
+        return Id;<br>
+      } else<br>
+        return teeLog(HandleOrErr.takeError());<br>
+    } else<br>
+      return teeLog(ObjectOrErr.takeError());<br>
+  }<br>
+<br>
+  Error removeObject(ObjHandleT H) {<br>
+    auto HI = BaseLayerHandles.find(H);<br>
+    if (HI != BaseLayerHandles.end()) {<br>
+      if (auto Err = BaseLayer.removeObject(HI->second))<br>
+        return teeLog(std::move(Err));<br>
+      return Error::success();<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H));<br>
+  }<br>
+<br>
+  Expected<RemoteSymbol> findSymbol(const std::string &Name,<br>
+                                    bool ExportedSymbolsOnly) {<br>
+    if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))<br>
+      return this->jitSymbolToRemote(std::move(Sym));<br>
+    else if (auto Err = Sym.takeError())<br>
+      return teeLog(std::move(Err));<br>
+    return this->nullRemoteSymbol();<br>
+  }<br>
+<br>
+  Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,<br>
+                                      bool ExportedSymbolsOnly) {<br>
+    auto HI = BaseLayerHandles.find(H);<br>
+    if (HI != BaseLayerHandles.end()) {<br>
+      if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))<br>
+        return this->jitSymbolToRemote(std::move(Sym));<br>
+      else if (auto Err = Sym.takeError())<br>
+        return teeLog(std::move(Err));<br>
+      return this->nullRemoteSymbol();<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H));<br>
+  }<br>
+<br>
+  Error emitAndFinalize(ObjHandleT H) {<br>
+    auto HI = BaseLayerHandles.find(H);<br>
+    if (HI != BaseLayerHandles.end()) {<br>
+      if (auto Err = BaseLayer.emitAndFinalize(HI->second))<br>
+        return teeLog(std::move(Err));<br>
+      return Error::success();<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H));<br>
+  }<br>
+<br>
+  BaseLayerT &BaseLayer;<br>
+  remote::ResourceIdMgr HandleIdMgr;<br>
+  std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;<br>
+};<br>
+<br>
+} // end namespace orc<br>
+} // end namespace llvm<br>
+<br>
+#endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H<br>
<br>
Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcError.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcError.cpp?rev=312511&r1=312510&r2=312511&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcError.cpp?rev=312511&r1=312510&r2=312511&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcError.cpp (original)<br>
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcError.cpp Mon Sep  4 20:34:09 2017<br>
@@ -54,6 +54,8 @@ public:<br>
     case OrcErrorCode::UnknownErrorCodeFromRemote:<br>
       return "Unknown error returned from remote RPC function "<br>
              "(Use StringError to get error message)";<br>
+    case OrcErrorCode::UnknownResourceHandle:<br>
+      return "Unknown resource handle";<br>
     }<br>
     llvm_unreachable("Unhandled error code");<br>
   }<br>
<br>
Modified: llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt?rev=312511&r1=312510&r2=312511&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt?rev=312511&r1=312510&r2=312511&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt (original)<br>
+++ llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt Mon Sep  4 20:34:09 2017<br>
@@ -18,6 +18,7 @@ add_llvm_unittest(OrcJITTests<br>
   OrcCAPITest.cpp<br>
   OrcTestCommon.cpp<br>
   QueueChannel.cpp<br>
+  RemoteObjectLayerTest.cpp<br>
   RPCUtilsTest.cpp<br>
   RTDyldObjectLinkingLayerTest.cpp<br>
   )<br>
<br>
Added: llvm/trunk/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp?rev=312511&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp?rev=312511&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp (added)<br>
+++ llvm/trunk/unittests/ExecutionEngine/Orc/RemoteObjectLayerTest.cpp Mon Sep  4 20:34:09 2017<br>
@@ -0,0 +1,576 @@<br>
+//===---------------------- RemoteObjectLayerTest.cpp ---------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"<br>
+#include "llvm/ExecutionEngine/Orc/NullResolver.h"<br>
+#include "llvm/ExecutionEngine/Orc/RemoteObjectLayer.h"<br>
+#include "OrcTestCommon.h"<br>
+#include "QueueChannel.h"<br>
+#include "gtest/gtest.h"<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::orc;<br>
+<br>
+namespace {<br>
+<br>
+class MockObjectLayer {<br>
+public:<br>
+<br>
+  using ObjHandleT = uint64_t;<br>
+<br>
+  using ObjectPtr =<br>
+    std::shared_ptr<object::OwningBinary<object::ObjectFile>>;<br>
+<br>
+  using LookupFn = std::function<JITSymbol(StringRef, bool)>;<br>
+  using SymbolLookupTable = std::map<ObjHandleT, LookupFn>;<br>
+<br>
+  using AddObjectFtor =<br>
+    std::function<Expected<ObjHandleT>(ObjectPtr, SymbolLookupTable&)>;<br>
+<br>
+  class ObjectNotFound : public remote::ResourceNotFound<ObjHandleT> {<br>
+  public:<br>
+    ObjectNotFound(ObjHandleT H) : ResourceNotFound(H, "Object handle") {}<br>
+  };<br>
+<br>
+  MockObjectLayer(AddObjectFtor AddObject)<br>
+    : AddObject(std::move(AddObject)) {}<br>
+<br>
+  Expected<ObjHandleT> addObject(ObjectPtr Obj,<br>
+            std::shared_ptr<JITSymbolResolver> Resolver) {<br>
+    return AddObject(Obj, SymTab);<br>
+  }<br>
+<br>
+  Error removeObject(ObjHandleT H) {<br>
+    if (SymTab.count(H))<br>
+      return Error::success();<br>
+    else<br>
+      return make_error<ObjectNotFound>(H);<br>
+  }<br>
+<br>
+  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {<br>
+    for (auto KV : SymTab) {<br>
+      if (auto Sym = KV.second(Name, ExportedSymbolsOnly))<br>
+        return Sym;<br>
+      else if (auto Err = Sym.takeError())<br>
+        return std::move(Err);<br>
+    }<br>
+    return JITSymbol(nullptr);<br>
+  }<br>
+<br>
+  JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,<br>
+                         bool ExportedSymbolsOnly) {<br>
+    auto LI = SymTab.find(H);<br>
+    if (LI != SymTab.end())<br>
+      return LI->second(Name, ExportedSymbolsOnly);<br>
+    else<br>
+      return make_error<ObjectNotFound>(H);<br>
+  }<br>
+<br>
+  Error emitAndFinalize(ObjHandleT H) {<br>
+    if (SymTab.count(H))<br>
+      return Error::success();<br>
+    else<br>
+      return make_error<ObjectNotFound>(H);<br>
+  }<br>
+<br>
+private:<br>
+  AddObjectFtor AddObject;<br>
+  SymbolLookupTable SymTab;<br>
+};<br>
+<br>
+using RPCEndpoint = rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>;<br>
+<br>
+MockObjectLayer::ObjectPtr createTestObject() {<br>
+  OrcNativeTarget::initialize();<br>
+  auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget());<br>
+<br>
+  if (!TM)<br>
+    return nullptr;<br>
+<br>
+  LLVMContext Ctx;<br>
+  ModuleBuilder MB(Ctx, TM->getTargetTriple().str(), "TestModule");<br>
+  MB.getModule()->setDataLayout(TM->createDataLayout());<br>
+  auto *Main = MB.createFunctionDecl<void(int, char**)>("main");<br>
+  Main->getBasicBlockList().push_back(BasicBlock::Create(Ctx));<br>
+  IRBuilder<> B(&Main->back());<br>
+  B.CreateRet(ConstantInt::getSigned(Type::getInt32Ty(Ctx), 42));<br>
+<br>
+  SimpleCompiler IRCompiler(*TM);<br>
+  return std::make_shared<object::OwningBinary<object::ObjectFile>>(<br>
+           IRCompiler(*MB.getModule()));<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, AddObject) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      logAllUnhandledErrors(std::move(Err), llvm::errs(), "");<br>
+    };<br>
+<br>
+  // Copy the bytes out of the test object: the copy will be used to verify<br>
+  // that the original is correctly transmitted over RPC to the mock layer.<br>
+  StringRef ObjBytes = TestObject->getBinary()->getData();<br>
+  std::vector<char> ObjContents(ObjBytes.size());<br>
+  std::copy(ObjBytes.begin(), ObjBytes.end(), ObjContents.begin());<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+  MockObjectLayer BaseLayer(<br>
+    [&ObjContents](MockObjectLayer::ObjectPtr Obj,<br>
+                   MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+<br>
+      // Check that the received object file content matches the original.<br>
+      StringRef RPCObjContents = Obj->getBinary()->getData();<br>
+      EXPECT_EQ(RPCObjContents.size(), ObjContents.size())<br>
+        << "RPC'd object file has incorrect size";<br>
+      EXPECT_TRUE(std::equal(RPCObjContents.begin(), RPCObjContents.end(),<br>
+                             ObjContents.begin()))<br>
+        << "RPC'd object file content does not match original content";<br>
+<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  cantFail(Client.addObject(std::move(TestObject),<br>
+                            std::make_shared<NullResolver>()));<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, AddObjectFailure) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      auto ErrMsg = toString(std::move(Err));<br>
+      EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")<br>
+        << "Expected error string to be \"AddObjectFailure - Test Message\"";<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab)<br>
+        -> Expected<MockObjectLayer::ObjHandleT> {<br>
+      return make_error<StringError>("AddObjectFailure - Test Message",<br>
+                                     inconvertibleErrorCode());<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  auto HandleOrErr =<br>
+    Client.addObject(std::move(TestObject), std::make_shared<NullResolver>());<br>
+<br>
+  EXPECT_FALSE(HandleOrErr) << "Expected error from addObject";<br>
+<br>
+  auto ErrMsg = toString(HandleOrErr.takeError());<br>
+  EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")<br>
+    << "Expected error string to be \"AddObjectFailure - Test Message\"";<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+<br>
+TEST(RemoteObjectLayer, RemoveObject) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      logAllUnhandledErrors(std::move(Err), llvm::errs(), "");<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+      SymTab[1] = MockObjectLayer::LookupFn();<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  auto H  = cantFail(Client.addObject(std::move(TestObject),<br>
+                                      std::make_shared<NullResolver>()));<br>
+<br>
+  cantFail(Client.removeObject(H));<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, RemoveObjectFailure) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      auto ErrMsg = toString(std::move(Err));<br>
+      EXPECT_EQ(ErrMsg, "Object handle 42 not found")<br>
+        << "Expected error string to be \"Object handle 42 not found\"";<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  // AddObject lambda does not update symbol table, so removeObject will treat<br>
+  // this as a bad object handle.<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+      return 42;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  auto H  = cantFail(Client.addObject(std::move(TestObject),<br>
+                                      std::make_shared<NullResolver>()));<br>
+<br>
+  auto Err = Client.removeObject(H);<br>
+  EXPECT_TRUE(!!Err) << "Expected error from removeObject";<br>
+<br>
+  auto ErrMsg = toString(std::move(Err));<br>
+  EXPECT_EQ(ErrMsg, "Object handle 42 not found")<br>
+    << "Expected error string to be \"Object handle 42 not found\"";<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, FindSymbol) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      auto ErrMsg = toString(std::move(Err));<br>
+      EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")<br>
+        << "Expected error string to be \"Object handle 42 not found\"";<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  // AddObject lambda does not update symbol table, so removeObject will treat<br>
+  // this as a bad object handle.<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+      SymTab[42] =<br>
+        [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {<br>
+          if (Name == "foobar")<br>
+            return JITSymbol(0x12348765, JITSymbolFlags::Exported);<br>
+          return make_error<JITSymbolNotFound>(Name);<br>
+        };<br>
+      return 42;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  cantFail(Client.addObject(std::move(TestObject),<br>
+                            std::make_shared<NullResolver>()));<br>
+<br>
+  auto Sym1 = Client.findSymbol("foobar", true);<br>
+<br>
+  EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";<br>
+  EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)<br>
+    << "Symbol 'foobar' does not return the correct address";<br>
+<br>
+  auto Sym2 = Client.findSymbol("barbaz", true);<br>
+  EXPECT_FALSE(!!Sym2) << "Symbol 'barbaz' should not be findable";<br>
+  auto Err = Sym2.takeError();<br>
+  EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";<br>
+  auto ErrMsg = toString(std::move(Err));<br>
+  EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")<br>
+    << "Expected symbol-not-found error for Sym2";<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, FindSymbolIn) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      auto ErrMsg = toString(std::move(Err));<br>
+      EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")<br>
+        << "Expected error string to be \"Object handle 42 not found\"";<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  // AddObject lambda does not update symbol table, so removeObject will treat<br>
+  // this as a bad object handle.<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+      SymTab[42] =<br>
+        [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {<br>
+          if (Name == "foobar")<br>
+            return JITSymbol(0x12348765, JITSymbolFlags::Exported);<br>
+          return make_error<JITSymbolNotFound>(Name);<br>
+        };<br>
+      // Dummy symbol table entry - this should not be visible to<br>
+      // findSymbolIn.<br>
+      SymTab[43] =<br>
+        [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {<br>
+          if (Name == "barbaz")<br>
+            return JITSymbol(0xdeadbeef, JITSymbolFlags::Exported);<br>
+          return make_error<JITSymbolNotFound>(Name);<br>
+        };<br>
+<br>
+      return 42;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  auto H = cantFail(Client.addObject(std::move(TestObject),<br>
+                                     std::make_shared<NullResolver>()));<br>
+<br>
+  auto Sym1 = Client.findSymbolIn(H, "foobar", true);<br>
+<br>
+  EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";<br>
+  EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)<br>
+    << "Symbol 'foobar' does not return the correct address";<br>
+<br>
+  auto Sym2 = Client.findSymbolIn(H, "barbaz", true);<br>
+  EXPECT_FALSE(!!Sym2) << "Symbol 'barbaz' should not be findable";<br>
+  auto Err = Sym2.takeError();<br>
+  EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";<br>
+  auto ErrMsg = toString(std::move(Err));<br>
+  EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")<br>
+    << "Expected symbol-not-found error for Sym2";<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, EmitAndFinalize) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      logAllUnhandledErrors(std::move(Err), llvm::errs(), "");<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+      SymTab[1] = MockObjectLayer::LookupFn();<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  auto H = cantFail(Client.addObject(std::move(TestObject),<br>
+                                     std::make_shared<NullResolver>()));<br>
+<br>
+  auto Err = Client.emitAndFinalize(H);<br>
+  EXPECT_FALSE(!!Err) << "emitAndFinalize should work";<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, EmitAndFinalizeFailure) {<br>
+  llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();<br>
+  auto TestObject = createTestObject();<br>
+  if (!TestObject)<br>
+    return;<br>
+<br>
+  auto Channels = createPairedQueueChannels();<br>
+<br>
+  auto ReportError =<br>
+    [](Error Err) {<br>
+      auto ErrMsg = toString(std::move(Err));<br>
+      EXPECT_EQ(ErrMsg, "Object handle 1 not found")<br>
+        << "Expected bad handle error";<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEndpoint> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookupTable &SymTab) {<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::utils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne());<br>
+    });<br>
+<br>
+  auto H = cantFail(Client.addObject(std::move(TestObject),<br>
+                                     std::make_shared<NullResolver>()));<br>
+<br>
+  auto Err = Client.emitAndFinalize(H);<br>
+  EXPECT_TRUE(!!Err) << "emitAndFinalize should work";<br>
+<br>
+  auto ErrMsg = toString(std::move(Err));<br>
+  EXPECT_EQ(ErrMsg, "Object handle 1 not found")<br>
+    << "emitAndFinalize returned incorrect error";<br>
+<br>
+  cantFail(ClientEP.callB<remote::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<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>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</blockquote></div>