<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="HOEnZb"><div class="h5"><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/boot<wbr>strap-clang-libcxx-lld-i686-<wbr>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/linu<wbr>x/x86_64/lowlevellock.S:135</div><div>#1  0x00007ffff7bc6649 in _L_lock_909 () from /lib/x86_64-linux-gnu/libpthre<wbr>ad.so.0</div><div>#2  0x00007ffff7bc6470 in __GI___pthread_mutex_lock (mutex=0x294c080 <llvm::orc::rpc::Serialization<wbr>Traits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>) at ../nptl/pthread_mutex_lock.c:7<wbr>9</div><div>#3  0x00000000010ba243 in __gthread_mutex_lock (__mutex=0x294c080 <llvm::orc::rpc::Serialization<wbr>Traits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/x86_64<wbr>-linux-gnu/c++/4.8/bits/gthr-<wbr>default.h:748</div><div>#4  0x00000000010ba215 in __gthread_recursive_mutex_lock (__mutex=0x294c080 <llvm::orc::rpc::Serialization<wbr>Traits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/x86_64<wbr>-linux-gnu/c++/4.8/bits/gthr-<wbr>default.h:810</div><div>#5  0x00000000010d77d5 in std::recursive_mutex::lock (this=0x294c080 <llvm::orc::rpc::Serialization<wbr>Traits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::SerializersMutex>)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/mutex:175</div><div>#6  0x00000000010d74d3 in std::lock_guard<std::recursive<wbr>_mutex>::lock_guard (this=0x7ffff6783888, __m=...) at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/mutex:414</div><div>#7  0x00000000010eb461 in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&) (C=...,</div><div>    Err=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x31a25d>)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:375</div><div>#8  0x00000000010ebabd in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serializeAsStringError (C=..., EIB=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:415</div><div>#9  0x00000000010eb9b6 in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}::operator()(llvm::E<wbr>rrorInfoBase const&) const (this=0x7ffff6783af8, EIB=...) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:384</div><div>#10 0x00000000010eb91d in llvm::ErrorHandlerTraits<llvm:<wbr>:Error (&)(llvm::ErrorInfoBase&)>::ap<wbr>ply<llvm::orc::rpc::Serializat<wbr>ionTraits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}>(llvm::orc::rpc::Se<wbr>rializationTraits<llvm::orc::<wbr>rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}&&, std::unique_ptr<llvm::ErrorInf<wbr>oBase, std::default_delete<llvm::Erro<wbr>rInfoBase> >) (</div><div>    H=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x31a33f>, E=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/Support/<wbr>Error.h:752</div><div>#11 0x00000000010eb82b in llvm::handleErrorImpl<llvm::or<wbr>c::rpc::SerializationTraits<ll<wbr>vm::orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}>(std::unique_ptr<ll<wbr>vm::ErrorInfoBase, std::default_delete<llvm::Erro<wbr>rInfoBase> >, llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}&&) (Payload=..., Handler=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x284ec1>)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/Support/<wbr>Error.h:844</div><div>#12 0x00000000010eb740 in llvm::handleErrors<llvm::orc::<wbr>rpc::SerializationTraits<llvm:<wbr>:orc::rpc::RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}>(llvm::Error, llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&)::{lambda(llvm::<wbr>ErrorInfoBase const&)#1}&&) (E=...,</div><div>    Hs=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x284dec>)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/Support/<wbr>Error.h:873</div><div>#13 0x00000000010eb4d7 in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::serialize(llvm::orc::rp<wbr>c::RawByteChannel&, llvm::Error&&) (C=...,</div><div>    Err=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x31a25d>)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:380</div><div>#14 0x00000000010eb41f in llvm::orc::rpc::SequenceSerial<wbr>ization<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error>::serialize<llvm::<wbr>Error>(llvm::orc::rpc::RawByte<wbr>Channel&, llvm::Error&&) (C=...,</div><div>    CArg=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x31a221>)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:277</div><div>#15 0x00000000010eb3bf in llvm::orc::rpc::serializeSeq<l<wbr>lvm::orc::rpc::RawByteChannel, llvm::Error>(llvm::orc::rpc::R<wbr>awByteChannel&, llvm::Error&&) (C=...,</div><div>    Args=<unknown type in /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/builds/stagen<wbr>/unittests/ExecutionEngine/<wbr>Orc/OrcJITTests, CU 0x234b90, DIE 0x239991>)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:319</div><div>#16 0x00000000010eb284 in llvm::orc::rpc::detail::Respon<wbr>dHelper<true>::sendResult<<wbr>llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int> (C=..., ResponseId=@0x7fffffffdcd8: 1, SeqNo=0, Err=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:426</div><div>#17 0x00000000010ea480 in llvm::orc::rpc::detail::respon<wbr>d<llvm::Error, llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int> (C=..., ResponseId=@0x7fffffffdcd8: 1, SeqNo=0, Err=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:489</div><div>#18 0x00000000010be795 in std::function<llvm::Error (llvm::orc::rpc::RawByteChanne<wbr>l&, unsigned int)> llvm::orc::rpc::detail::RPCEnd<wbr>pointBase<llvm::orc::rpc::Sing<wbr>leThreadedRPCEndpoint<llvm::<wbr>orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int>::wrapHandler<llvm::orc::R<wbr>emoteObjectLayerAPI::RemoveObj<wbr>ect, llvm::orc::rpc::detail::Member<wbr>FnWrapper<llvm::orc::RemoteObj<wbr>ectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreaded<wbr>RPCEndpoint<llvm::orc::rpc::Ra<wbr>wByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long> >(llvm::orc::rpc::detail::Memb<wbr>erFnWrapper<llvm::orc::RemoteO<wbr>bjectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreaded<wbr>RPCEndpoint<llvm::orc::rpc::Ra<wbr>wByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long>)::{lambda(llvm::orc::rpc<wbr>::RawByteChannel&, unsigned int)#1}::operator()(llvm::orc:<wbr>:rpc::RawByteChannel&, unsigned int) (this=0x2bd0960, Channel=..., SeqNo=0) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:1342</div><div>#19 0x00000000010be497 in std::_Function_handler<llvm::E<wbr>rror (llvm::orc::rpc::RawByteChanne<wbr>l&, unsigned int), std::function<llvm::Error (llvm::orc::rpc::RawByteChanne<wbr>l&, unsigned int)> llvm::orc::rpc::detail::RPCEnd<wbr>pointBase<llvm::orc::rpc::Sing<wbr>leThreadedRPCEndpoint<llvm::<wbr>orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int>::wrapHandler<llvm::orc::R<wbr>emoteObjectLayerAPI::RemoveObj<wbr>ect, llvm::orc::rpc::detail::Member<wbr>FnWrapper<llvm::orc::RemoteObj<wbr>ectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreaded<wbr>RPCEndpoint<llvm::orc::rpc::Ra<wbr>wByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long> >(llvm::orc::rpc::detail::Memb<wbr>erFnWrapper<llvm::orc::RemoteO<wbr>bjectServerLayer<(anonymous namespace)::MockObjectLayer, llvm::orc::rpc::SingleThreaded<wbr>RPCEndpoint<llvm::orc::rpc::Ra<wbr>wByteChannel, unsigned int, unsigned int> >, llvm::Error, unsigned long>)::{lambda(llvm::orc::rpc<wbr>::RawByteChannel&, unsigned int)#1}>::_M_invoke(std::_Any_<wbr>data const&, llvm::orc::rpc::RawByteChannel<wbr>&, unsigned int) (__functor=..., __args=0, __args=0)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/functional:2056</div><div>#20 0x00000000010fbddd in std::function<llvm::Error (llvm::orc::rpc::RawByteChanne<wbr>l&, unsigned int)>::operator()(llvm::orc::r<wbr>pc::RawByteChannel&, unsigned int) const (this=0x2bd09b8, __args=0, __args=0)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/functional:2471</div><div>#21 0x00000000010f5984 in llvm::orc::rpc::detail::RPCEnd<wbr>pointBase<llvm::orc::rpc::Sing<wbr>leThreadedRPCEndpoint<llvm::<wbr>orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int>::handleOne (this=0x7fffffffdcc8) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:1140</div><div>#22 0x00000000010c9782 in (anonymous namespace)::RemoteObjectLayer_<wbr>RemoveObjectFailure_Test::Test<wbr>Body()::$_16::operator()() const (this=0x2b66398)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/unittests/ExecutionEngine<wbr>/Orc/RemoteObjectLayerTest.<wbr>cpp:309</div><div>#23 0x00000000010c9715 in std::_Bind_simple<(anonymous namespace)::RemoteObjectLayer_<wbr>RemoveObjectFailure_Test::Test<wbr>Body()::$_16 ()>::_M_invoke<>(std::_Index_t<wbr>uple<>) (this=0x2b66398)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/functional:1731</div><div>#24 0x00000000010c96e5 in std::_Bind_simple<(anonymous namespace)::RemoteObjectLayer_<wbr>RemoveObjectFailure_Test::Test<wbr>Body()::$_16 ()>::operator()() (this=0x2b66398)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/functional:1720</div><div>#25 0x00000000010c95a9 in std::thread::_Impl<std::_Bind_<wbr>simple<(anonymous namespace)::RemoteObjectLayer_<wbr>RemoveObjectFailure_Test::Test<wbr>Body()::$_16 ()> >::_M_run() (this=0x2b66380)</div><div>    at /usr/lib/gcc/x86_64-linux-gnu/<wbr>4.8/../../../../include/c++/4.<wbr>8/thread:115</div><div>#26 0x00007ffff6e15a40 in std::(anonymous namespace)::execute_native_thr<wbr>ead_routine (__p=<optimized out>) at ../../../../../src/libstdc++-v<wbr>3/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<wbr>_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/linu<wbr>x/x86_64/pthread_cond_wait.S:<wbr>185</div><div>#1  0x00007ffff6e124bc in __gthread_cond_wait (__mutex=<optimized out>, __cond=<optimized out>) at /build/buildd/gcc-4.8-4.8.4/bu<wbr>ild/x86_64-linux-gnu/libstdc++<wbr>-v3/include/x86_64-linux-gnu/<wbr>bits/gthr-default.h:864</div><div>#2  std::condition_variable::wait (this=<optimized out>, __lock=...) at ../../../../../src/libstdc++-v<wbr>3/src/c++11/condition_variable<wbr>.cc:52</div><div>#3  0x00000000010e109d in llvm::QueueChannel::readBytes (this=0x2b5d920, Dst=0x7fffffffd718 "", Size=8) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/unittests/ExecutionEngine<wbr>/Orc/QueueChannel.h:90</div><div>#4  0x00000000010d8bc4 in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, unsigned long, unsigned long, void>::deserialize (C=..., V=@0x7fffffffd718: 0)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RawByteChannel.h:105</div><div>#5  0x00000000010d8b74 in llvm::orc::rpc::SequenceSerial<wbr>ization<llvm::orc::rpc::<wbr>RawByteChannel, unsigned long>::deserialize<unsigned long> (C=..., CArg=@0x7fffffffd718: 0)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:284</div><div>#6  0x00000000010d8b44 in llvm::orc::rpc::deserializeSeq<wbr><llvm::orc::rpc::<wbr>RawByteChannel, unsigned long> (C=..., Args=@0x7fffffffd718: 0)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:325</div><div>#7  0x00000000010d8a57 in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, std::string, std::string, void>::deserialize (C=..., S=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RawByteChannel.h:174</div><div>#8  0x00000000010d8a14 in llvm::orc::rpc::SequenceSerial<wbr>ization<llvm::orc::rpc::<wbr>RawByteChannel, std::string>::deserialize<std:<wbr>:string> (C=..., CArg=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:284</div><div>#9  0x00000000010d88f4 in llvm::orc::rpc::deserializeSeq<wbr><llvm::orc::rpc::<wbr>RawByteChannel, std::string> (C=..., Args=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:325</div><div>#10 0x00000000010f997f in llvm::orc::rpc::SerializationT<wbr>raits<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::Error, void>::deserialize (C=..., Err=...)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCSerialization.h:393</div><div>#11 0x000000000110ed4d in llvm::orc::rpc::detail::Respon<wbr>seHandlerImpl<llvm::orc::rpc::<wbr>RawByteChannel, llvm::Error, llvm::orc::rpc::detail::Result<wbr>Traits<llvm::Error>::ErrorRetu<wbr>rnType llvm::orc::rpc::SingleThreaded<wbr>RPCEndpoint<llvm::orc::rpc::Ra<wbr>wByteChannel, unsigned int, unsigned int>::callB<llvm::orc::RemoteO<wbr>bjectLayerAPI::RemoveObject, unsigned long, llvm::Error>(unsigned long const&)::{lambda(llvm::Error)#<wbr>1}>::handleResponse(llvm::orc:<wbr>:rpc::RawByteChannel&) (</div><div>    this=0x2b80950, C=...) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:808</div><div>#12 0x00000000010fbc25 in llvm::orc::rpc::detail::RPCEnd<wbr>pointBase<llvm::orc::rpc::Sing<wbr>leThreadedRPCEndpoint<llvm::<wbr>orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int>::handleResponse (this=0x7fffffffdee0, SeqNo=0) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:1262</div><div>#13 0x00000000010f5916 in llvm::orc::rpc::detail::RPCEnd<wbr>pointBase<llvm::orc::rpc::Sing<wbr>leThreadedRPCEndpoint<llvm::<wbr>orc::rpc::RawByteChannel, unsigned int, unsigned int>, llvm::orc::rpc::RawByteChannel<wbr>, unsigned int, unsigned int>::handleOne (this=0x7fffffffdee0) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:1137</div><div>#14 0x000000000110e280 in llvm::orc::rpc::SingleThreaded<wbr>RPCEndpoint<llvm::orc::rpc::Ra<wbr>wByteChannel, unsigned int, unsigned int>::callB<llvm::orc::RemoteO<wbr>bjectLayerAPI::RemoveObject, unsigned long, llvm::Error> (this=0x7fffffffdee0,</div><div>    Args=@0x7fffffffda30: 1) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RPCUtils.h:1588</div><div>#15 0x000000000110d0aa in llvm::orc::RemoteObjectClientL<wbr>ayer<llvm::orc::rpc::SingleThr<wbr>eadedRPCEndpoint<llvm::orc::<wbr>rpc::RawByteChannel, unsigned int, unsigned int> >::removeObject (this=0x7fffffffde38, H=1)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/include/llvm/ExecutionEng<wbr>ine/Orc/RemoteObjectLayer.h:<wbr>317</div><div>#16 0x00000000010c7bda in (anonymous namespace)::RemoteObjectLayer_<wbr>RemoveObjectFailure_Test::Test<wbr>Body (this=0x2b519c0)</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/unittests/ExecutionEngine<wbr>/Orc/RemoteObjectLayerTest.<wbr>cpp:315</div><div>#17 0x00000000019e58ce in testing::internal::HandleSehEx<wbr>ceptionsInMethodIfSupported<<wbr>testing::Test, void> (object=0x2b519c0, method=&virtual testing::Test::TestBody(), location=0x3e1861 "the test body")</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2402</div><div>#18 0x00000000019d7012 in testing::internal::HandleExcep<wbr>tionsInMethodIfSupported<<wbr>testing::Test, void> (object=0x2b519c0, method=&virtual testing::Test::TestBody(), location=0x3e1861 "the test body")</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2455</div><div>#19 0x00000000019c53e6 in testing::Test::Run (this=0x2b519c0) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2474</div><div>#20 0x00000000019c5c2d in testing::TestInfo::Run (this=0x2b33550) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2656</div><div>#21 0x00000000019c617c in testing::TestCase::Run (this=0x2b32f00) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2774</div><div>#22 0x00000000019cb6b1 in testing::internal::UnitTestImp<wbr>l::RunAllTests (this=0x2b31210) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:4649</div><div>#23 0x00000000019e7f0e in testing::internal::HandleSehEx<wbr>ceptionsInMethodIfSupported<<wbr>testing::internal::UnitTestImp<wbr>l, bool> (object=0x2b31210,</div><div>    method=(bool (testing::internal::UnitTestIm<wbr>pl::*)(testing::internal::<wbr>UnitTestImpl * const)) 0x19cb3d0 <testing::internal::UnitTestIm<wbr>pl::RunAllTests()>, location=0x3e1fdc "auxiliary test code (environments or event listeners)")</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2402</div><div>#24 0x00000000019d8a22 in testing::internal::HandleExcep<wbr>tionsInMethodIfSupported<<wbr>testing::internal::UnitTestImp<wbr>l, bool> (object=0x2b31210,</div><div>    method=(bool (testing::internal::UnitTestIm<wbr>pl::*)(testing::internal::<wbr>UnitTestImpl * const)) 0x19cb3d0 <testing::internal::UnitTestIm<wbr>pl::RunAllTests()>, location=0x3e1fdc "auxiliary test code (environments or event listeners)")</div><div>    at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:2455</div><div>#25 0x00000000019cb3a2 in testing::UnitTest::Run (this=0x2b1be30 <testing::UnitTest::GetInstanc<wbr>e()::instance>) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/src/gtest.cc:4257</div><div>#26 0x00000000019bdcb1 in RUN_ALL_TESTS () at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/googletest<wbr>/include/gtest/gtest.h:2233</div><div>#27 0x00000000019bdc41 in main (argc=1, argv=0x7fffffffe618) at /home/bb/bootstrap-clang-libcx<wbr>x-lld-i686-linux/llvm-project/<wbr>llvm/utils/unittest/UnitTestMa<wbr>in/TestMain.cpp:51</div></div><div><br></div><div><br></div></div><div class="m_-3452541299801939580HOEnZb"><div class="m_-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-pr<wbr>oject?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/Execut<wbr>ionEngine/Orc/RemoteObjectLaye<wbr>r.h<br>
    llvm/trunk/unittests/Execution<wbr>Engine/Orc/RemoteObjectLayerTe<wbr>st.cpp<br>
