18
18
#include " clang/Frontend/CompilerInstance.h"
19
19
#include " clang/Frontend/TextDiagnosticPrinter.h"
20
20
#include " clang/Interpreter/Interpreter.h"
21
+ #include " clang/Interpreter/RemoteJITUtils.h"
21
22
#include " clang/Interpreter/Value.h"
22
23
#include " clang/Sema/Lookup.h"
23
24
#include " clang/Sema/Sema.h"
25
+ #include " llvm/TargetParser/Host.h"
24
26
25
27
#include " gmock/gmock.h"
26
28
#include " gtest/gtest.h"
27
29
28
30
using namespace clang ;
29
31
32
+ static const llvm::ExitOnError ExitOnError;
33
+
30
34
int Global = 42 ;
31
35
// JIT reports symbol not found on Windows without the visibility attribute.
32
36
REPL_EXTERNAL_VISIBILITY int getGlobal () { return Global; }
@@ -52,6 +56,99 @@ createInterpreter(const Args &ExtraArgs = {},
52
56
return cantFail (clang::Interpreter::create (std::move (CI)));
53
57
}
54
58
59
+ static std::string getExecutorPath () {
60
+ llvm::SmallString<256 > ExecutorPath (llvm::sys::fs::getMainExecutable (
61
+ nullptr , reinterpret_cast <void *>(&getExecutorPath)));
62
+ llvm::sys::path::remove_filename (ExecutorPath);
63
+
64
+ llvm::sys::path::remove_filename (ExecutorPath); // Remove "Interpreter"
65
+ llvm::sys::path::remove_filename (ExecutorPath); // Remove "unittests"
66
+ llvm::sys::path::remove_filename (ExecutorPath); // Remove "clang"
67
+ llvm::sys::path::remove_filename (ExecutorPath); // Remove "tools"
68
+
69
+ llvm::sys::path::append (ExecutorPath, " bin" , " llvm-jitlink-executor" );
70
+ return ExecutorPath.str ().str ();
71
+ }
72
+
73
+ static std::string getOrcRuntimePath () {
74
+ llvm::SmallString<256 > RuntimePath (llvm::sys::fs::getMainExecutable (
75
+ nullptr , reinterpret_cast <void *>(&getOrcRuntimePath)));
76
+
77
+ llvm::sys::path::remove_filename (RuntimePath);
78
+
79
+ llvm::sys::path::remove_filename (RuntimePath); // Remove "Interpreter"
80
+ llvm::sys::path::remove_filename (RuntimePath); // Remove "unittests"
81
+ llvm::sys::path::remove_filename (RuntimePath); // Remove "clang"
82
+ llvm::sys::path::remove_filename (RuntimePath); // Remove "tools"
83
+
84
+ llvm::sys::path::append (RuntimePath, " lib" , " clang" , " 21" , " lib" );
85
+
86
+ // Add platform-specific runtime library
87
+ llvm::Triple SystemTriple (llvm::sys::getProcessTriple ());
88
+ if (SystemTriple.isOSDarwin ()) {
89
+ llvm::sys::path::append (RuntimePath, " darwin" , " liborc_rt_osx.a" );
90
+ } else if (SystemTriple.isOSLinux ()) {
91
+ llvm::sys::path::append (RuntimePath, " linux" , " liborc_rt.a" );
92
+ } else {
93
+ // Add other platforms as needed
94
+ llvm::sys::path::append (RuntimePath, " liborc_rt.a" );
95
+ }
96
+
97
+ return RuntimePath.str ().str ();
98
+ }
99
+
100
+ static std::unique_ptr<Interpreter>
101
+ createInterpreterWithRemoteExecution (const Args &ExtraArgs = {},
102
+ DiagnosticConsumer *Client = nullptr ) {
103
+ Args ClangArgs = {" -Xclang" , " -emit-llvm-only" };
104
+ llvm::append_range (ClangArgs, ExtraArgs);
105
+ auto CB = clang::IncrementalCompilerBuilder ();
106
+ CB.SetCompilerArgs (ClangArgs);
107
+ auto CI = cantFail (CB.CreateCpp ());
108
+ if (Client)
109
+ CI->getDiagnostics ().setClient (Client, /* ShouldOwnClient=*/ false );
110
+
111
+ std::unique_ptr<llvm::orc::LLJITBuilder> JB;
112
+
113
+ llvm::Triple SystemTriple (llvm::sys::getProcessTriple ());
114
+
115
+ std::cout << " System Triple: " << SystemTriple.getTriple () << " \n " ;
116
+ std::cout << " Executor Path: " << getExecutorPath () << " \n " ;
117
+
118
+ if ((SystemTriple.isOSBinFormatELF () || SystemTriple.isOSBinFormatMachO ())) {
119
+ std::string OOPExecutor = getExecutorPath ();
120
+ bool UseSharedMemory = false ;
121
+ std::string SlabAllocateSizeString = " " ;
122
+ std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
123
+ EPC = ExitOnError (launchExecutor (OOPExecutor, UseSharedMemory,
124
+ SlabAllocateSizeString,
125
+ [=] { // Lambda defined inline
126
+ auto redirect = [](int from, int to) {
127
+ if (from != to) {
128
+ dup2 (from, to);
129
+ close (from);
130
+ }
131
+ };
132
+
133
+ redirect (0 , STDIN_FILENO);
134
+ redirect (1 , STDOUT_FILENO);
135
+ redirect (2 , STDERR_FILENO);
136
+
137
+ setvbuf (stdout, nullptr , _IONBF, 0 );
138
+ setvbuf (stderr, nullptr , _IONBF, 0 );
139
+ }));
140
+ std::string OrcRuntimePath = getOrcRuntimePath ();
141
+
142
+ if (EPC) {
143
+ CB.SetTargetTriple (EPC->getTargetTriple ().getTriple ());
144
+ JB = ExitOnError (clang::Interpreter::createLLJITBuilder (std::move (EPC),
145
+ OrcRuntimePath));
146
+ }
147
+ }
148
+
149
+ return cantFail (clang::Interpreter::create (std::move (CI), std::move (JB)));
150
+ }
151
+
55
152
static size_t DeclsSize (TranslationUnitDecl *PTUDecl) {
56
153
return std::distance (PTUDecl->decls ().begin (), PTUDecl->decls ().end ());
57
154
}
@@ -68,6 +165,18 @@ TEST_F(InterpreterTest, Sanity) {
68
165
EXPECT_EQ (1U , DeclsSize (R2.TUPart ));
69
166
}
70
167
168
+ TEST_F (InterpreterTest, SanityWithRemoteExecution) {
169
+ std::unique_ptr<Interpreter> Interp = createInterpreterWithRemoteExecution ();
170
+
171
+ using PTU = PartialTranslationUnit;
172
+
173
+ PTU &R1 (cantFail (Interp->Parse (" void g(); void g() {}" )));
174
+ EXPECT_EQ (2U , DeclsSize (R1.TUPart ));
175
+
176
+ PTU &R2 (cantFail (Interp->Parse (" int i;" )));
177
+ EXPECT_EQ (1U , DeclsSize (R2.TUPart ));
178
+ }
179
+
71
180
static std::string DeclToString (Decl *D) {
72
181
return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString ();
73
182
}
0 commit comments