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