Skip to content

Commit 79849c3

Browse files
author
kr-2003
committed
pipes for redirection in oop jit
1 parent d889a74 commit 79849c3

File tree

4 files changed

+161
-2
lines changed

4 files changed

+161
-2
lines changed

clang/include/clang/Interpreter/RemoteJITUtils.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
2828
launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
29-
llvm::StringRef SlabAllocateSizeString);
29+
llvm::StringRef SlabAllocateSizeString,
30+
std::function<void()> CustomizeFork = nullptr);
3031

3132
/// Create a JITLinkExecutor that connects to the given network address
3233
/// through a TCP socket. A valid NetworkAddress provides hostname and port,
@@ -35,4 +36,13 @@ llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
3536
connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
3637
llvm::StringRef SlabAllocateSizeString);
3738

39+
#ifdef LLVM_ON_UNIX
40+
/// Returns PID of last launched executor.
41+
pid_t getLastLaunchedExecutorPID();
42+
43+
/// Returns PID of nth launched executor.
44+
/// 1-based indexing.
45+
pid_t getNthLaunchedExecutorPID(int n);
46+
#endif
47+
3848
#endif // LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H

clang/lib/Interpreter/RemoteJITUtils.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
using namespace llvm;
3434
using namespace llvm::orc;
3535

36+
#if LLVM_ON_UNIX
37+
static std::vector<pid_t> LaunchedExecutorPID;
38+
#endif
39+
3640
Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
3741
SizeString = SizeString.trim();
3842

@@ -91,7 +95,8 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
9195

9296
Expected<std::unique_ptr<SimpleRemoteEPC>>
9397
launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
94-
llvm::StringRef SlabAllocateSizeString) {
98+
llvm::StringRef SlabAllocateSizeString,
99+
std::function<void()> CustomizeFork) {
95100
#ifndef LLVM_ON_UNIX
96101
// FIXME: Add support for Windows.
97102
return make_error<StringError>("-" + ExecutablePath +
@@ -134,6 +139,9 @@ launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
134139
close(ToExecutor[WriteEnd]);
135140
close(FromExecutor[ReadEnd]);
136141

142+
if (CustomizeFork)
143+
CustomizeFork();
144+
137145
// Execute the child process.
138146
std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
139147
{
@@ -155,6 +163,8 @@ launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
155163
<< ExecutorPath.get() << "\"\n";
156164
exit(1);
157165
}
166+
} else {
167+
LaunchedExecutorPID.push_back(ChildPID);
158168
}
159169
// else we're the parent...
160170

@@ -265,3 +275,18 @@ connectTCPSocket(StringRef NetworkAddress, bool UseSharedMemory,
265275
std::move(S), *SockFD, *SockFD);
266276
#endif
267277
}
278+
279+
#if LLVM_ON_UNIX
280+
281+
pid_t getLastLaunchedExecutorPID() {
282+
if (!LaunchedExecutorPID.size())
283+
return -1;
284+
return LaunchedExecutorPID.back();
285+
}
286+
287+
pid_t getNthLaunchedExecutorPID(int n) {
288+
if (n - 1 < 0 || n - 1 >= static_cast<int>(LaunchedExecutorPID.size()))
289+
return -1;
290+
return LaunchedExecutorPID.at(n - 1);
291+
}
292+
#endif

clang/unittests/Interpreter/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ add_distinct_clang_unittest(ClangReplInterpreterTests
2626
TargetParser
2727
)
2828

29+
if(TARGET llvm-jitlink-executor AND TARGET compiler-rt)
30+
add_dependencies(ClangReplInterpreterTests
31+
llvm-jitlink-executor
32+
compiler-rt
33+
)
34+
endif()
35+
2936
# Exceptions on Windows are not yet supported.
3037
if(NOT WIN32)
3138
add_subdirectory(ExceptionTests)

clang/unittests/Interpreter/InterpreterTest.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,36 @@
1515
#include "clang/AST/Decl.h"
1616
#include "clang/AST/DeclGroup.h"
1717
#include "clang/AST/Mangle.h"
18+
#include "clang/Basic/Version.h"
19+
#include "clang/Config/config.h"
1820
#include "clang/Frontend/CompilerInstance.h"
1921
#include "clang/Frontend/TextDiagnosticPrinter.h"
2022
#include "clang/Interpreter/Interpreter.h"
23+
#include "clang/Interpreter/RemoteJITUtils.h"
2124
#include "clang/Interpreter/Value.h"
2225
#include "clang/Sema/Lookup.h"
2326
#include "clang/Sema/Sema.h"
27+
#include "llvm/Support/Error.h"
28+
#include "llvm/TargetParser/Host.h"
2429

2530
#include "gmock/gmock.h"
2631
#include "gtest/gtest.h"
2732

2833
using namespace clang;
2934

35+
llvm::ExitOnError ExitOnError;
36+
3037
int Global = 42;
3138
// JIT reports symbol not found on Windows without the visibility attribute.
3239
REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
3340
REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
3441

