15
15
#include " clang/AST/Decl.h"
16
16
#include " clang/AST/DeclGroup.h"
17
17
#include " clang/AST/Mangle.h"
18
+ #include " clang/Basic/Version.h"
19
+ #include " clang/Config/config.h"
18
20
#include " clang/Frontend/CompilerInstance.h"
19
21
#include " clang/Frontend/TextDiagnosticPrinter.h"
20
22
#include " clang/Interpreter/Interpreter.h"
23
+ #include " clang/Interpreter/RemoteJITUtils.h"
21
24
#include " clang/Interpreter/Value.h"
22
25
#include " clang/Sema/Lookup.h"
23
26
#include " clang/Sema/Sema.h"
27
+ #include " llvm/Support/Error.h"
28
+ #include " llvm/TargetParser/Host.h"
24
29
25
30
#include " gmock/gmock.h"
26
31
#include " gtest/gtest.h"
27
32
28
33
using namespace clang ;
29
34
35
+ llvm::ExitOnError ExitOnError;
36
+
30
37
int Global = 42 ;
31
38
// JIT reports symbol not found on Windows without the visibility attribute.
32
39
REPL_EXTERNAL_VISIBILITY int getGlobal () { return Global; }
33
40
REPL_EXTERNAL_VISIBILITY void setGlobal (int val) { Global = val; }
34
41
42
+ #ifdef _WIN32
43
+ #define STDIN_FILENO 0
44
+ #define STDOUT_FILENO 1
45
+ #define STDERR_FILENO 2
46
+ #endif
47
+
35
48
namespace {
36
49
37
50
class InterpreterTest : public InterpreterTestBase {
@@ -52,6 +65,93 @@ createInterpreter(const Args &ExtraArgs = {},
52
65
return cantFail (clang::Interpreter::create (std::move (CI)));
53
66
}
54
67
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
+
55
155
static size_t DeclsSize (TranslationUnitDecl *PTUDecl) {
56
156
return std::distance (PTUDecl->decls ().begin (), PTUDecl->decls ().end ());
57
157
}
@@ -68,6 +168,23 @@ TEST_F(InterpreterTest, Sanity) {
68
168
EXPECT_EQ (1U , DeclsSize (R2.TUPart ));
69
169
}
70
170
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
+
71
188
static std::string DeclToString (Decl *D) {
72
189
return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString ();
73
190
}
0 commit comments