<div dir="ltr"><div dir="ltr">On Sat, Apr 3, 2021 at 6:10 AM Stefan Gränitz <<a href="mailto:stefan.graenitz@gmail.com" target="_blank">stefan.graenitz@gmail.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div>
    <blockquote type="cite">then run `ninja check-llvm-examples` does it
      fail for you?</blockquote>
    Yes fails. And with your fix in llvm/test/CMakeLists.txt it works
    again. (First time I built check-llvm-examples individually.)<br></div></blockquote><div><br>Ah, for me it also fails with check-llvm, does that fail for you (following the above repro steps, but using check-llvm instead of check-llvm-examples). But 'check-all' maybe builds a broader scope and then it doesn't fail because it was built for whatever other reasons. Hmm, nope, I can even reproduce it with check-all.<br><br>Does it reproduce with check-all for you (now that/after you've deleted the binary and removed the fix like that)<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
    <br>
    I now remember that this sort of thing happened before and required
    another ToolSubst change in llvm/test/<a href="http://lit.cfg.py" target="_blank">lit.cfg.py</a>:<br>
    <a href="https://reviews.llvm.org/rGea7b1c79f73d8def" target="_blank">https://reviews.llvm.org/rGea7b1c79f73d8def</a><br>
    <br>
    Not sure it's necessary here too / still today. If yes, would we
    mimic the CMAKE_HOST_UNIX condition in Python</div></blockquote><div><br>In which bit of python? In the ToolSubst code? I think the "unresolved=ignore" part means it doesn't need to be exactly the same as the conditions in which its built (but might make something more robust if we did have exactly the same condition checking and then maybe "unresolved=fail" could be used - but I'm not sure of the ramifications of that (I don't know if ignoring the failure to resolve could result in the test execution falling back to using a binary of the same name installed elsewhere on the system - which would be unfortunate/problematic))<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div> or just add it
    unconditionally? If not: Maybe the other ToolSubst's are obsolete as
    well?<br></div></blockquote><div><br>Yeah, I really don't know anything about them.<br><br><a class="gmail_plusreply" id="plusReplyChip-1" href="mailto:echristo@gmail.com" tabindex="-1">@Eric Christopher</a> - any idea what the ToolSubst's you updated in <a href="https://reviews.llvm.org/rGea7b1c79f73d8def">https://reviews.llvm.org/rGea7b1c79f73d8def</a> are for/when they're needed/not needed?<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
    <br>
    <blockquote type="cite">> Also, I didn't get a message from
      buildmaster for this. Do we have a bot for your setup and is it
      public?<br>
      <br>
      Not sure - I guess probably not. We probably should have something
      building with the examples enabled.</blockquote>
    There are bots that build with examples enabled, but they do the
    same thing I used to do: configure with examples and check-llvm.
    This way the issue doesn't show up.</div></blockquote><div><br>Hmm, it does seem to show up for me (after I deleted the binary and removed the CMakeFiles.txt change) in check-llvm and check-all. So I'm not sure what's different about your situation or buildbots, etc - do you use Ninja or make or some other thing? (though I'd imagine we have buildbots using ninja... )<br><br>- Dave<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div> <br>
    <br>
    <div>On 03/04/2021 09:30, David Blaikie
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">On Wed, Mar 31, 2021 at 1:34 AM Stefan Gränitz <<a href="mailto:stefan.graenitz@gmail.com" target="_blank">stefan.graenitz@gmail.com</a>>
        wrote:<br>
        ><br>
        > Hi David, thanks for working on it!<br>
        ><br>
        > I ran the test suite on Linux and macOS with examples
        enabled and it worked well.<br>
        <br>
        Did you modify an existing build directory that had already
        built the examples from some other invocation?<br>
        <br>
        If you do these things:<br>
        <br>
        1) enable examples in your CMakeCache.txt:<br>
         LLVM_BUILD_EXAMPLES:BOOL=ON<br>
         LLVM_INCLUDE_EXAMPLES:BOOL=ON<br>
        2) Delete any already built version of the jit binary:<br>
         build$ rm -f ./bin/LLJITWithRemoteDebugging<br>
        3) Undo ae217bf1f3277b8c14590a130ee5e63cc1664443 by making this
        change:<br>
        <font face="monospace">diff --git llvm/test/CMakeLists.txt
          llvm/test/CMakeLists.txt<br>
          index 81107be862de..7c4fa2e9033a 100644<br>
          --- llvm/test/CMakeLists.txt<br>
          +++ llvm/test/CMakeLists.txt<br>
          @@ -158,11 +158,6 @@ if(LLVM_BUILD_EXAMPLES)<br>
               Kaleidoscope-Ch7<br>
               LLJITWithThinLTOSummaries<br>
               )<br>
          -  if(CMAKE_HOST_UNIX)<br>
          -    list(APPEND LLVM_TEST_DEPENDS<br>
          -      LLJITWithRemoteDebugging<br>
          -      )<br>
          -  endif()<br>
             if (NOT WIN32)<br>
               list(APPEND LLVM_TEST_DEPENDS<br>
                 Bye</font><br>
        <br>
        then run `ninja check-llvm-examples` (or make, etc - though
        perhaps ninja is part of the necessary repro steps, I guess - I
        haven't tried with make) - does it fail for you?<br>
        <br>
        > Also, I didn't get a message from buildmaster for this. Do
        we have a bot for your setup and is it public?<br>
        <br>
        Not sure - I guess probably not. We probably should have
        something building with the examples enabled.<br>
        <br>
        ><br>
        > On 30/03/2021 22:05, David Blaikie wrote:<br>
        ><br>
        > This broke the build with examples enabled
        (LLVM_BUILD_EXAMPLES=ON) I think. My second attempt at fixing
        this is in ae217bf1f3277b8c14590a130ee5e63cc1664443<br>
        ><br>
        > On Sun, Mar 28, 2021 at 8:25 AM Stefan Gränitz via
        llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>>
        wrote:<br>
        >><br>
        >><br>
        >> Author: Stefan Gränitz<br>
        >> Date: 2021-03-28T17:25:09+02:00<br>
        >> New Revision: 258f055ed93661900bc568350e09f467c0950486<br>
        >><br>
        >> URL: <a href="https://github.com/llvm/llvm-project/commit/258f055ed93661900bc568350e09f467c0950486" target="_blank">https://github.com/llvm/llvm-project/commit/258f055ed93661900bc568350e09f467c0950486</a><br>
        >> DIFF: <a href="https://github.com/llvm/llvm-project/commit/258f055ed93661900bc568350e09f467c0950486.diff" target="_blank">https://github.com/llvm/llvm-project/commit/258f055ed93661900bc568350e09f467c0950486.diff</a><br>
        >><br>
        >> LOG: [Orc][examples] Add LLJITWithRemoteDebugging
        example<br>
        >><br>
        >> Added:<br>
        >>    
        llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/CMakeLists.txt<br>
        >>    
llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/LLJITWithRemoteDebugging.cpp<br>
        >>    
        llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp<br>
        >>    
        llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.h<br>
        >>     llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1.c<br>
        >>    
        llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1_elf.ll<br>
        >>    
        llvm/test/Examples/OrcV2Examples/lljit-with-remote-debugging.test<br>
        >><br>
        >> Modified:<br>
        >>     llvm/examples/OrcV2Examples/CMakeLists.txt<br>
        >>     llvm/examples/OrcV2Examples/ExampleModules.h<br>
        >><br>
        >> Removed:<br>
        >><br>
        >><br>
        >><br>
        >>
################################################################################<br>
        >> diff  --git
        a/llvm/examples/OrcV2Examples/CMakeLists.txt
        b/llvm/examples/OrcV2Examples/CMakeLists.txt<br>
        >> index bed277e59e0b..f6a11d6f0ef2 100644<br>
        >> --- a/llvm/examples/OrcV2Examples/CMakeLists.txt<br>
        >> +++ b/llvm/examples/OrcV2Examples/CMakeLists.txt<br>
        >> @@ -12,3 +12,7 @@
        add_subdirectory(OrcV2CBindingsAddObjectFile)<br>
        >>  add_subdirectory(OrcV2CBindingsBasicUsage)<br>
        >>  add_subdirectory(OrcV2CBindingsReflectProcessSymbols)<br>
        >>  add_subdirectory(OrcV2CBindingsRemovableCode)<br>
        >> +<br>
        >> +if(CMAKE_HOST_UNIX)<br>
        >> +  add_subdirectory(LLJITWithRemoteDebugging)<br>
        >> +endif()<br>
        >><br>
        >> diff  --git
        a/llvm/examples/OrcV2Examples/ExampleModules.h
        b/llvm/examples/OrcV2Examples/ExampleModules.h<br>
        >> index c88609fae769..53da756e15f7 100644<br>
        >> --- a/llvm/examples/OrcV2Examples/ExampleModules.h<br>
        >> +++ b/llvm/examples/OrcV2Examples/ExampleModules.h<br>
        >> @@ -52,4 +52,16 @@ parseExampleModule(llvm::StringRef
        Source, llvm::StringRef Name) {<br>
        >>    return createSMDiagnosticError(Err);<br>
        >>  }<br>
        >><br>
        >> +inline
        llvm::Expected<llvm::orc::ThreadSafeModule><br>
        >> +parseExampleModuleFromFile(llvm::StringRef FileName) {<br>
        >> +  using namespace llvm;<br>
        >> +  auto Ctx = std::make_unique<LLVMContext>();<br>
        >> +  SMDiagnostic Err;<br>
        >> +<br>
        >> +  if (auto M = parseIRFile(FileName, Err, *Ctx))<br>
        >> +    return orc::ThreadSafeModule(std::move(M),
        std::move(Ctx));<br>
        >> +<br>
        >> +  return createSMDiagnosticError(Err);<br>
        >> +}<br>
        >> +<br>
        >>  #endif // LLVM_EXAMPLES_ORCV2EXAMPLES_EXAMPLEMODULES_H<br>
        >><br>
        >> diff  --git
        a/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/CMakeLists.txt
b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/CMakeLists.txt<br>
        >> new file mode 100644<br>
        >> index 000000000000..b93dd4924b05<br>
        >> --- /dev/null<br>
        >> +++
        b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/CMakeLists.txt<br>
        >> @@ -0,0 +1,18 @@<br>
        >> +set(LLVM_LINK_COMPONENTS<br>
        >> +  Core<br>
        >> +  ExecutionEngine<br>
        >> +  IRReader<br>
        >> +  JITLink<br>
        >> +  OrcJIT<br>
        >> +  OrcTargetProcess<br>
        >> +  Support<br>
        >> +  nativecodegen<br>
        >> +  )<br>
        >> +<br>
        >> +add_llvm_example(LLJITWithRemoteDebugging<br>
        >> +  LLJITWithRemoteDebugging.cpp<br>
        >> +  RemoteJITUtils.cpp<br>
        >> +<br>
        >> +  DEPENDS<br>
        >> +    llvm-jitlink-executor<br>
        >> +  )<br>
        >><br>
        >> diff  --git
a/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/LLJITWithRemoteDebugging.cpp
b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/LLJITWithRemoteDebugging.cpp<br>
        >> new file mode 100644<br>
        >> index 000000000000..6da30f608206<br>
        >> --- /dev/null<br>
        >> +++
b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/LLJITWithRemoteDebugging.cpp<br>
        >> @@ -0,0 +1,258 @@<br>
        >> +//===--- LLJITWithRemoteDebugging.cpp - LLJIT
        targeting a child process ---===//<br>
        >> +//<br>
        >> +// Part of the LLVM Project, under the Apache License
        v2.0 with LLVM Exceptions.<br>
        >> +// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for
        license information.<br>
        >> +// SPDX-License-Identifier: Apache-2.0 WITH
        LLVM-exception<br>
        >> +//<br>
        >>
+//===----------------------------------------------------------------------===//<br>
        >> +//<br>
        >> +// This example shows how to use LLJIT and JITLink for
        out-of-process execution<br>
        >> +// with debug support.  A few notes beforehand:<br>
        >> +//<br>
        >> +//  * Debuggers must implement the GDB JIT interface
        (gdb, udb, lldb 12+).<br>
        >> +//  * Debug support is currently limited to ELF on
        x86-64 platforms that run<br>
        >> +//    Unix-like systems.<br>
        >> +//  * There is a test for this example and it ships an
        IR file that is prepared<br>
        >> +//    for the instructions below.<br>
        >> +//<br>
        >> +//<br>
        >> +// The following command line session provides a
        complete walkthrough of the<br>
        >> +// feature using LLDB 12:<br>
        >> +//<br>
        >> +// [Terminal 1] Prepare a debuggable out-of-process
        JIT session:<br>
        >> +//<br>
        >> +//    > cd llvm-project/build<br>
        >> +//    > ninja LLJITWithRemoteDebugging
        llvm-jitlink-executor<br>
        >> +//    > cp
        ../llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1_elf.ll .<br>
        >> +//    > bin/LLJITWithRemoteDebugging
        --wait-for-debugger argc_sub1_elf.ll<br>
        >> +//    Found out-of-process executor:
        bin/llvm-jitlink-executor<br>
        >> +//    Launched executor in subprocess: 65535<br>
        >> +//    Attach a debugger and press any key to continue.<br>
        >> +//<br>
        >> +//<br>
        >> +// [Terminal 2] Attach a debugger to the child
        process:<br>
        >> +//<br>
        >> +//    (lldb) log enable lldb jit<br>
        >> +//    (lldb) settings set plugin.jit-loader.gdb.enable
        on<br>
        >> +//    (lldb) settings set target.source-map Inputs/ \<br>
        >> +//            
        /path/to/llvm-project/llvm/test/Examples/OrcV2Examples/Inputs/<br>
        >> +//    (lldb) attach -p 65535<br>
        >> +//     JITLoaderGDB::SetJITBreakpoint looking for JIT
        register hook<br>
        >> +//     JITLoaderGDB::SetJITBreakpoint setting JIT
        breakpoint<br>
        >> +//    Process 65535 stopped<br>
        >> +//    (lldb) b sub1<br>
        >> +//    Breakpoint 1: no locations (pending).<br>
        >> +//    WARNING:  Unable to resolve breakpoint to any
        actual locations.<br>
        >> +//    (lldb) c<br>
        >> +//    Process 65535 resuming<br>
        >> +//<br>
        >> +//<br>
        >> +// [Terminal 1] Press a key to start code generation
        and execution:<br>
        >> +//<br>
        >> +//    Parsed input IR code from: argc_sub1_elf.ll<br>
        >> +//    Initialized LLJIT for remote executor<br>
        >> +//    Running: argc_sub1_elf.ll<br>
        >> +//<br>
        >> +//<br>
        >> +// [Terminal 2] Breakpoint hits; we change the argc
        value from 1 to 42:<br>
        >> +//<br>
        >> +//    (lldb)  JITLoaderGDB::JITDebugBreakpointHit hit
        JIT breakpoint<br>
        >> +//     JITLoaderGDB::ReadJITDescriptorImpl registering
        JIT entry at 0x106b34000<br>
        >> +//    1 location added to breakpoint 1<br>
        >> +//    Process 65535 stopped<br>
        >> +//    * thread #1, queue = 'com.apple.main-thread',
        stop reason = breakpoint 1.1<br>
        >> +//        frame #0: JIT(0x106b34000)`sub1(x=1) at
        argc_sub1.c:1:28<br>
        >> +//    -> 1     int sub1(int x) { return x - 1; }<br>
        >> +//       2     int main(int argc, char **argv) {
        return sub1(argc); }<br>
        >> +//    (lldb) p x<br>
        >> +//    (int) $0 = 1<br>
        >> +//    (lldb) expr x = 42<br>
        >> +//    (int) $1 = 42<br>
        >> +//    (lldb) c<br>
        >> +//<br>
        >> +//<br>
        >> +// [Terminal 1] Example output reflects the modified
        value:<br>
        >> +//<br>
        >> +//    Exit code: 41<br>
        >> +//<br>
        >>
+//===----------------------------------------------------------------------===//<br>
        >> +<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"<br>
        >> +#include "llvm/ExecutionEngine/Orc/LLJIT.h"<br>
        >> +#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"<br>
        >> +#include "llvm/Support/CommandLine.h"<br>
        >> +#include "llvm/Support/Error.h"<br>
        >> +#include "llvm/Support/FormatVariadic.h"<br>
        >> +#include "llvm/Support/InitLLVM.h"<br>
        >> +#include "llvm/Support/TargetSelect.h"<br>
        >> +#include "llvm/Support/raw_ostream.h"<br>
        >> +<br>
        >> +#include "../ExampleModules.h"<br>
        >> +#include "RemoteJITUtils.h"<br>
        >> +<br>
        >> +#include <memory><br>
        >> +#include <string><br>
        >> +<br>
        >> +using namespace llvm;<br>
        >> +using namespace llvm::orc;<br>
        >> +<br>
        >> +// The LLVM IR file to run.<br>
        >> +static cl::list<std::string>
        InputFiles(cl::Positional, cl::OneOrMore,<br>
        >> +                                      
         cl::desc("<input files>"));<br>
        >> +<br>
        >> +// Command line arguments to pass to the JITed main
        function.<br>
        >> +static cl::list<std::string> InputArgv("args",
        cl::Positional,<br>
        >> +                                      
        cl::desc("<program arguments>..."),<br>
        >> +                                       cl::ZeroOrMore,
        cl::PositionalEatsArgs);<br>
        >> +<br>
        >> +// Given paths must exist on the remote target.<br>
        >> +static cl::list<std::string><br>
        >> +    Dylibs("dlopen", cl::desc("Dynamic libraries to
        load before linking"),<br>
        >> +           cl::value_desc("filename"),
        cl::ZeroOrMore);<br>
        >> +<br>
        >> +// File path of the executable to launch for execution
        in a child process.<br>
        >> +// Inter-process communication will go through
        stdin/stdout pipes.<br>
        >> +static cl::opt<std::string><br>
        >> +    OOPExecutor("executor", cl::desc("Set the
        out-of-process executor"),<br>
        >> +                cl::value_desc("filename"));<br>
        >> +<br>
        >> +// Network address of a running executor process that
        we can connected through a<br>
        >> +// TCP socket. It may run locally or on a remote
        machine.<br>
        >> +static cl::opt<std::string> OOPExecutorConnect(<br>
        >> +    "connect",<br>
        >> +    cl::desc("Connect to an out-of-process executor
        through a TCP socket"),<br>
        >> +    cl::value_desc("<hostname>:<port>"));<br>
        >> +<br>
        >> +// Give the user a chance to connect a debugger. Once
        we connected the executor<br>
        >> +// process, wait for the user to press a key (and
        print out its PID if it's a<br>
        >> +// child process).<br>
        >> +static cl::opt<bool><br>
        >> +    WaitForDebugger("wait-for-debugger",<br>
        >> +                    cl::desc("Wait for user input
        before entering JITed code"),<br>
        >> +                    cl::init(false));<br>
        >> +<br>
        >> +ExitOnError ExitOnErr;<br>
        >> +<br>
        >> +static std::unique_ptr<JITLinkExecutor>
        connectExecutor(const char *Argv0,<br>
        >> +                                                      
         ExecutionSession &ES) {<br>
        >> +  // Connect to a running out-of-process executor
        through a TCP socket.<br>
        >> +  if (!OOPExecutorConnect.empty()) {<br>
        >> +    std::unique_ptr<TCPSocketJITLinkExecutor>
        Exec =<br>
        >> +      
         ExitOnErr(JITLinkExecutor::ConnectTCPSocket(OOPExecutorConnect,
        ES));<br>
        >> +<br>
        >> +    outs() << "Connected to executor at "
        << OOPExecutorConnect << "\n";<br>
        >> +    if (WaitForDebugger) {<br>
        >> +      outs() << "Attach a debugger and press any
        key to continue.\n";<br>
        >> +      fflush(stdin);<br>
        >> +      getchar();<br>
        >> +    }<br>
        >> +<br>
        >> +    return std::move(Exec);<br>
        >> +  }<br>
        >> +<br>
        >> +  // Launch a out-of-process executor locally in a
        child process.<br>
        >> +  std::unique_ptr<ChildProcessJITLinkExecutor>
        Exec = ExitOnErr(<br>
        >> +      OOPExecutor.empty() ?
        JITLinkExecutor::FindLocal(Argv0)<br>
        >> +                          :
        JITLinkExecutor::CreateLocal(OOPExecutor));<br>
        >> +<br>
        >> +  outs() << "Found out-of-process executor: "
        << Exec->getPath() << "\n";<br>
        >> +<br>
        >> +  ExitOnErr(Exec->launch(ES));<br>
        >> +  if (WaitForDebugger) {<br>
        >> +    outs() << "Launched executor in subprocess:
        " << Exec->getPID() << "\n"<br>
        >> +           << "Attach a debugger and press any
        key to continue.\n";<br>
        >> +    fflush(stdin);<br>
        >> +    getchar();<br>
        >> +  }<br>
        >> +<br>
        >> +  return std::move(Exec);<br>
        >> +}<br>
        >> +<br>
        >> +int main(int argc, char *argv[]) {<br>
        >> +  InitLLVM X(argc, argv);<br>
        >> +<br>
        >> +  InitializeNativeTarget();<br>
        >> +  InitializeNativeTargetAsmPrinter();<br>
        >> +<br>
        >> +  ExitOnErr.setBanner(std::string(argv[0]) + ": ");<br>
        >> +  cl::ParseCommandLineOptions(argc, argv,
        "LLJITWithRemoteDebugging");<br>
        >> +<br>
        >> +  auto ES =
        std::make_unique<ExecutionSession>();<br>
        >> +  ES->setErrorReporter([&](Error Err) {
        ExitOnErr(std::move(Err)); });<br>
        >> +<br>
        >> +  // Launch/connect the out-of-process executor.<br>
        >> +  std::unique_ptr<JITLinkExecutor> Executor =
        connectExecutor(argv[0], *ES);<br>
        >> +<br>
        >> +  // Load the given IR files.<br>
        >> +  std::vector<ThreadSafeModule> TSMs;<br>
        >> +  for (const std::string &Path : InputFiles) {<br>
        >> +    outs() << "Parsing input IR code from: "
        << Path << "\n";<br>
        >> +  
         TSMs.push_back(ExitOnErr(parseExampleModuleFromFile(Path)));<br>
        >> +  }<br>
        >> +<br>
        >> +  StringRef TT;<br>
        >> +  StringRef MainModuleName;<br>
        >> +  TSMs.front().withModuleDo([&MainModuleName,
        &TT](Module &M) {<br>
        >> +    MainModuleName = M.getName();<br>
        >> +    TT = M.getTargetTriple();<br>
        >> +  });<br>
        >> +<br>
        >> +  for (const ThreadSafeModule &TSM : TSMs)<br>
        >> +    ExitOnErr(TSM.withModuleDo([TT,
        MainModuleName](Module &M) -> Error {<br>
        >> +      if (M.getTargetTriple() != TT)<br>
        >> +        return make_error<StringError>(<br>
        >> +            formatv("Different target triples in input
        files:\n"<br>
        >> +                    "  '{0}' in '{1}'\n  '{2}' in
        '{3}'",<br>
        >> +                    TT, MainModuleName,
        M.getTargetTriple(), M.getName()),<br>
        >> +            inconvertibleErrorCode());<br>
        >> +      return Error::success();<br>
        >> +    }));<br>
        >> +<br>
        >> +  // Create a target machine that matches the input
        triple.<br>
        >> +  JITTargetMachineBuilder JTMB((Triple(TT)));<br>
        >> +  JTMB.setCodeModel(CodeModel::Small);<br>
        >> +  JTMB.setRelocationModel(Reloc::PIC_);<br>
        >> +<br>
        >> +  // Create LLJIT and destroy it before disconnecting
        the target process.<br>
        >> +  {<br>
        >> +    outs() << "Initializing LLJIT for remote
        executor\n";<br>
        >> +    auto J = ExitOnErr(LLJITBuilder()<br>
        >> +                          
        .setExecutionSession(std::move(ES))<br>
        >> +                          
        .setJITTargetMachineBuilder(std::move(JTMB))<br>
        >> +                          
        .setObjectLinkingLayerCreator(std::ref(*Executor))<br>
        >> +                           .create());<br>
        >> +<br>
        >> +    // Add plugin for debug support.<br>
        >> +  
         ExitOnErr(Executor->addDebugSupport(J->getObjLinkingLayer()));<br>
        >> +<br>
        >> +    // Load required shared libraries on the remote
        target and add a generator<br>
        >> +    // for each of it, so the compiler can lookup
        their symbols.<br>
        >> +    for (const std::string &Path : Dylibs)<br>
        >> +    
 J->getMainJITDylib().addGenerator(ExitOnErr(Executor->loadDylib(Path)));<br>
        >> +<br>
        >> +    // Add the loaded IR module to the JIT. This will
        set up symbol tables and<br>
        >> +    // prepare for materialization.<br>
        >> +    for (ThreadSafeModule &TSM : TSMs)<br>
        >> +      ExitOnErr(J->addIRModule(std::move(TSM)));<br>
        >> +<br>
        >> +    // The example uses a non-lazy JIT for simplicity.
        Thus, looking up the main<br>
        >> +    // function will materialize all reachable code.
        It also triggers debug<br>
        >> +    // registration in the remote target process.<br>
        >> +    JITEvaluatedSymbol MainFn =
        ExitOnErr(J->lookup("main"));<br>
        >> +<br>
        >> +    outs() << "Running: main(";<br>
        >> +    int Pos = 0;<br>
        >> +    for (const std::string &Arg : InputArgv)<br>
        >> +      outs() << (Pos++ == 0 ? "" : ", ")
        << Arg;<br>
        >> +    outs() << ")\n";<br>
        >> +<br>
        >> +    // Execute the code in the remote target process
        and dump the result. With<br>
        >> +    // the debugger attached to the target, it should
        be possible to inspect the<br>
        >> +    // JITed code as if it was compiled statically.<br>
        >> +    int Result =
        ExitOnErr(Executor->runAsMain(MainFn, InputArgv));<br>
        >> +    outs() << "Exit code: " << Result
        << "\n";<br>
        >> +  }<br>
        >> +<br>
        >> +  ExitOnErr(Executor->disconnect());<br>
        >> +  return 0;<br>
        >> +}<br>
        >><br>
        >> diff  --git
a/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp
b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp<br>
        >> new file mode 100644<br>
        >> index 000000000000..abce14de0fe0<br>
        >> --- /dev/null<br>
        >> +++
b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp<br>
        >> @@ -0,0 +1,347 @@<br>
        >> +//===-- RemoteJITUtils.cpp - Utilities for
        remote-JITing --------*- C++ -*-===//<br>
        >> +//<br>
        >> +// Part of the LLVM Project, under the Apache License
        v2.0 with LLVM Exceptions.<br>
        >> +// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for
        license information.<br>
        >> +// SPDX-License-Identifier: Apache-2.0 WITH
        LLVM-exception<br>
        >> +//<br>
        >>
+//===----------------------------------------------------------------------===//<br>
        >> +<br>
        >> +#include "RemoteJITUtils.h"<br>
        >> +<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h"<br>
        >> +#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/TPCDebugObjectRegistrar.h"<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h"<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"<br>
        >> +#include "llvm/Support/FileSystem.h"<br>
        >> +#include "llvm/Support/Path.h"<br>
        >> +#include "llvm/Support/ToolOutputFile.h"<br>
        >> +<br>
        >> +#ifdef LLVM_ON_UNIX<br>
        >> +#include <netdb.h><br>
        >> +#include <netinet/in.h><br>
        >> +#include <sys/socket.h><br>
        >> +#include <unistd.h><br>
        >> +#endif // LLVM_ON_UNIX<br>
        >> +<br>
        >> +using namespace llvm;<br>
        >> +using namespace llvm::orc;<br>
        >> +<br>
        >> +namespace llvm {<br>
        >> +namespace orc {<br>
        >> +<br>
        >> +class RemoteTargetProcessControl<br>
        >> +    : public OrcRPCTargetProcessControlBase<<br>
        >> +        
         shared::MultiThreadedRPCEndpoint<JITLinkExecutor::RPCChannel>>
        {<br>
        >> +public:<br>
        >> +  using RPCChannel = JITLinkExecutor::RPCChannel;<br>
        >> +  using RPCEndpoint =
        shared::MultiThreadedRPCEndpoint<RPCChannel>;<br>
        >> +<br>
        >> +private:<br>
        >> +  using ThisT = RemoteTargetProcessControl;<br>
        >> +  using BaseT =
        OrcRPCTargetProcessControlBase<RPCEndpoint>;<br>
        >> +  using MemoryAccess =
        OrcRPCTPCMemoryAccess<ThisT>;<br>
        >> +  using MemoryManager =
        OrcRPCTPCJITLinkMemoryManager<ThisT>;<br>
        >> +<br>
        >> +public:<br>
        >> +  using BaseT::initializeORCRPCTPCBase;<br>
        >> +<br>
        >> +  RemoteTargetProcessControl(ExecutionSession &ES,<br>
        >> +                            
        std::unique_ptr<RPCChannel> Channel,<br>
        >> +                            
        std::unique_ptr<RPCEndpoint> Endpoint);<br>
        >> +<br>
        >> +  void initializeMemoryManagement();<br>
        >> +  Error disconnect() override;<br>
        >> +<br>
        >> +private:<br>
        >> +  std::unique_ptr<RPCChannel> Channel;<br>
        >> +  std::unique_ptr<RPCEndpoint> Endpoint;<br>
        >> +  std::unique_ptr<MemoryAccess> OwnedMemAccess;<br>
        >> +  std::unique_ptr<MemoryManager> OwnedMemMgr;<br>
        >> +  std::atomic<bool> Finished{false};<br>
        >> +  std::thread ListenerThread;<br>
        >> +};<br>
        >> +<br>
        >>
        +RemoteTargetProcessControl::RemoteTargetProcessControl(<br>
        >> +    ExecutionSession &ES,
        std::unique_ptr<RPCChannel> Channel,<br>
        >> +    std::unique_ptr<RPCEndpoint> Endpoint)<br>
        >> +    : BaseT(ES.getSymbolStringPool(), *Endpoint,<br>
        >> +            [&ES](Error Err) {
        ES.reportError(std::move(Err)); }),<br>
        >> +      Channel(std::move(Channel)),
        Endpoint(std::move(Endpoint)) {<br>
        >> +<br>
        >> +  ListenerThread = std::thread([&]() {<br>
        >> +    while (!Finished) {<br>
        >> +      if (auto Err =
        this->Endpoint->handleOne()) {<br>
        >> +        reportError(std::move(Err));<br>
        >> +        return;<br>
        >> +      }<br>
        >> +    }<br>
        >> +  });<br>
        >> +}<br>
        >> +<br>
        >> +void
        RemoteTargetProcessControl::initializeMemoryManagement() {<br>
        >> +  OwnedMemAccess =
        std::make_unique<MemoryAccess>(*this);<br>
        >> +  OwnedMemMgr =
        std::make_unique<MemoryManager>(*this);<br>
        >> +<br>
        >> +  // Base class needs non-owning access.<br>
        >> +  MemAccess = OwnedMemAccess.get();<br>
        >> +  MemMgr = OwnedMemMgr.get();<br>
        >> +}<br>
        >> +<br>
        >> +Error RemoteTargetProcessControl::disconnect() {<br>
        >> +  std::promise<MSVCPError> P;<br>
        >> +  auto F = P.get_future();<br>
        >> +  auto Err = closeConnection([&](Error Err) ->
        Error {<br>
        >> +    P.set_value(std::move(Err));<br>
        >> +    Finished = true;<br>
        >> +    return Error::success();<br>
        >> +  });<br>
        >> +  ListenerThread.join();<br>
        >> +  return joinErrors(std::move(Err), F.get());<br>
        >> +}<br>
        >> +<br>
        >> +} // namespace orc<br>
        >> +} // namespace llvm<br>
        >> +<br>
        >> +JITLinkExecutor::JITLinkExecutor() = default;<br>
        >> +JITLinkExecutor::~JITLinkExecutor() = default;<br>
        >> +<br>
        >> +Expected<std::unique_ptr<ObjectLayer>><br>
        >> +JITLinkExecutor::operator()(ExecutionSession &ES,
        const Triple &TT) {<br>
        >> +  return
        std::make_unique<ObjectLinkingLayer>(ES,
        TPC->getMemMgr());<br>
        >> +}<br>
        >> +<br>
        >> +Error JITLinkExecutor::addDebugSupport(ObjectLayer
        &ObjLayer) {<br>
        >> +  auto Registrar = createJITLoaderGDBRegistrar(*TPC);<br>
        >> +  if (!Registrar)<br>
        >> +    return Registrar.takeError();<br>
        >> +<br>
        >> +
         cast<ObjectLinkingLayer>(&ObjLayer)->addPlugin(<br>
        >> +    
 std::make_unique<DebugObjectManagerPlugin>(ObjLayer.getExecutionSession(),<br>
        >> +                                                
        std::move(*Registrar)));<br>
        >> +<br>
        >> +  return Error::success();<br>
        >> +}<br>
        >> +<br>
        >>
        +Expected<std::unique_ptr<DefinitionGenerator>><br>
        >> +JITLinkExecutor::loadDylib(StringRef RemotePath) {<br>
        >> +  if (auto Handle =
        TPC->loadDylib(RemotePath.data()))<br>
        >> +    return
        std::make_unique<TPCDynamicLibrarySearchGenerator>(*TPC,
        *Handle);<br>
        >> +  else<br>
        >> +    return Handle.takeError();<br>
        >> +}<br>
        >> +<br>
        >> +Expected<int>
        JITLinkExecutor::runAsMain(JITEvaluatedSymbol MainSym,<br>
        >> +                                        
        ArrayRef<std::string> Args) {<br>
        >> +  return TPC->runAsMain(MainSym.getAddress(),
        Args);<br>
        >> +}<br>
        >> +<br>
        >> +Error JITLinkExecutor::disconnect() { return
        TPC->disconnect(); }<br>
        >> +<br>
        >> +static std::string defaultPath(const char *HostArgv0,
        StringRef ExecutorName) {<br>
        >> +  // This just needs to be some symbol in the binary;
        C++ doesn't<br>
        >> +  // allow taking the address of ::main however.<br>
        >> +  void *P = (void *)(intptr_t)defaultPath;<br>
        >> +  SmallString<256>
        FullName(sys::fs::getMainExecutable(HostArgv0, P));<br>
        >> +  sys::path::remove_filename(FullName);<br>
        >> +  sys::path::append(FullName, ExecutorName);<br>
        >> +  return FullName.str().str();<br>
        >> +}<br>
        >> +<br>
        >>
        +Expected<std::unique_ptr<ChildProcessJITLinkExecutor>><br>
        >> +JITLinkExecutor::FindLocal(const char *HostArgv) {<br>
        >> +  std::string BestGuess = defaultPath(HostArgv,
        "llvm-jitlink-executor");<br>
        >> +  auto Executor = CreateLocal(BestGuess);<br>
        >> +  if (!Executor) {<br>
        >> +    consumeError(Executor.takeError());<br>
        >> +    return make_error<StringError>(<br>
        >> +        formatv("Unable to find usable executor: {0}",
        BestGuess),<br>
        >> +        inconvertibleErrorCode());<br>
        >> +  }<br>
        >> +  return Executor;<br>
        >> +}<br>
        >> +<br>
        >>
        +Expected<std::unique_ptr<ChildProcessJITLinkExecutor>><br>
        >> +JITLinkExecutor::CreateLocal(std::string
        ExecutablePath) {<br>
        >> +  if (!sys::fs::can_execute(ExecutablePath))<br>
        >> +    return make_error<StringError>(<br>
        >> +        formatv("Specified executor invalid: {0}",
        ExecutablePath),<br>
        >> +        inconvertibleErrorCode());<br>
        >> +  return
        std::unique_ptr<ChildProcessJITLinkExecutor>(<br>
        >> +      new
        ChildProcessJITLinkExecutor(std::move(ExecutablePath)));<br>
        >> +}<br>
        >> +<br>
        >> +TCPSocketJITLinkExecutor::TCPSocketJITLinkExecutor(<br>
        >> +    std::unique_ptr<RemoteTargetProcessControl>
        TPC) {<br>
        >> +  this->TPC = std::move(TPC);<br>
        >> +}<br>
        >> +<br>
        >> +#ifndef LLVM_ON_UNIX<br>
        >> +<br>
        >> +// FIXME: Add support for Windows.<br>
        >> +Error
        ChildProcessJITLinkExecutor::launch(ExecutionSession &ES) {<br>
        >> +  return make_error<StringError>(<br>
        >> +      "Remote JITing not yet supported on non-unix
        platforms",<br>
        >> +      inconvertibleErrorCode());<br>
        >> +}<br>
        >> +<br>
        >> +// FIXME: Add support for Windows.<br>
        >>
        +Expected<std::unique_ptr<TCPSocketJITLinkExecutor>><br>
        >> +JITLinkExecutor::ConnectTCPSocket(StringRef
        NetworkAddress,<br>
        >> +                                  ExecutionSession
        &ES) {<br>
        >> +  return make_error<StringError>(<br>
        >> +      "Remote JITing not yet supported on non-unix
        platforms",<br>
        >> +      inconvertibleErrorCode());<br>
        >> +}<br>
        >> +<br>
        >> +#else<br>
        >> +<br>
        >> +Error
        ChildProcessJITLinkExecutor::launch(ExecutionSession &ES) {<br>
        >> +  constexpr int ReadEnd = 0;<br>
        >> +  constexpr int WriteEnd = 1;<br>
        >> +<br>
        >> +  // Pipe FDs.<br>
        >> +  int ToExecutor[2];<br>
        >> +  int FromExecutor[2];<br>
        >> +<br>
        >> +  // Create pipes to/from the executor..<br>
        >> +  if (pipe(ToExecutor) != 0 || pipe(FromExecutor) !=
        0)<br>
        >> +    return make_error<StringError>("Unable to
        create pipe for executor",<br>
        >> +                                  
        inconvertibleErrorCode());<br>
        >> +<br>
        >> +  ProcessID = fork();<br>
        >> +  if (ProcessID == 0) {<br>
        >> +    // In the child...<br>
        >> +<br>
        >> +    // Close the parent ends of the pipes<br>
        >> +    close(ToExecutor[WriteEnd]);<br>
        >> +    close(FromExecutor[ReadEnd]);<br>
        >> +<br>
        >> +    // Execute the child process.<br>
        >> +    std::unique_ptr<char[]> ExecPath,
        FDSpecifier;<br>
        >> +    {<br>
        >> +      ExecPath =
        std::make_unique<char[]>(ExecutablePath.size() + 1);<br>
        >> +      strcpy(ExecPath.get(), ExecutablePath.data());<br>
        >> +<br>
        >> +      std::string FDSpecifierStr("filedescs=");<br>
        >> +      FDSpecifierStr += utostr(ToExecutor[ReadEnd]);<br>
        >> +      FDSpecifierStr += ',';<br>
        >> +      FDSpecifierStr +=
        utostr(FromExecutor[WriteEnd]);<br>
        >> +      FDSpecifier =
        std::make_unique<char[]>(FDSpecifierStr.size() + 1);<br>
        >> +      strcpy(FDSpecifier.get(),
        FDSpecifierStr.c_str());<br>
        >> +    }<br>
        >> +<br>
        >> +    char *const Args[] = {ExecPath.get(),
        FDSpecifier.get(), nullptr};<br>
        >> +    int RC = execvp(ExecPath.get(), Args);<br>
        >> +    if (RC != 0)<br>
        >> +      return make_error<StringError>(<br>
        >> +          "Unable to launch out-of-process executor '"
        + ExecutablePath + "'\n",<br>
        >> +          inconvertibleErrorCode());<br>
        >> +<br>
        >> +    llvm_unreachable("Fork won't return in success
        case");<br>
        >> +  }<br>
        >> +  // else we're the parent...<br>
        >> +<br>
        >> +  // Close the child ends of the pipes<br>
        >> +  close(ToExecutor[ReadEnd]);<br>
        >> +  close(FromExecutor[WriteEnd]);<br>
        >> +<br>
        >> +  auto Channel =<br>
        >> +    
         std::make_unique<RPCChannel>(FromExecutor[ReadEnd],
        ToExecutor[WriteEnd]);<br>
        >> +  auto Endpoint =<br>
        >> +    
 std::make_unique<RemoteTargetProcessControl::RPCEndpoint>(*Channel,
        true);<br>
        >> +<br>
        >> +  TPC =
        std::make_unique<RemoteTargetProcessControl>(ES,
        std::move(Channel),<br>
        >> +                                                    
        std::move(Endpoint));<br>
        >> +<br>
        >> +  if (auto Err = TPC->initializeORCRPCTPCBase())<br>
        >> +    return joinErrors(std::move(Err),
        TPC->disconnect());<br>
        >> +<br>
        >> +  TPC->initializeMemoryManagement();<br>
        >> +<br>
        >> +  shared::registerStringError<RPCChannel>();<br>
        >> +  return Error::success();<br>
        >> +}<br>
        >> +<br>
        >> +static Expected<int>
        connectTCPSocketImpl(std::string Host,<br>
        >> +                                          std::string
        PortStr) {<br>
        >> +  addrinfo *AI;<br>
        >> +  addrinfo Hints{};<br>
        >> +  Hints.ai_family = AF_INET;<br>
        >> +  Hints.ai_socktype = SOCK_STREAM;<br>
        >> +  Hints.ai_flags = AI_NUMERICSERV;<br>
        >> +<br>
        >> +  if (int EC = getaddrinfo(Host.c_str(),
        PortStr.c_str(), &Hints, &AI))<br>
        >> +    return make_error<StringError>(<br>
        >> +        formatv("address resolution failed ({0})",
        gai_strerror(EC)),<br>
        >> +        inconvertibleErrorCode());<br>
        >> +<br>
        >> +  // Cycle through the returned addrinfo structures
        and connect to the first<br>
        >> +  // reachable endpoint.<br>
        >> +  int SockFD;<br>
        >> +  addrinfo *Server;<br>
        >> +  for (Server = AI; Server != nullptr; Server =
        Server->ai_next) {<br>
        >> +    // If socket fails, maybe it's because the address
        family is not supported.<br>
        >> +    // Skip to the next addrinfo structure.<br>
        >> +    if ((SockFD = socket(AI->ai_family,
        AI->ai_socktype, AI->ai_protocol)) < 0)<br>
        >> +      continue;<br>
        >> +<br>
        >> +    // If connect works, we exit the loop with a
        working socket.<br>
        >> +    if (connect(SockFD, Server->ai_addr,
        Server->ai_addrlen) == 0)<br>
        >> +      break;<br>
        >> +<br>
        >> +    close(SockFD);<br>
        >> +  }<br>
        >> +  freeaddrinfo(AI);<br>
        >> +<br>
        >> +  // Did we reach the end of the loop without
        connecting to a valid endpoint?<br>
        >> +  if (Server == nullptr)<br>
        >> +    return make_error<StringError>("invalid
        hostname",<br>
        >> +                                  
        inconvertibleErrorCode());<br>
        >> +<br>
        >> +  return SockFD;<br>
        >> +}<br>
        >> +<br>
        >>
        +Expected<std::unique_ptr<TCPSocketJITLinkExecutor>><br>
        >> +JITLinkExecutor::ConnectTCPSocket(StringRef
        NetworkAddress,<br>
        >> +                                  ExecutionSession
        &ES) {<br>
        >> +  auto CreateErr = [NetworkAddress](StringRef Details)
        {<br>
        >> +    return make_error<StringError>(<br>
        >> +        formatv("Failed to connect TCP socket '{0}':
        {1}", NetworkAddress,<br>
        >> +                Details),<br>
        >> +        inconvertibleErrorCode());<br>
        >> +  };<br>
        >> +<br>
        >> +  StringRef Host, PortStr;<br>
        >> +  std::tie(Host, PortStr) = NetworkAddress.split(':');<br>
        >> +  if (Host.empty())<br>
        >> +    return CreateErr("host name cannot be empty");<br>
        >> +  if (PortStr.empty())<br>
        >> +    return CreateErr("port cannot be empty");<br>
        >> +  int Port = 0;<br>
        >> +  if (PortStr.getAsInteger(10, Port))<br>
        >> +    return CreateErr("port number is not a valid
        integer");<br>
        >> +<br>
        >> +  Expected<int> SockFD =
        connectTCPSocketImpl(Host.str(), PortStr.str());<br>
        >> +  if (!SockFD)<br>
        >> +    return CreateErr(toString(SockFD.takeError()));<br>
        >> +<br>
        >> +  auto Channel =
        std::make_unique<RPCChannel>(*SockFD, *SockFD);<br>
        >> +  auto Endpoint =<br>
        >> +    
 std::make_unique<RemoteTargetProcessControl::RPCEndpoint>(*Channel,
        true);<br>
        >> +<br>
        >> +  auto TPC =
        std::make_unique<RemoteTargetProcessControl>(<br>
        >> +      ES, std::move(Channel), std::move(Endpoint));<br>
        >> +<br>
        >> +  if (auto Err = TPC->initializeORCRPCTPCBase())<br>
        >> +    return joinErrors(std::move(Err),
        TPC->disconnect());<br>
        >> +<br>
        >> +  TPC->initializeMemoryManagement();<br>
        >> +  shared::registerStringError<RPCChannel>();<br>
        >> +<br>
        >> +  return
        std::unique_ptr<TCPSocketJITLinkExecutor>(<br>
        >> +      new TCPSocketJITLinkExecutor(std::move(TPC)));<br>
        >> +}<br>
        >> +<br>
        >> +#endif<br>
        >><br>
        >> diff  --git
        a/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.h
b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.h<br>
        >> new file mode 100644<br>
        >> index 000000000000..e629c0e036f5<br>
        >> --- /dev/null<br>
        >> +++
        b/llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.h<br>
        >> @@ -0,0 +1,111 @@<br>
        >> +//===-- RemoteJITUtils.h - Utilities for remote-JITing
        ----------*- C++ -*-===//<br>
        >> +//<br>
        >> +// Part of the LLVM Project, under the Apache License
        v2.0 with LLVM Exceptions.<br>
        >> +// See <a href="https://llvm.org/LICENSE.txt" target="_blank">https://llvm.org/LICENSE.txt</a> for
        license information.<br>
        >> +// SPDX-License-Identifier: Apache-2.0 WITH
        LLVM-exception<br>
        >> +//<br>
        >>
+//===----------------------------------------------------------------------===//<br>
        >> +//<br>
        >> +// Utilities for TargetProcessControl-based remote
        JITing with Orc and JITLink.<br>
        >> +//<br>
        >>
+//===----------------------------------------------------------------------===//<br>
        >> +<br>
        >> +#ifndef
        LLVM_EXAMPLES_ORCV2EXAMPLES_LLJITWITHREMOTEDEBUGGING_REMOTEJITUTILS_H<br>
        >> +#define
        LLVM_EXAMPLES_ORCV2EXAMPLES_LLJITWITHREMOTEDEBUGGING_REMOTEJITUTILS_H<br>
        >> +<br>
        >> +#include "llvm/ADT/ArrayRef.h"<br>
        >> +#include "llvm/ADT/StringRef.h"<br>
        >> +#include "llvm/ADT/Triple.h"<br>
        >> +#include "llvm/ExecutionEngine/JITSymbol.h"<br>
        >> +#include "llvm/ExecutionEngine/Orc/Core.h"<br>
        >> +#include "llvm/ExecutionEngine/Orc/Layer.h"<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"<br>
        >> +#include
        "llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h"<br>
        >> +#include "llvm/Support/Error.h"<br>
        >> +<br>
        >> +#include <memory><br>
        >> +#include <string><br>
        >> +<br>
        >> +#if !defined(_MSC_VER) &&
        !defined(__MINGW32__)<br>
        >> +#include <unistd.h><br>
        >> +#else<br>
        >> +#include <io.h><br>
        >> +#endif<br>
        >> +<br>
        >> +namespace llvm {<br>
        >> +namespace orc {<br>
        >> +<br>
        >> +class ChildProcessJITLinkExecutor;<br>
        >> +class RemoteTargetProcessControl;<br>
        >> +class TCPSocketJITLinkExecutor;<br>
        >> +<br>
        >> +class JITLinkExecutor {<br>
        >> +public:<br>
        >> +  using RPCChannel = shared::FDRawByteChannel;<br>
        >> +<br>
        >> +  /// Create a JITLinkExecutor for the given
        exectuable on disk.<br>
        >> +  static
        Expected<std::unique_ptr<ChildProcessJITLinkExecutor>><br>
        >> +  CreateLocal(std::string ExecutablePath);<br>
        >> +<br>
        >> +  /// Find the default exectuable on disk and create a
        JITLinkExecutor for it.<br>
        >> +  static
        Expected<std::unique_ptr<ChildProcessJITLinkExecutor>><br>
        >> +  FindLocal(const char *JITArgv0);<br>
        >> +<br>
        >> +  /// Create a JITLinkExecutor that connects to the
        given network address<br>
        >> +  /// through a TCP socket. A valid NetworkAddress
        provides hostname and port,<br>
        >> +  /// e.g. localhost:20000.<br>
        >> +  static
        Expected<std::unique_ptr<TCPSocketJITLinkExecutor>><br>
        >> +  ConnectTCPSocket(StringRef NetworkAddress,
        ExecutionSession &ES);<br>
        >> +<br>
        >> +  // Implement ObjectLinkingLayerCreator<br>
        >> +  Expected<std::unique_ptr<ObjectLayer>>
        operator()(ExecutionSession &,<br>
        >> +                                                  
         const Triple &);<br>
        >> +<br>
        >> +  Error addDebugSupport(ObjectLayer &ObjLayer);<br>
        >> +<br>
        >> +
         Expected<std::unique_ptr<DefinitionGenerator>><br>
        >> +  loadDylib(StringRef RemotePath);<br>
        >> +<br>
        >> +  Expected<int> runAsMain(JITEvaluatedSymbol
        MainSym,<br>
        >> +                          ArrayRef<std::string>
        Args);<br>
        >> +  Error disconnect();<br>
        >> +<br>
        >> +  virtual ~JITLinkExecutor();<br>
        >> +<br>
        >> +protected:<br>
        >> +  std::unique_ptr<RemoteTargetProcessControl>
        TPC;<br>
        >> +<br>
        >> +  JITLinkExecutor();<br>
        >> +};<br>
        >> +<br>
        >> +/// JITLinkExecutor that runs in a child process on
        the local machine.<br>
        >> +class ChildProcessJITLinkExecutor : public
        JITLinkExecutor {<br>
        >> +public:<br>
        >> +  Error launch(ExecutionSession &ES);<br>
        >> +<br>
        >> +  pid_t getPID() const { return ProcessID; }<br>
        >> +  StringRef getPath() const { return ExecutablePath; }<br>
        >> +<br>
        >> +private:<br>
        >> +  std::string ExecutablePath;<br>
        >> +  pid_t ProcessID;<br>
        >> +<br>
        >> +  ChildProcessJITLinkExecutor(std::string
        ExecutablePath)<br>
        >> +      : ExecutablePath(std::move(ExecutablePath)) {}<br>
        >> +<br>
        >> +  static std::string defaultPath(const char
        *HostArgv0, StringRef ExecutorName);<br>
        >> +  friend class JITLinkExecutor;<br>
        >> +};<br>
        >> +<br>
        >> +/// JITLinkExecutor connected through a TCP socket.<br>
        >> +class TCPSocketJITLinkExecutor : public
        JITLinkExecutor {<br>
        >> +private:<br>
        >> +
 TCPSocketJITLinkExecutor(std::unique_ptr<RemoteTargetProcessControl>
        TPC);<br>
        >> +<br>
        >> +  friend class JITLinkExecutor;<br>
        >> +};<br>
        >> +<br>
        >> +} // namespace orc<br>
        >> +} // namespace llvm<br>
        >> +<br>
        >> +#endif<br>
        >><br>
        >> diff  --git
        a/llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1.c
        b/llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1.c<br>
        >> new file mode 100644<br>
        >> index 000000000000..3a5c2bcefee1<br>
        >> --- /dev/null<br>
        >> +++
        b/llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1.c<br>
        >> @@ -0,0 +1,2 @@<br>
        >> +int sub1(int x) { return x - 1; }<br>
        >> +int main(int argc, char **argv) { return sub1(argc); }<br>
        >><br>
        >> diff  --git
        a/llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1_elf.ll
        b/llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1_elf.ll<br>
        >> new file mode 100644<br>
        >> index 000000000000..659dbe109ec6<br>
        >> --- /dev/null<br>
        >> +++
        b/llvm/test/Examples/OrcV2Examples/Inputs/argc_sub1_elf.ll<br>
        >> @@ -0,0 +1,52 @@<br>
        >> +; ModuleID = 'argc_sub1.c'<br>
        >> +target triple = "x86_64-unknown-unknown-elf"<br>
        >> +<br>
        >> +define i32 @sub1(i32) !dbg !8 {<br>
        >> +  call void @llvm.dbg.value(metadata i32 %0, metadata
        !13, metadata !DIExpression()), !dbg !14<br>
        >> +  %2 = add nsw i32 %0, -1, !dbg !15<br>
        >> +  ret i32 %2, !dbg !16<br>
        >> +}<br>
        >> +<br>
        >> +define i32 @main(i32, i8** nocapture readnone) !dbg
        !17 {<br>
        >> +  call void @llvm.dbg.value(metadata i32 %0, metadata
        !24, metadata !DIExpression()), !dbg !26<br>
        >> +  call void @llvm.dbg.value(metadata i8** %1, metadata
        !25, metadata !DIExpression()), !dbg !27<br>
        >> +  %3 = tail call i32 @sub1(i32 %0), !dbg !28<br>
        >> +  ret i32 %3, !dbg !29<br>
        >> +}<br>
        >> +<br>
        >> +declare void @llvm.dbg.value(metadata, metadata,
        metadata)<br>
        >> +<br>
        >> +!<a href="http://llvm.dbg.cu" target="_blank">llvm.dbg.cu</a>
        = !{!0}<br>
        >> +!llvm.module.flags = !{!3, !4, !5, !6}<br>
        >> +!llvm.ident = !{!7}<br>
        >> +<br>
        >> +!0 = distinct !DICompileUnit(language: DW_LANG_C99,
        file: !1, producer: "clang version 7.0.1-8+deb10u2
        (tags/RELEASE_701/final)", isOptimized: true, runtimeVersion: 0,
        emissionKind: FullDebug, enums: !2)<br>
        >> +!1 = !DIFile(filename: "argc_sub1.c", directory:
        "Inputs/")<br>
        >> +!2 = !{}<br>
        >> +!3 = !{i32 2, !"Dwarf Version", i32 4}<br>
        >> +!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
        >> +!5 = !{i32 1, !"wchar_size", i32 4}<br>
        >> +!6 = !{i32 7, !"PIC Level", i32 2}<br>
        >> +!7 = !{!"clang version 7.0.1-8+deb10u2
        (tags/RELEASE_701/final)"}<br>
        >> +!8 = distinct !DISubprogram(name: "sub1", scope: !1,
        file: !1, line: 1, type: !9, isLocal: false, isDefinition: true,
        scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit:
        !0, retainedNodes: !12)<br>
        >> +!9 = !DISubroutineType(types: !10)<br>
        >> +!10 = !{!11, !11}<br>
        >> +!11 = !DIBasicType(name: "int", size: 32, encoding:
        DW_ATE_signed)<br>
        >> +!12 = !{!13}<br>
        >> +!13 = !DILocalVariable(name: "x", arg: 1, scope: !8,
        file: !1, line: 1, type: !11)<br>
        >> +!14 = !DILocation(line: 1, column: 14, scope: !8)<br>
        >> +!15 = !DILocation(line: 1, column: 28, scope: !8)<br>
        >> +!16 = !DILocation(line: 1, column: 19, scope: !8)<br>
        >> +!17 = distinct !DISubprogram(name: "main", scope: !1,
        file: !1, line: 2, type: !18, isLocal: false, isDefinition:
        true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true,
        unit: !0, retainedNodes: !23)<br>
        >> +!18 = !DISubroutineType(types: !19)<br>
        >> +!19 = !{!11, !11, !20}<br>
        >> +!20 = !DIDerivedType(tag: DW_TAG_pointer_type,
        baseType: !21, size: 64)<br>
        >> +!21 = !DIDerivedType(tag: DW_TAG_pointer_type,
        baseType: !22, size: 64)<br>
        >> +!22 = !DIBasicType(name: "char", size: 8, encoding:
        DW_ATE_signed_char)<br>
        >> +!23 = !{!24, !25}<br>
        >> +!24 = !DILocalVariable(name: "argc", arg: 1, scope:
        !17, file: !1, line: 2, type: !11)<br>
        >> +!25 = !DILocalVariable(name: "argv", arg: 2, scope:
        !17, file: !1, line: 2, type: !20)<br>
        >> +!26 = !DILocation(line: 2, column: 14, scope: !17)<br>
        >> +!27 = !DILocation(line: 2, column: 27, scope: !17)<br>
        >> +!28 = !DILocation(line: 2, column: 42, scope: !17)<br>
        >> +!29 = !DILocation(line: 2, column: 35, scope: !17)<br>
        >><br>
        >> diff  --git
        a/llvm/test/Examples/OrcV2Examples/lljit-with-remote-debugging.test
b/llvm/test/Examples/OrcV2Examples/lljit-with-remote-debugging.test<br>
        >> new file mode 100644<br>
        >> index 000000000000..a9c3946b55e2<br>
        >> --- /dev/null<br>
        >> +++
        b/llvm/test/Examples/OrcV2Examples/lljit-with-remote-debugging.test<br>
        >> @@ -0,0 +1,10 @@<br>
        >> +# This test makes sure that the example builds and
        executes as expected.<br>
        >> +# Instructions for debugging can be found in
        LLJITWithRemoteDebugging.cpp<br>
        >> +<br>
        >> +# RUN: LLJITWithRemoteDebugging
        %p/Inputs/argc_sub1_elf.ll<br>
        >> +# CHECK: Running: {{.*}}/Inputs/argc_sub1_elf.ll<br>
        >> +# CHECK: Exit code: 0<br>
        >> +<br>
        >> +# RUN: LLJITWithRemoteDebugging
        %p/Inputs/argc_sub1_elf.ll --args 2nd 3rd 4th<br>
        >> +# CHECK: Running: {{.*}}/Inputs/argc_sub1_elf.ll 2nd
        3rd 4th<br>
        >> +# CHECK: Exit code: 3<br>
        >><br>
        >><br>
        >><br>
        >> _______________________________________________<br>
        >> llvm-commits mailing list<br>
        >> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
        >> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
        ><br>
        > --<br>
        > <a href="https://flowcrypt.com/pub/stefan.graenitz@gmail.com" target="_blank">https://flowcrypt.com/pub/stefan.graenitz@gmail.com</a></div>
    </blockquote>
    <pre cols="72">-- 
<a href="https://flowcrypt.com/pub/stefan.graenitz@gmail.com" target="_blank">https://flowcrypt.com/pub/stefan.graenitz@gmail.com</a></pre>
  </div>

</blockquote></div></div>