<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <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>
    <br>
    I now remember that this sort of thing happened before and required
    another ToolSubst change in llvm/test/lit.cfg.py:<br>
    <a class="moz-txt-link-freetext" href="https://reviews.llvm.org/rGea7b1c79f73d8def">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 or just add it
    unconditionally? If not: Maybe the other ToolSubst's are obsolete as
    well?<br>
    <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. <br>
    <br>
    <div class="moz-cite-prefix">On 03/04/2021 09:30, David Blaikie
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAENS6Ev=CF0J+MPEh_Gy7dozZLdKL3LHNe1euWJkKmvVgRu1cA@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">On Wed, Mar 31, 2021 at 1:34 AM Stefan Gränitz <<a
          href="mailto:stefan.graenitz@gmail.com" moz-do-not-send="true">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"
          moz-do-not-send="true">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"
          moz-do-not-send="true">https://github.com/llvm/llvm-project/commit/258f055ed93661900bc568350e09f467c0950486</a><br>
        >> DIFF: <a
href="https://github.com/llvm/llvm-project/commit/258f055ed93661900bc568350e09f467c0950486.diff"
          moz-do-not-send="true">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"
          moz-do-not-send="true">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"
          moz-do-not-send="true">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"
          moz-do-not-send="true">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" moz-do-not-send="true">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"
          moz-do-not-send="true">llvm-commits@lists.llvm.org</a><br>
        >> <a
          href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits"
          moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
        ><br>
        > --<br>
        > <a
          href="https://flowcrypt.com/pub/stefan.graenitz@gmail.com"
          moz-do-not-send="true">https://flowcrypt.com/pub/stefan.graenitz@gmail.com</a></div>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
<a class="moz-txt-link-freetext" href="https://flowcrypt.com/pub/stefan.graenitz@gmail.com">https://flowcrypt.com/pub/stefan.graenitz@gmail.com</a></pre>
  </body>
</html>