42+
#ifdef _WIN32
43+
#define STDIN_FILENO 0
44+
#define STDOUT_FILENO 1
45+
#define STDERR_FILENO 2
46+
#endif
47+
3548
namespace {
3649

3750
class InterpreterTest : public InterpreterTestBase {
@@ -52,6 +65,93 @@ createInterpreter(const Args &ExtraArgs = {},
5265
return cantFail(clang::Interpreter::create(std::move(CI)));
5366
}
5467

68+
static std::string getExecutorPath() {
69+
llvm::SmallString<256> ExecutorPath(llvm::sys::fs::getMainExecutable(
70+
nullptr, reinterpret_cast<void *>(&getExecutorPath)));
71+
llvm::sys::path::remove_filename(ExecutorPath);
72+
73+
llvm::sys::path::remove_filename(ExecutorPath); // Remove "Interpreter"
74+
llvm::sys::path::remove_filename(ExecutorPath); // Remove "unittests"
75+
llvm::sys::path::remove_filename(ExecutorPath); // Remove "clang"
76+
llvm::sys::path::remove_filename(ExecutorPath); // Remove "tools"
77+
78+
llvm::sys::path::append(ExecutorPath, "bin", "llvm-jitlink-executor");
79+
return ExecutorPath.str().str();
80+
}
81+
82+
static std::string getOrcRuntimePath() {
83+
llvm::SmallString<256> RuntimePath(llvm::sys::fs::getMainExecutable(
84+
nullptr, reinterpret_cast<void *>(&getOrcRuntimePath)));
85+
86+
llvm::sys::path::remove_filename(RuntimePath);
87+
88+
llvm::sys::path::remove_filename(RuntimePath); // Remove "Interpreter"
89+
llvm::sys::path::remove_filename(RuntimePath); // Remove "unittests"
90+
llvm::sys::path::remove_filename(RuntimePath); // Remove "clang"
91+
llvm::sys::path::remove_filename(RuntimePath); // Remove "tools"
92+
93+
llvm::sys::path::append(RuntimePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
94+
CLANG_VERSION_MAJOR_STRING, "lib");
95+
96+
llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
97+
if (SystemTriple.isOSBinFormatMachO()) {
98+
llvm::sys::path::append(RuntimePath, "darwin", "liborc_rt_osx.a");
99+
} else if (SystemTriple.isOSBinFormatELF()) {
100+
llvm::sys::path::append(RuntimePath, "x86_64-unknown-linux-gnu",
101+
"liborc_rt.a");
102+
}
103+
104+
return RuntimePath.str().str();
105+
}
106+
107+
static std::unique_ptr<Interpreter>
108+
createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
109+
DiagnosticConsumer *Client = nullptr) {
110+
Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
111+
llvm::append_range(ClangArgs, ExtraArgs);
112+
auto CB = clang::IncrementalCompilerBuilder();
113+
CB.SetCompilerArgs(ClangArgs);
114+
auto CI = cantFail(CB.CreateCpp());
115+
if (Client)
116+
CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
117+
118+
std::unique_ptr<llvm::orc::LLJITBuilder> JB;
119+
120+
llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
121+
122+
if ((SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO())) {
123+
std::string OOPExecutor = getExecutorPath();
124+
std::string OrcRuntimePath = getOrcRuntimePath();
125+
bool UseSharedMemory = false;
126+
std::string SlabAllocateSizeString = "";
127+
std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
128+
EPC = ExitOnError(launchExecutor(OOPExecutor, UseSharedMemory,
129+
SlabAllocateSizeString,
130+
[=] { // Lambda defined inline
131+
auto redirect = [](int from, int to) {
132+
if (from != to) {
133+
dup2(from, to);
134+
close(from);
135+
}
136+
};
137+
138+
redirect(0, STDIN_FILENO);
139+
redirect(1, STDOUT_FILENO);
140+
redirect(2, STDERR_FILENO);
141+
142+
setvbuf(stdout, nullptr, _IONBF, 0);
143+
setvbuf(stderr, nullptr, _IONBF, 0);
144+
}));
145+
if (EPC) {
146+
CB.SetTargetTriple(EPC->getTargetTriple().getTriple());
147+
JB = ExitOnError(clang::Interpreter::createLLJITBuilder(std::move(EPC),
148+
OrcRuntimePath));
149+
}
150+
}
151+
152+
return cantFail(clang::Interpreter::create(std::move(CI), std::move(JB)));
153+
}
154+
55155
static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
56156
return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
57157
}
@@ -68,6 +168,23 @@ TEST_F(InterpreterTest, Sanity) {
68168
EXPECT_EQ(1U, DeclsSize(R2.TUPart));
69169
}
70170

171+
TEST_F(InterpreterTest, SanityWithRemoteExecution) {
172+
if (!HostSupportsJIT())
173+
GTEST_SKIP();
174+
175+
std::string OrcRuntimePath = getOrcRuntimePath();
176+
177+
std::unique_ptr<Interpreter> Interp = createInterpreterWithRemoteExecution();
178+
179+
using PTU = PartialTranslationUnit;
180+
181+
PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));
182+
EXPECT_EQ(2U, DeclsSize(R1.TUPart));
183+
184+
PTU &R2(cantFail(Interp->Parse("int i;")));
185+
EXPECT_EQ(1U, DeclsSize(R2.TUPart));
186+
}
187+
71188
static std::string DeclToString(Decl *D) {
72189
return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString();
73190
}

0 commit comments

Comments
 (0)