Modified:<br>
    llvm/trunk/include/llvm/Execut<wbr>ionEngine/JITSymbol.h<br>
    llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/OrcError.h<br>
    llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/OrcRemoteTargetR<wbr>PCAPI.h<br>
    llvm/trunk/lib/ExecutionEngine<wbr>/Orc/OrcError.cpp<br>
    llvm/trunk/unittests/Execution<wbr>Engine/Orc/CMakeLists.txt<br>
<br>
Modified: llvm/trunk/include/llvm/Execut<wbr>ionEngine/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-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ExecutionEngine/JITSymbol.h?<wbr>rev=312511&r1=312510&r2=<wbr>312511&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Execut<wbr>ionEngine/JITSymbol.h (original)<br>
+++ llvm/trunk/include/llvm/Execut<wbr>ionEngine/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/Execut<wbr>ionEngine/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-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ExecutionEngine/Orc/OrcError.<wbr>h?rev=312511&r1=312510&r2=<wbr>312511&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/OrcError.h (original)<br>
+++ llvm/trunk/include/llvm/Execut<wbr>ionEngine/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/Execut<wbr>ionEngine/Orc/OrcRemoteTargetR<wbr>PCAPI.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-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ExecutionEngine/Orc/OrcRemoteT<wbr>argetRPCAPI.h?rev=312511&r1=<wbr>312510&r2=312511&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/OrcRemoteTargetR<wbr>PCAPI.h (original)<br>
+++ llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/OrcRemoteTargetR<wbr>PCAPI.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<Res<wbr>ourceIdT>> {<br>
+public:<br>
+  static char ID;<br>
+<br>
+  ResourceNotFound(ResourceIdT ResourceId,<br>
+                   std::string ResourceDescription = "")<br>
+    : ResourceId(std::move(ResourceI<wbr>d)),<br>
+      ResourceDescription(std::move(<wbr>ResourceDescription)) {}<br>
+<br>
+  std::error_code convertToErrorCode() const override {<br>
+    return orcError(OrcErrorCode::Unknown<wbr>ResourceHandle);<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>:<wbr>: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::Un<wbr>derlyingType>(Flags),<br>
+                        Flags.getTargetFlags());<br>
+  }<br>
+<br>
+  static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) {<br>
+    JITSymbolFlags::UnderlyingType JITFlags;<br>
+    JITSymbolFlags::TargetFlagsTyp<wbr>e TargetFlags;<br>
+    if (auto Err = deserializeSeq(C, JITFlags, TargetFlags))<br>
+      return Err;<br>
+    Flags = JITSymbolFlags(static_cast<JIT<wbr>SymbolFlags::FlagNames>(JITFla<wbr>gs),<br>
+                           TargetFlags);<br>
+    return Error::success();<br>
+  }<br>
+};<br>
+<br>
 template <> class RPCTypeName<remote::DirectBuff<wbr>erWriter> {<br>
 public:<br>
   static const char *getName() { return "DirectBufferWriter"; }<br>
<br>
Added: llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/RemoteObjectLaye<wbr>r.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-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>ExecutionEngine/Orc/RemoteObje<wbr>ctLayer.h?rev=312511&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/RemoteObjectLaye<wbr>r.h (added)<br>
+++ llvm/trunk/include/llvm/Execut<wbr>ionEngine/Orc/RemoteObjectLaye<wbr>r.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>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+// Forwards objects to a remote object layer via RPC.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_EXECUTIONENGINE_ORC_REMOT<wbr>EOBJECTLAYER_H<br>
+#define LLVM_EXECUTIONENGINE_ORC_REMOT<wbr>EOBJECTLAYER_H<br>
+<br>
+#include "llvm/ExecutionEngine/Orc/OrcR<wbr>emoteTargetRPCAPI.h"<br>
+#include "llvm/Object/ObjectFile.h"<br>
+#include "llvm/ExecutionEngine/Orc/Lamb<wbr>daResolver.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::Resourc<wbr>eId;<br>
+<br>
+protected:<br>
+<br>
+  using RemoteSymbolId = remote::ResourceIdMgr::Resourc<wbr>eId;<br>
+  using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;<br>
+<br>
+public:<br>
+<br>
+  using BadSymbolHandleError = remote::ResourceNotFound<Remot<wbr>eSymbolId>;<br>
+  using BadObjectHandleError = remote::ResourceNotFound<ObjHa<wbr>ndleT>;<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::stri<wbr>ng)> {<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::st<wbr>ring,<br>
+                                                              bool)> {<br>
+  public:<br>
+    static const char *getName() { return "FindSymbol"; }<br>
+  };<br>
+<br>
+  class FindSymbolIn<br>
+    : public rpc::Function<FindSymbolIn,<br>
+                           Expected<RemoteSymbol>(ObjHan<wbr>dleT, 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>(ObjHan<wbr>dleT, std::string)> {<br>
+  public:<br>
+    static const char *getName() { return "Lookup"; }<br>
+  };<br>
+<br>
+  class LookupInLogicalDylib<br>
+    : public rpc::Function<LookupInLogicalD<wbr>ylib,<br>
+                           Expected<RemoteSymbol>(ObjHan<wbr>dleT, std::string)> {<br>
+  public:<br>
+    static const char *getName() { return "LookupInLogicalDylib"; }<br>
+  };<br>
+<br>
+  class ReleaseRemoteSymbol<br>
+    : public rpc::Function<ReleaseRemoteSym<wbr>bol, Error(RemoteSymbolId)> {<br>
+  public:<br>
+    static const char *getName() { return "ReleaseRemoteSymbol"; }<br>
+  };<br>
+<br>
+  class MaterializeRemoteSymbol<br>
+    : public rpc::Function<MaterializeRemot<wbr>eSymbol,<br>
+                           Expected<JITTargetAddress>(Re<wbr>moteSymbolId)> {<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(ReportEr<wbr>ror)),<br>
+        SymbolIdMgr(NullSymbolId + 1) {<br>
+    using ThisT = RemoteObjectLayer<RPCEndpoint><wbr>;<br>
+    Remote.template addHandler<ReleaseRemoteSymbol<wbr>>(<br>
+             *this, &ThisT::handleReleaseRemoteSym<wbr>bol);<br>
+    Remote.template addHandler<MaterializeRemoteSy<wbr>mbol>(<br>
+             *this, &ThisT::handleMaterializeRemot<wbr>eSymbol);<br>
+  }<br>
+<br>
+protected:<br>
+<br>
+  class RemoteSymbolMaterializer {<br>
+  public:<br>
+<br>
+    RemoteSymbolMaterializer(Remot<wbr>eObjectLayer &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<RemoteSymbolMateria<wbr>lizer&>(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<ErrorIn<wbr>foBase> EIB) {<br>
+                          ReportError(make_error<StringE<wbr>rror>(<br>
+                                        EIB->message(),<br>
+                                        EIB->convertToErrorCode()));<br>
+                          return Error(std::move(EIB));<br>
+                        });<br>
+  }<br>
+<br>
+  Error badRemoteSymbolIdError(RemoteS<wbr>ymbolId Id) {<br>
+    return make_error<BadSymbolHandleErro<wbr>r>(Id, "Remote JIT Symbol");<br>
+  }<br>
+<br>
+  Error badObjectHandleError(ObjHandle<wbr>T H) {<br>
+    return make_error<RemoteObjectLayerAP<wbr>I::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_<wbr>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<Rem<wbr>oteSymbol> 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.templat<wbr>e callB<Func>(Args...));<br>
+  }<br>
+<br>
+  RPCEndpoint &Remote;<br>
+  std::function<void(Error)> ReportError;<br>
+<br>
+private:<br>
+<br>
+  void releaseRemoteSymbol(RemoteSymb<wbr>olId Id) {<br>
+    if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id)<wbr>)<br>
+      ReportError(std::move(Err));<br>
+  }<br>
+<br>
+  Expected<JITTargetAddress> materializeRemoteSymbol(Remote<wbr>SymbolId Id) {<br>
+    return Remote.template callB<MaterializeRemoteSymbol><wbr>(Id);<br>
+  }<br>
+<br>
+  Error handleReleaseRemoteSymbol(Remo<wbr>teSymbolId 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(<wbr>Id));<br>
+  }<br>
+<br>
+  Expected<JITTargetAddress> handleMaterializeRemoteSymbol(<wbr>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(<wbr>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::AddObjec<wbr>t;<br>
+  using RemoveObject = RemoteObjectLayerAPI::RemoveOb<wbr>ject;<br>
+  using FindSymbol = RemoteObjectLayerAPI::FindSymb<wbr>ol;<br>
+  using FindSymbolIn = RemoteObjectLayerAPI::FindSymb<wbr>olIn;<br>
+  using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndF<wbr>inalize;<br>
+  using Lookup = RemoteObjectLayerAPI::Lookup;<br>
+  using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupIn<wbr>LogicalDylib;<br>
+<br>
+  using RemoteObjectLayer<RPCEndpoint><wbr>::teeLog;<br>
+  using RemoteObjectLayer<RPCEndpoint><wbr>::badObjectHandleError;<br>
+  using RemoteObjectLayer<RPCEndpoint><wbr>::remoteToJITSymbol;<br>
+<br>
+public:<br>
+<br>
+  using ObjHandleT = RemoteObjectLayerAPI::ObjHandl<wbr>eT;<br>
+  using RemoteSymbol = RemoteObjectLayerAPI::RemoteSy<wbr>mbol;<br>
+<br>
+  using ObjectPtr =<br>
+    std::shared_ptr<object::Owning<wbr>Binary<object::ObjectFile>>;<br>
+<br>
+  RemoteObjectClientLayer(RPCEnd<wbr>point &Remote,<br>
+                          std::function<void(Error)> ReportError)<br>
+      : RemoteObjectLayer<RPCEndpoint><wbr>(Remote, std::move(ReportError)) {<br>
+    using ThisT = RemoteObjectClientLayer<RPCEnd<wbr>point>;<br>
+    Remote.template addHandler<Lookup>(*this, &ThisT::lookup);<br>
+    Remote.template addHandler<LookupInLogicalDyli<wbr>b>(<br>
+            *this, &ThisT::lookupInLogicalDylib);<br>
+  }<br>
+<br>
+  Expected<ObjHandleT><br>
+  addObject(ObjectPtr Object, std::shared_ptr<JITSymbolResol<wbr>ver> Resolver) {<br>
+    StringRef ObjBuffer = Object->getBinary()->getData()<wbr>;<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<wbr>) && "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->se<wbr>cond->findSymbol(Name));<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H)<wbr>);<br>
+  }<br>
+<br>
+  Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandle<wbr>T H,<br>
+                                              const std::string &Name) {<br>
+    auto RI = Resolvers.find(H);<br>
+    if (RI != Resolvers.end())<br>
+      return this->jitSymbolToRemote(<br>
+               RI->second->findSymbolInLogic<wbr>alDylib(Name));<br>
+    else<br>
+      return teeLog(badObjectHandleError(H)<wbr>);<br>
+  }<br>
+<br>
+  std::map<remote::ResourceIdMgr<wbr>::ResourceId,<br>
+           std::shared_ptr<JITSymbolReso<wbr>lver>> Resolvers;<br>
+};<br>
+<br>
+template <typename BaseLayerT, typename RPCEndpoint><br>
+class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {<br>
+private:<br>
+<br>
+  using ObjHandleT = RemoteObjectLayerAPI::ObjHandl<wbr>eT;<br>
+  using RemoteSymbol = RemoteObjectLayerAPI::RemoteSy<wbr>mbol;<br>
+<br>
+  using AddObject = RemoteObjectLayerAPI::AddObjec<wbr>t;<br>
+  using RemoveObject = RemoteObjectLayerAPI::RemoveOb<wbr>ject;<br>
+  using FindSymbol = RemoteObjectLayerAPI::FindSymb<wbr>ol;<br>
+  using FindSymbolIn = RemoteObjectLayerAPI::FindSymb<wbr>olIn;<br>
+  using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndF<wbr>inalize;<br>
+  using Lookup = RemoteObjectLayerAPI::Lookup;<br>
+  using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupIn<wbr>LogicalDylib;<br>
+<br>
+  using RemoteObjectLayer<RPCEndpoint><wbr>::teeLog;<br>
+  using RemoteObjectLayer<RPCEndpoint><wbr>::badObjectHandleError;<br>
+  using RemoteObjectLayer<RPCEndpoint><wbr>::remoteToJITSymbol;<br>
+<br>
+public:<br>
+<br>
+  RemoteObjectServerLayer(BaseLa<wbr>yerT &BaseLayer,<br>
+                          RPCEndpoint &Remote,<br>
+                          std::function<void(Error)> ReportError)<br>
+    : RemoteObjectLayer<RPCEndpoint><wbr>(Remote, std::move(ReportError)),<br>
+      BaseLayer(BaseLayer), HandleIdMgr(1) {<br>
+    using ThisT = RemoteObjectServerLayer<BaseLa<wbr>yerT, RPCEndpoint>;<br>
+<br>
+    Remote.template addHandler<AddObject>(*this, &ThisT::addObject);<br>
+    Remote.template addHandler<RemoveObject>(*this<wbr>, &ThisT::removeObject);<br>
+    Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);<br>
+    Remote.template addHandler<FindSymbolIn>(*this<wbr>, &ThisT::findSymbolIn);<br>
+    Remote.template addHandler<EmitAndFinalize>(*t<wbr>his, &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(ObjHandle<wbr>T Id, const std::string &Name) {<br>
+    return remoteToJITSymbol(<br>
+             this->Remote.template callB<LookupInLogicalDylib>(Id<wbr>, Name));<br>
+  }<br>
+<br>
+  Expected<ObjHandleT> addObject(std::string ObjBuffer) {<br>
+    auto Buffer = llvm::make_unique<StringMemory<wbr>Buffer>(std::move(ObjBuffer));<br>
+    if (auto ObjectOrErr =<br>
+          object::ObjectFile::createObje<wbr>ctFile(Buffer->getMemBufferRef<wbr>())) {<br>
+      auto Object =<br>
+        std::make_shared<object::Ownin<wbr>gBinary<object::ObjectFile>>(<br>
+          std::move(*ObjectOrErr), std::move(Buffer));<br>
+<br>
+      auto Id = HandleIdMgr.getNext();<br>
+      assert(!BaseLayerHandles.count<wbr>(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(<wbr>Object), std::move(Resolver))) {<br>
+        BaseLayerHandles[Id] = std::move(*HandleOrErr);<br>
+        return Id;<br>
+      } else<br>
+        return teeLog(HandleOrErr.takeError()<wbr>);<br>
+    } else<br>
+      return teeLog(ObjectOrErr.takeError()<wbr>);<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->sec<wbr>ond))<br>
+        return teeLog(std::move(Err));<br>
+      return Error::success();<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H)<wbr>);<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::m<wbr>ove(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->sec<wbr>ond, Name, ExportedSymbolsOnly))<br>
+        return this->jitSymbolToRemote(std::m<wbr>ove(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)<wbr>);<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-><wbr>second))<br>
+        return teeLog(std::move(Err));<br>
+      return Error::success();<br>
+    } else<br>
+      return teeLog(badObjectHandleError(H)<wbr>);<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_REMOT<wbr>EOBJECTLAYER_H<br>
<br>
Modified: llvm/trunk/lib/ExecutionEngine<wbr>/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-pr<wbr>oject/llvm/trunk/lib/Execution<wbr>Engine/Orc/OrcError.cpp?rev=<wbr>312511&r1=312510&r2=312511&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/ExecutionEngine<wbr>/Orc/OrcError.cpp (original)<br>
+++ llvm/trunk/lib/ExecutionEngine<wbr>/Orc/OrcError.cpp Mon Sep  4 20:34:09 2017<br>
@@ -54,6 +54,8 @@ public:<br>
     case OrcErrorCode::UnknownErrorCode<wbr>FromRemote:<br>
       return "Unknown error returned from remote RPC function "<br>
              "(Use StringError to get error message)";<br>
