[llvm] 258f055 - [Orc][examples] Add LLJITWithRemoteDebugging example

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 3 09:08:22 PDT 2021


On Sat, Apr 3, 2021 at 6:10 AM Stefan Gränitz <stefan.graenitz at gmail.com>
wrote:

> then run `ninja check-llvm-examples` does it fail for you?
>
> Yes fails. And with your fix in llvm/test/CMakeLists.txt it works again.
> (First time I built check-llvm-examples individually.)
>

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.

Does it reproduce with check-all for you (now that/after you've deleted the
binary and removed the fix like that)


>
> I now remember that this sort of thing happened before and required
> another ToolSubst change in llvm/test/lit.cfg.py:
> https://reviews.llvm.org/rGea7b1c79f73d8def
>
> Not sure it's necessary here too / still today. If yes, would we mimic the
> CMAKE_HOST_UNIX condition in Python
>

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))


> or just add it unconditionally? If not: Maybe the other ToolSubst's are
> obsolete as well?
>

Yeah, I really don't know anything about them.

@Eric Christopher <echristo at gmail.com> - any idea what the ToolSubst's you
updated in https://reviews.llvm.org/rGea7b1c79f73d8def are for/when they're
needed/not needed?


>
> > Also, I didn't get a message from buildmaster for this. Do we have a bot
> for your setup and is it public?
>
> Not sure - I guess probably not. We probably should have something
> building with the examples enabled.
>
> 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.
>

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... )

- Dave


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


More information about the llvm-commits mailing list