+    case OrcErrorCode::UnknownResourceH<wbr>andle:<br>
+      return "Unknown resource handle";<br>
     }<br>
     llvm_unreachable("Unhandled error code");<br>
   }<br>
<br>
Modified: llvm/trunk/unittests/Execution<wbr>Engine/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-pr<wbr>oject/llvm/trunk/unittests/Exe<wbr>cutionEngine/Orc/CMakeLists.<wbr>txt?rev=312511&r1=312510&r2=<wbr>312511&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/unittests/Execution<wbr>Engine/Orc/CMakeLists.txt (original)<br>
+++ llvm/trunk/unittests/Execution<wbr>Engine/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.<wbr>cpp<br>
   )<br>
<br>
Added: llvm/trunk/unittests/Execution<wbr>Engine/Orc/RemoteObjectLayerTe<wbr>st.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-pr<wbr>oject/llvm/trunk/unittests/Exe<wbr>cutionEngine/Orc/RemoteObjectL<wbr>ayerTest.cpp?rev=312511&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/unittests/Execution<wbr>Engine/Orc/RemoteObjectLayerTe<wbr>st.cpp (added)<br>
+++ llvm/trunk/unittests/Execution<wbr>Engine/Orc/RemoteObjectLayerTe<wbr>st.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>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "llvm/ExecutionEngine/Orc/Comp<wbr>ileUtils.h"<br>
+#include "llvm/ExecutionEngine/Orc/Null<wbr>Resolver.h"<br>
+#include "llvm/ExecutionEngine/Orc/Remo<wbr>teObjectLayer.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::Owning<wbr>Binary<object::ObjectFile>>;<br>
+<br>
+  using LookupFn = std::function<JITSymbol(String<wbr>Ref, bool)>;<br>
+  using SymbolLookupTable = std::map<ObjHandleT, LookupFn>;<br>
+<br>
+  using AddObjectFtor =<br>
+    std::function<Expected<ObjHand<wbr>leT>(ObjectPtr, SymbolLookupTable&)>;<br>
+<br>
+  class ObjectNotFound : public remote::ResourceNotFound<ObjHa<wbr>ndleT> {<br>
+  public:<br>
+    ObjectNotFound(ObjHandleT H) : ResourceNotFound(H, "Object handle") {}<br>
+  };<br>
+<br>
+  MockObjectLayer(AddObjectFtor AddObject)<br>
+    : AddObject(std::move(AddObject)<wbr>) {}<br>
+<br>
+  Expected<ObjHandleT> addObject(ObjectPtr Obj,<br>
+            std::shared_ptr<JITSymbolResol<wbr>ver> 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<wbr><rpc::RawByteChannel>;<br>
+<br>
+MockObjectLayer::ObjectPtr createTestObject() {<br>
+  OrcNativeTarget::initialize();<br>
+  auto TM = std::unique_ptr<TargetMachine><wbr>(EngineBuilder().selectTarget(<wbr>));<br>
+<br>
+  if (!TM)<br>
+    return nullptr;<br>
+<br>
+  LLVMContext Ctx;<br>
+  ModuleBuilder MB(Ctx, TM->getTargetTriple().str(), "TestModule");<br>
+  MB.getModule()->setDataLayout(<wbr>TM->createDataLayout());<br>
+  auto *Main = MB.createFunctionDecl<void(int<wbr>, char**)>("main");<br>
+  Main->getBasicBlockList().push<wbr>_back(BasicBlock::Create(Ctx))<wbr>;<br>
+  IRBuilder<> B(&Main->back());<br>
+  B.CreateRet(ConstantInt::getSi<wbr>gned(Type::getInt32Ty(Ctx), 42));<br>
+<br>
+  SimpleCompiler IRCompiler(*TM);<br>
+  return std::make_shared<object::Ownin<wbr>gBinary<object::ObjectFile>>(<br>
+           IRCompiler(*MB.getModule()));<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, AddObject) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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::mov<wbr>e(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()->getDa<wbr>ta();<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<RPCEnd<wbr>point> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+  MockObjectLayer BaseLayer(<br>
+    [&ObjContents](MockObjectLayer<wbr>::ObjectPtr Obj,<br>
+                   MockObjectLayer::SymbolLookup<wbr>Table &SymTab) {<br>
+<br>
+      // Check that the received object file content matches the original.<br>
+      StringRef RPCObjContents = Obj->getBinary()->getData();<br>
+      EXPECT_EQ(RPCObjContents.size(<wbr>), ObjContents.size())<br>
+        << "RPC'd object file has incorrect size";<br>
+      EXPECT_TRUE(std::equal(RPCObjC<wbr>ontents.begin(), RPCObjContents.end(),<br>
+                             ObjContents.begin()))<br>
+        << "RPC'd object file content does not match original content";<br>
+<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                            std::make_shared<NullResolver><wbr>()));<br>
+  cantFail(ClientEP.callB<remote<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, AddObjectFailure) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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<RPCEnd<wbr>point> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookup<wbr>Table &SymTab)<br>
+        -> Expected<MockObjectLayer::ObjH<wbr>andleT> {<br>
+      return make_error<StringError>("AddOb<wbr>jectFailure - Test Message",<br>
+                                     inconvertibleErrorCode());<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  auto HandleOrErr =<br>
+    Client.addObject(std::move(Tes<wbr>tObject), std::make_shared<NullResolver><wbr>());<br>
+<br>
+  EXPECT_FALSE(HandleOrErr) << "Expected error from addObject";<br>
+<br>
+  auto ErrMsg = toString(HandleOrErr.takeError<wbr>());<br>
+  EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")<br>
+    << "Expected error string to be \"AddObjectFailure - Test Message\"";<br>
+<br>
+  cantFail(ClientEP.callB<remote<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+<br>
+TEST(RemoteObjectLayer, RemoveObject) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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::mov<wbr>e(Err), llvm::errs(), "");<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEnd<wbr>point> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookup<wbr>Table &SymTab) {<br>
+      SymTab[1] = MockObjectLayer::LookupFn();<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  auto H  = cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                                      std::make_shared<NullResolver><wbr>()));<br>
+<br>
+  cantFail(Client.removeObject(H<wbr>));<br>
+<br>
+  cantFail(ClientEP.callB<remote<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, RemoveObjectFailure) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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<RPCEnd<wbr>point> 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::SymbolLookup<wbr>Table &SymTab) {<br>
+      return 42;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  auto H  = cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                                      std::make_shared<NullResolver><wbr>()));<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<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, FindSymbol) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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<RPCEnd<wbr>point> 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::SymbolLookup<wbr>Table &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>(<wbr>Name);<br>
+        };<br>
+      return 42;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                            std::make_shared<NullResolver><wbr>()));<br>
+<br>
+  auto Sym1 = Client.findSymbol("foobar", true);<br>
+<br>
+  EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";<br>
+  EXPECT_EQ(cantFail(Sym1.getAdd<wbr>ress()), 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<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, FindSymbolIn) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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<RPCEnd<wbr>point> 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::SymbolLookup<wbr>Table &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>(<wbr>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>(<wbr>Name);<br>
+        };<br>
+<br>
+      return 42;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  auto H = cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                                     std::make_shared<NullResolver<wbr>>()));<br>
+<br>
+  auto Sym1 = Client.findSymbolIn(H, "foobar", true);<br>
+<br>
+  EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";<br>
+  EXPECT_EQ(cantFail(Sym1.getAdd<wbr>ress()), 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<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, EmitAndFinalize) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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::mov<wbr>e(Err), llvm::errs(), "");<br>
+    };<br>
+<br>
+  RPCEndpoint ClientEP(*Channels.first, true);<br>
+  RemoteObjectClientLayer<RPCEnd<wbr>point> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookup<wbr>Table &SymTab) {<br>
+      SymTab[1] = MockObjectLayer::LookupFn();<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  auto H = cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                                     std::make_shared<NullResolver<wbr>>()));<br>
+<br>
+  auto Err = Client.emitAndFinalize(H);<br>
+  EXPECT_FALSE(!!Err) << "emitAndFinalize should work";<br>
+<br>
+  cantFail(ClientEP.callB<remote<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+TEST(RemoteObjectLayer, EmitAndFinalizeFailure) {<br>
+  llvm::orc::rpc::registerString<wbr>Error<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<RPCEnd<wbr>point> Client(ClientEP, ReportError);<br>
+<br>
+  RPCEndpoint ServerEP(*Channels.second, true);<br>
+<br>
+  MockObjectLayer BaseLayer(<br>
+    [](MockObjectLayer::ObjectPtr Obj,<br>
+       MockObjectLayer::SymbolLookup<wbr>Table &SymTab) {<br>
+      return 1;<br>
+    });<br>
+  RemoteObjectServerLayer<MockOb<wbr>jectLayer, RPCEndpoint> Server(BaseLayer,<br>
+                                                               ServerEP,<br>
+                                                               ReportError);<br>
+<br>
+  bool Finished = false;<br>
+  ServerEP.addHandler<remote::ut<wbr>ils::TerminateSession>(<br>
+    [&]() { Finished = true; }<br>
+  );<br>
+<br>
+  auto ServerThread =<br>
+    std::thread([&]() {<br>
+      while (!Finished)<br>
+        cantFail(ServerEP.handleOne())<wbr>;<br>
+    });<br>
+<br>
+  auto H = cantFail(Client.addObject(std:<wbr>:move(TestObject),<br>
+                                     std::make_shared<NullResolver<wbr>>()));<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<wbr>::utils::TerminateSession>());<br>
+  ServerThread.join();<br>
+}<br>
+<br>
+}<br>
<br>
<br>
______________________________<wbr>_________________<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/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>