1 | //===------ Interpreter.cpp - Incremental Compilation and Execution -------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the component which performs incremental code |
10 | // compilation and execution. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "DeviceOffload.h" |
15 | #include "IncrementalExecutor.h" |
16 | #include "IncrementalParser.h" |
17 | #include "InterpreterUtils.h" |
18 | #include "llvm/Support/VirtualFileSystem.h" |
19 | #ifdef __EMSCRIPTEN__ |
20 | #include "Wasm.h" |
21 | #include <dlfcn.h> |
22 | #endif // __EMSCRIPTEN__ |
23 | |
24 | #include "clang/AST/ASTConsumer.h" |
25 | #include "clang/AST/ASTContext.h" |
26 | #include "clang/AST/Mangle.h" |
27 | #include "clang/AST/TypeVisitor.h" |
28 | #include "clang/Basic/DiagnosticSema.h" |
29 | #include "clang/Basic/TargetInfo.h" |
30 | #include "clang/CodeGen/CodeGenAction.h" |
31 | #include "clang/CodeGen/ModuleBuilder.h" |
32 | #include "clang/CodeGen/ObjectFilePCHContainerWriter.h" |
33 | #include "clang/Driver/Compilation.h" |
34 | #include "clang/Driver/Driver.h" |
35 | #include "clang/Driver/Job.h" |
36 | #include "clang/Driver/Options.h" |
37 | #include "clang/Driver/Tool.h" |
38 | #include "clang/Frontend/CompilerInstance.h" |
39 | #include "clang/Frontend/FrontendAction.h" |
40 | #include "clang/Frontend/MultiplexConsumer.h" |
41 | #include "clang/Frontend/TextDiagnosticBuffer.h" |
42 | #include "clang/FrontendTool/Utils.h" |
43 | #include "clang/Interpreter/Interpreter.h" |
44 | #include "clang/Interpreter/Value.h" |
45 | #include "clang/Lex/PreprocessorOptions.h" |
46 | #include "clang/Sema/Lookup.h" |
47 | #include "clang/Serialization/ObjectFilePCHContainerReader.h" |
48 | #include "llvm/ExecutionEngine/JITSymbol.h" |
49 | #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" |
50 | #include "llvm/ExecutionEngine/Orc/LLJIT.h" |
51 | #include "llvm/IR/Module.h" |
52 | #include "llvm/Support/Errc.h" |
53 | #include "llvm/Support/ErrorHandling.h" |
54 | #include "llvm/Support/raw_ostream.h" |
55 | #include "llvm/TargetParser/Host.h" |
56 | #include "llvm/Transforms/Utils/Cloning.h" // for CloneModule |
57 | |
58 | #define DEBUG_TYPE "clang-repl" |
59 | |
60 | using namespace clang; |
61 | // FIXME: Figure out how to unify with namespace init_convenience from |
62 | // tools/clang-import-test/clang-import-test.cpp |
63 | namespace { |
64 | /// Retrieves the clang CC1 specific flags out of the compilation's jobs. |
65 | /// \returns NULL on error. |
66 | static llvm::Expected<const llvm::opt::ArgStringList *> |
67 | GetCC1Arguments(DiagnosticsEngine *Diagnostics, |
68 | driver::Compilation *Compilation) { |
69 | // We expect to get back exactly one Command job, if we didn't something |
70 | // failed. Extract that job from the Compilation. |
71 | const driver::JobList &Jobs = Compilation->getJobs(); |
72 | if (!Jobs.size() || !isa<driver::Command>(Val: *Jobs.begin())) |
73 | return llvm::createStringError(EC: llvm::errc::not_supported, |
74 | S: "Driver initialization failed. " |
75 | "Unable to create a driver job" ); |
76 | |
77 | // The one job we find should be to invoke clang again. |
78 | const driver::Command *Cmd = cast<driver::Command>(Val: &(*Jobs.begin())); |
79 | if (llvm::StringRef(Cmd->getCreator().getName()) != "clang" ) |
80 | return llvm::createStringError(EC: llvm::errc::not_supported, |
81 | S: "Driver initialization failed" ); |
82 | |
83 | return &Cmd->getArguments(); |
84 | } |
85 | |
86 | static llvm::Expected<std::unique_ptr<CompilerInstance>> |
87 | CreateCI(const llvm::opt::ArgStringList &Argv) { |
88 | std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); |
89 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
90 | |
91 | // Register the support for object-file-wrapped Clang modules. |
92 | // FIXME: Clang should register these container operations automatically. |
93 | auto PCHOps = Clang->getPCHContainerOperations(); |
94 | PCHOps->registerWriter(Writer: std::make_unique<ObjectFilePCHContainerWriter>()); |
95 | PCHOps->registerReader(Reader: std::make_unique<ObjectFilePCHContainerReader>()); |
96 | |
97 | // Buffer diagnostics from argument parsing so that we can output them using |
98 | // a well formed diagnostic object. |
99 | DiagnosticOptions DiagOpts; |
100 | TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; |
101 | DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer); |
102 | bool Success = CompilerInvocation::CreateFromArgs( |
103 | Res&: Clang->getInvocation(), CommandLineArgs: llvm::ArrayRef(Argv.begin(), Argv.size()), Diags); |
104 | |
105 | // Infer the builtin include path if unspecified. |
106 | if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && |
107 | Clang->getHeaderSearchOpts().ResourceDir.empty()) |
108 | Clang->getHeaderSearchOpts().ResourceDir = |
109 | CompilerInvocation::GetResourcesPath(Argv0: Argv[0], MainAddr: nullptr); |
110 | |
111 | // Create the actual diagnostics engine. |
112 | Clang->createDiagnostics(VFS&: *llvm::vfs::getRealFileSystem()); |
113 | if (!Clang->hasDiagnostics()) |
114 | return llvm::createStringError(EC: llvm::errc::not_supported, |
115 | S: "Initialization failed. " |
116 | "Unable to create diagnostics engine" ); |
117 | |
118 | DiagsBuffer->FlushDiagnostics(Diags&: Clang->getDiagnostics()); |
119 | if (!Success) |
120 | return llvm::createStringError(EC: llvm::errc::not_supported, |
121 | S: "Initialization failed. " |
122 | "Unable to flush diagnostics" ); |
123 | |
124 | // FIXME: Merge with CompilerInstance::ExecuteAction. |
125 | llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(InputData: "" ).release(); |
126 | Clang->getPreprocessorOpts().addRemappedFile(From: "<<< inputs >>>" , To: MB); |
127 | |
128 | Clang->setTarget(TargetInfo::CreateTargetInfo( |
129 | Diags&: Clang->getDiagnostics(), Opts&: Clang->getInvocation().getTargetOpts())); |
130 | if (!Clang->hasTarget()) |
131 | return llvm::createStringError(EC: llvm::errc::not_supported, |
132 | S: "Initialization failed. " |
133 | "Target is missing" ); |
134 | |
135 | Clang->getTarget().adjust(Diags&: Clang->getDiagnostics(), Opts&: Clang->getLangOpts()); |
136 | |
137 | // Don't clear the AST before backend codegen since we do codegen multiple |
138 | // times, reusing the same AST. |
139 | Clang->getCodeGenOpts().ClearASTBeforeBackend = false; |
140 | |
141 | Clang->getFrontendOpts().DisableFree = false; |
142 | Clang->getCodeGenOpts().DisableFree = false; |
143 | return std::move(Clang); |
144 | } |
145 | |
146 | } // anonymous namespace |
147 | |
148 | namespace clang { |
149 | |
150 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
151 | IncrementalCompilerBuilder::create(std::string TT, |
152 | std::vector<const char *> &ClangArgv) { |
153 | |
154 | // If we don't know ClangArgv0 or the address of main() at this point, try |
155 | // to guess it anyway (it's possible on some platforms). |
156 | std::string MainExecutableName = |
157 | llvm::sys::fs::getMainExecutable(argv0: nullptr, MainExecAddr: nullptr); |
158 | |
159 | ClangArgv.insert(position: ClangArgv.begin(), x: MainExecutableName.c_str()); |
160 | |
161 | // Prepending -c to force the driver to do something if no action was |
162 | // specified. By prepending we allow users to override the default |
163 | // action and use other actions in incremental mode. |
164 | // FIXME: Print proper driver diagnostics if the driver flags are wrong. |
165 | // We do C++ by default; append right after argv[0] if no "-x" given |
166 | ClangArgv.insert(position: ClangArgv.end(), x: "-Xclang" ); |
167 | ClangArgv.insert(position: ClangArgv.end(), x: "-fincremental-extensions" ); |
168 | ClangArgv.insert(position: ClangArgv.end(), x: "-c" ); |
169 | |
170 | // Put a dummy C++ file on to ensure there's at least one compile job for the |
171 | // driver to construct. |
172 | ClangArgv.push_back(x: "<<< inputs >>>" ); |
173 | |
174 | // Buffer diagnostics from argument parsing so that we can output them using a |
175 | // well formed diagnostic object. |
176 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
177 | std::unique_ptr<DiagnosticOptions> DiagOpts = |
178 | CreateAndPopulateDiagOpts(Argv: ClangArgv); |
179 | TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; |
180 | DiagnosticsEngine Diags(DiagID, *DiagOpts, DiagsBuffer); |
181 | |
182 | driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags); |
183 | Driver.setCheckInputsExist(false); // the input comes from mem buffers |
184 | llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv); |
185 | std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(Args: RF)); |
186 | |
187 | if (Compilation->getArgs().hasArg(Ids: driver::options::OPT_v)) |
188 | Compilation->getJobs().Print(OS&: llvm::errs(), Terminator: "\n" , /*Quote=*/false); |
189 | |
190 | auto ErrOrCC1Args = GetCC1Arguments(Diagnostics: &Diags, Compilation: Compilation.get()); |
191 | if (auto Err = ErrOrCC1Args.takeError()) |
192 | return std::move(Err); |
193 | |
194 | return CreateCI(Argv: **ErrOrCC1Args); |
195 | } |
196 | |
197 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
198 | IncrementalCompilerBuilder::CreateCpp() { |
199 | std::vector<const char *> Argv; |
200 | Argv.reserve(n: 5 + 1 + UserArgs.size()); |
201 | Argv.push_back(x: "-xc++" ); |
202 | #ifdef __EMSCRIPTEN__ |
203 | Argv.push_back("-target" ); |
204 | Argv.push_back("wasm32-unknown-emscripten" ); |
205 | Argv.push_back("-fvisibility=default" ); |
206 | #endif |
207 | llvm::append_range(C&: Argv, R&: UserArgs); |
208 | |
209 | std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); |
210 | return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv); |
211 | } |
212 | |
213 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
214 | IncrementalCompilerBuilder::createCuda(bool device) { |
215 | std::vector<const char *> Argv; |
216 | Argv.reserve(n: 5 + 4 + UserArgs.size()); |
217 | |
218 | Argv.push_back(x: "-xcuda" ); |
219 | if (device) |
220 | Argv.push_back(x: "--cuda-device-only" ); |
221 | else |
222 | Argv.push_back(x: "--cuda-host-only" ); |
223 | |
224 | std::string SDKPathArg = "--cuda-path=" ; |
225 | if (!CudaSDKPath.empty()) { |
226 | SDKPathArg += CudaSDKPath; |
227 | Argv.push_back(x: SDKPathArg.c_str()); |
228 | } |
229 | |
230 | std::string ArchArg = "--offload-arch=" ; |
231 | if (!OffloadArch.empty()) { |
232 | ArchArg += OffloadArch; |
233 | Argv.push_back(x: ArchArg.c_str()); |
234 | } |
235 | |
236 | llvm::append_range(C&: Argv, R&: UserArgs); |
237 | |
238 | std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); |
239 | return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv); |
240 | } |
241 | |
242 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
243 | IncrementalCompilerBuilder::CreateCudaDevice() { |
244 | return IncrementalCompilerBuilder::createCuda(device: true); |
245 | } |
246 | |
247 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
248 | IncrementalCompilerBuilder::CreateCudaHost() { |
249 | return IncrementalCompilerBuilder::createCuda(device: false); |
250 | } |
251 | |
252 | class InProcessPrintingASTConsumer final : public MultiplexConsumer { |
253 | Interpreter &Interp; |
254 | |
255 | public: |
256 | InProcessPrintingASTConsumer(std::unique_ptr<ASTConsumer> C, Interpreter &I) |
257 | : MultiplexConsumer(std::move(C)), Interp(I) {} |
258 | bool HandleTopLevelDecl(DeclGroupRef DGR) override final { |
259 | if (DGR.isNull()) |
260 | return true; |
261 | |
262 | for (Decl *D : DGR) |
263 | if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(Val: D)) |
264 | if (TLSD && TLSD->isSemiMissing()) { |
265 | auto ExprOrErr = |
266 | Interp.ExtractValueFromExpr(E: cast<Expr>(Val: TLSD->getStmt())); |
267 | if (llvm::Error E = ExprOrErr.takeError()) { |
268 | llvm::logAllUnhandledErrors(E: std::move(E), OS&: llvm::errs(), |
269 | ErrorBanner: "Value printing failed: " ); |
270 | return false; // abort parsing |
271 | } |
272 | TLSD->setStmt(*ExprOrErr); |
273 | } |
274 | |
275 | return MultiplexConsumer::HandleTopLevelDecl(D: DGR); |
276 | } |
277 | }; |
278 | |
279 | /// A custom action enabling the incremental processing functionality. |
280 | /// |
281 | /// The usual \p FrontendAction expects one call to ExecuteAction and once it |
282 | /// sees a call to \p EndSourceFile it deletes some of the important objects |
283 | /// such as \p Preprocessor and \p Sema assuming no further input will come. |
284 | /// |
285 | /// \p IncrementalAction ensures it keep its underlying action's objects alive |
286 | /// as long as the \p IncrementalParser needs them. |
287 | /// |
288 | class IncrementalAction : public WrapperFrontendAction { |
289 | private: |
290 | bool IsTerminating = false; |
291 | Interpreter &Interp; |
292 | std::unique_ptr<ASTConsumer> Consumer; |
293 | |
294 | public: |
295 | IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, |
296 | llvm::Error &Err, Interpreter &I, |
297 | std::unique_ptr<ASTConsumer> Consumer = nullptr) |
298 | : WrapperFrontendAction([&]() { |
299 | llvm::ErrorAsOutParameter EAO(&Err); |
300 | std::unique_ptr<FrontendAction> Act; |
301 | switch (CI.getFrontendOpts().ProgramAction) { |
302 | default: |
303 | Err = llvm::createStringError( |
304 | EC: std::errc::state_not_recoverable, |
305 | Fmt: "Driver initialization failed. " |
306 | "Incremental mode for action %d is not supported" , |
307 | Vals: CI.getFrontendOpts().ProgramAction); |
308 | return Act; |
309 | case frontend::ASTDump: |
310 | case frontend::ASTPrint: |
311 | case frontend::ParseSyntaxOnly: |
312 | Act = CreateFrontendAction(CI); |
313 | break; |
314 | case frontend::PluginAction: |
315 | case frontend::EmitAssembly: |
316 | case frontend::EmitBC: |
317 | case frontend::EmitObj: |
318 | case frontend::PrintPreprocessedInput: |
319 | case frontend::EmitLLVMOnly: |
320 | Act.reset(p: new EmitLLVMOnlyAction(&LLVMCtx)); |
321 | break; |
322 | } |
323 | return Act; |
324 | }()), |
325 | Interp(I), Consumer(std::move(Consumer)) {} |
326 | FrontendAction *getWrapped() const { return WrappedAction.get(); } |
327 | TranslationUnitKind getTranslationUnitKind() override { |
328 | return TU_Incremental; |
329 | } |
330 | |
331 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
332 | StringRef InFile) override { |
333 | std::unique_ptr<ASTConsumer> C = |
334 | WrapperFrontendAction::CreateASTConsumer(CI, InFile); |
335 | |
336 | if (Consumer) { |
337 | std::vector<std::unique_ptr<ASTConsumer>> Cs; |
338 | Cs.push_back(x: std::move(Consumer)); |
339 | Cs.push_back(x: std::move(C)); |
340 | return std::make_unique<MultiplexConsumer>(args: std::move(Cs)); |
341 | } |
342 | |
343 | return std::make_unique<InProcessPrintingASTConsumer>(args: std::move(C), args&: Interp); |
344 | } |
345 | |
346 | void ExecuteAction() override { |
347 | WrapperFrontendAction::ExecuteAction(); |
348 | getCompilerInstance().getSema().CurContext = nullptr; |
349 | } |
350 | |
351 | // Do not terminate after processing the input. This allows us to keep various |
352 | // clang objects alive and to incrementally grow the current TU. |
353 | void EndSourceFile() override { |
354 | // The WrappedAction can be nullptr if we issued an error in the ctor. |
355 | if (IsTerminating && getWrapped()) |
356 | WrapperFrontendAction::EndSourceFile(); |
357 | } |
358 | |
359 | void FinalizeAction() { |
360 | assert(!IsTerminating && "Already finalized!" ); |
361 | IsTerminating = true; |
362 | EndSourceFile(); |
363 | } |
364 | }; |
365 | |
366 | Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, |
367 | llvm::Error &ErrOut, |
368 | std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder, |
369 | std::unique_ptr<clang::ASTConsumer> Consumer) |
370 | : JITBuilder(std::move(JITBuilder)) { |
371 | CI = std::move(Instance); |
372 | llvm::ErrorAsOutParameter EAO(&ErrOut); |
373 | auto LLVMCtx = std::make_unique<llvm::LLVMContext>(); |
374 | TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(args: std::move(LLVMCtx)); |
375 | |
376 | Act = TSCtx->withContextDo(F: [&](llvm::LLVMContext *Ctx) { |
377 | return std::make_unique<IncrementalAction>(args&: *CI, args&: *Ctx, args&: ErrOut, args&: *this, |
378 | args: std::move(Consumer)); |
379 | }); |
380 | |
381 | if (ErrOut) |
382 | return; |
383 | CI->ExecuteAction(Act&: *Act); |
384 | |
385 | IncrParser = std::make_unique<IncrementalParser>(args&: *CI, args&: ErrOut); |
386 | |
387 | if (ErrOut) |
388 | return; |
389 | |
390 | if (getCodeGen()) { |
391 | CachedInCodeGenModule = GenModule(); |
392 | // The initial PTU is filled by `-include` or by CUDA includes |
393 | // automatically. |
394 | if (!CI->getPreprocessorOpts().Includes.empty()) { |
395 | // We can't really directly pass the CachedInCodeGenModule to the Jit |
396 | // because it will steal it, causing dangling references as explained in |
397 | // Interpreter::Execute |
398 | auto M = llvm::CloneModule(M: *CachedInCodeGenModule); |
399 | ASTContext &C = CI->getASTContext(); |
400 | RegisterPTU(TU: C.getTranslationUnitDecl(), M: std::move(M)); |
401 | } |
402 | if (llvm::Error Err = CreateExecutor()) { |
403 | ErrOut = joinErrors(E1: std::move(ErrOut), E2: std::move(Err)); |
404 | return; |
405 | } |
406 | } |
407 | |
408 | // Not all frontends support code-generation, e.g. ast-dump actions don't |
409 | if (getCodeGen()) { |
410 | // Process the PTUs that came from initialization. For example -include will |
411 | // give us a header that's processed at initialization of the preprocessor. |
412 | for (PartialTranslationUnit &PTU : PTUs) |
413 | if (llvm::Error Err = Execute(T&: PTU)) { |
414 | ErrOut = joinErrors(E1: std::move(ErrOut), E2: std::move(Err)); |
415 | return; |
416 | } |
417 | } |
418 | } |
419 | |
420 | Interpreter::~Interpreter() { |
421 | IncrParser.reset(); |
422 | Act->FinalizeAction(); |
423 | if (DeviceParser) |
424 | DeviceParser.reset(); |
425 | if (DeviceAct) |
426 | DeviceAct->FinalizeAction(); |
427 | if (IncrExecutor) { |
428 | if (llvm::Error Err = IncrExecutor->cleanUp()) |
429 | llvm::report_fatal_error( |
430 | reason: llvm::Twine("Failed to clean up IncrementalExecutor: " ) + |
431 | toString(E: std::move(Err))); |
432 | } |
433 | } |
434 | |
435 | // These better to put in a runtime header but we can't. This is because we |
436 | // can't find the precise resource directory in unittests so we have to hard |
437 | // code them. |
438 | const char *const Runtimes = R"( |
439 | #define __CLANG_REPL__ 1 |
440 | #ifdef __cplusplus |
441 | #define EXTERN_C extern "C" |
442 | void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); |
443 | struct __clang_Interpreter_NewTag{} __ci_newtag; |
444 | void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; |
445 | template <class T, class = T (*)() /*disable for arrays*/> |
446 | void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { |
447 | for (auto Idx = 0; Idx < Size; ++Idx) |
448 | new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]); |
449 | } |
450 | template <class T, unsigned long N> |
451 | void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { |
452 | __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); |
453 | } |
454 | #else |
455 | #define EXTERN_C extern |
456 | #endif // __cplusplus |
457 | |
458 | EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); |
459 | )" ; |
460 | |
461 | llvm::Expected<std::unique_ptr<Interpreter>> |
462 | Interpreter::create(std::unique_ptr<CompilerInstance> CI, |
463 | std::unique_ptr<llvm::orc::LLJITBuilder> JB) { |
464 | llvm::Error Err = llvm::Error::success(); |
465 | auto Interp = std::unique_ptr<Interpreter>( |
466 | new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr)); |
467 | if (Err) |
468 | return std::move(Err); |
469 | |
470 | // Add runtime code and set a marker to hide it from user code. Undo will not |
471 | // go through that. |
472 | auto PTU = Interp->Parse(Code: Runtimes); |
473 | if (!PTU) |
474 | return PTU.takeError(); |
475 | Interp->markUserCodeStart(); |
476 | |
477 | Interp->ValuePrintingInfo.resize(N: 4); |
478 | return std::move(Interp); |
479 | } |
480 | |
481 | llvm::Expected<std::unique_ptr<Interpreter>> |
482 | Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, |
483 | std::unique_ptr<CompilerInstance> DCI) { |
484 | // avoid writing fat binary to disk using an in-memory virtual file system |
485 | llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS = |
486 | std::make_unique<llvm::vfs::InMemoryFileSystem>(); |
487 | llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS = |
488 | std::make_unique<llvm::vfs::OverlayFileSystem>( |
489 | args: llvm::vfs::getRealFileSystem()); |
490 | OverlayVFS->pushOverlay(FS: IMVFS); |
491 | CI->createFileManager(VFS: OverlayVFS); |
492 | |
493 | llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr = |
494 | Interpreter::create(CI: std::move(CI)); |
495 | if (!InterpOrErr) |
496 | return InterpOrErr; |
497 | |
498 | std::unique_ptr<Interpreter> Interp = std::move(*InterpOrErr); |
499 | |
500 | llvm::Error Err = llvm::Error::success(); |
501 | |
502 | auto DeviceAct = Interp->TSCtx->withContextDo(F: [&](llvm::LLVMContext *Ctx) { |
503 | return std::make_unique<IncrementalAction>(args&: *DCI, args&: *Ctx, args&: Err, args&: *Interp); |
504 | }); |
505 | |
506 | if (Err) |
507 | return std::move(Err); |
508 | |
509 | Interp->DeviceAct = std::move(DeviceAct); |
510 | |
511 | DCI->ExecuteAction(Act&: *Interp->DeviceAct); |
512 | |
513 | Interp->DeviceCI = std::move(DCI); |
514 | |
515 | auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( |
516 | args&: *Interp->DeviceCI, args&: *Interp->getCompilerInstance(), args&: IMVFS, args&: Err, |
517 | args&: Interp->PTUs); |
518 | |
519 | if (Err) |
520 | return std::move(Err); |
521 | |
522 | Interp->DeviceParser = std::move(DeviceParser); |
523 | return std::move(Interp); |
524 | } |
525 | |
526 | const CompilerInstance *Interpreter::getCompilerInstance() const { |
527 | return CI.get(); |
528 | } |
529 | |
530 | CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); } |
531 | |
532 | llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { |
533 | if (!IncrExecutor) { |
534 | if (auto Err = CreateExecutor()) |
535 | return std::move(Err); |
536 | } |
537 | |
538 | return IncrExecutor->GetExecutionEngine(); |
539 | } |
540 | |
541 | ASTContext &Interpreter::getASTContext() { |
542 | return getCompilerInstance()->getASTContext(); |
543 | } |
544 | |
545 | const ASTContext &Interpreter::getASTContext() const { |
546 | return getCompilerInstance()->getASTContext(); |
547 | } |
548 | |
549 | void Interpreter::markUserCodeStart() { |
550 | assert(!InitPTUSize && "We only do this once" ); |
551 | InitPTUSize = PTUs.size(); |
552 | } |
553 | |
554 | size_t Interpreter::getEffectivePTUSize() const { |
555 | assert(PTUs.size() >= InitPTUSize && "empty PTU list?" ); |
556 | return PTUs.size() - InitPTUSize; |
557 | } |
558 | |
559 | PartialTranslationUnit & |
560 | Interpreter::RegisterPTU(TranslationUnitDecl *TU, |
561 | std::unique_ptr<llvm::Module> M /*={}*/, |
562 | IncrementalAction *Action) { |
563 | PTUs.emplace_back(args: PartialTranslationUnit()); |
564 | PartialTranslationUnit &LastPTU = PTUs.back(); |
565 | LastPTU.TUPart = TU; |
566 | |
567 | if (!M) |
568 | M = GenModule(Action); |
569 | |
570 | assert((!getCodeGen(Action) || M) && |
571 | "Must have a llvm::Module at this point" ); |
572 | |
573 | LastPTU.TheModule = std::move(M); |
574 | LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1 |
575 | << ": [TU=" << LastPTU.TUPart); |
576 | if (LastPTU.TheModule) |
577 | LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " (" |
578 | << LastPTU.TheModule->getName() << ")" ); |
579 | LLVM_DEBUG(llvm::dbgs() << "]\n" ); |
580 | return LastPTU; |
581 | } |
582 | |
583 | llvm::Expected<PartialTranslationUnit &> |
584 | Interpreter::Parse(llvm::StringRef Code) { |
585 | // If we have a device parser, parse it first. The generated code will be |
586 | // included in the host compilation |
587 | if (DeviceParser) { |
588 | llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Input: Code); |
589 | if (auto E = DeviceTU.takeError()) |
590 | return std::move(E); |
591 | |
592 | RegisterPTU(TU: *DeviceTU, M: nullptr, Action: DeviceAct.get()); |
593 | |
594 | llvm::Expected<llvm::StringRef> PTX = DeviceParser->GeneratePTX(); |
595 | if (!PTX) |
596 | return PTX.takeError(); |
597 | |
598 | llvm::Error Err = DeviceParser->GenerateFatbinary(); |
599 | if (Err) |
600 | return std::move(Err); |
601 | } |
602 | |
603 | // Tell the interpreter sliently ignore unused expressions since value |
604 | // printing could cause it. |
605 | getCompilerInstance()->getDiagnostics().setSeverity( |
606 | Diag: clang::diag::warn_unused_expr, Map: diag::Severity::Ignored, Loc: SourceLocation()); |
607 | |
608 | llvm::Expected<TranslationUnitDecl *> TuOrErr = IncrParser->Parse(Input: Code); |
609 | if (!TuOrErr) |
610 | return TuOrErr.takeError(); |
611 | |
612 | return RegisterPTU(TU: *TuOrErr); |
613 | } |
614 | |
615 | static llvm::Expected<llvm::orc::JITTargetMachineBuilder> |
616 | createJITTargetMachineBuilder(const std::string &TT) { |
617 | if (TT == llvm::sys::getProcessTriple()) |
618 | // This fails immediately if the target backend is not registered |
619 | return llvm::orc::JITTargetMachineBuilder::detectHost(); |
620 | |
621 | // If the target backend is not registered, LLJITBuilder::create() will fail |
622 | return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); |
623 | } |
624 | |
625 | llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> |
626 | Interpreter::createLLJITBuilder( |
627 | std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC, |
628 | llvm::StringRef OrcRuntimePath) { |
629 | const std::string &TT = EPC->getTargetTriple().getTriple(); |
630 | auto JTMB = createJITTargetMachineBuilder(TT); |
631 | if (!JTMB) |
632 | return JTMB.takeError(); |
633 | auto JB = IncrementalExecutor::createDefaultJITBuilder(JTMB: std::move(*JTMB)); |
634 | if (!JB) |
635 | return JB.takeError(); |
636 | |
637 | (*JB)->setExecutorProcessControl(std::move(EPC)); |
638 | (*JB)->setPlatformSetUp( |
639 | llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str())); |
640 | |
641 | return std::move(*JB); |
642 | } |
643 | |
644 | llvm::Error Interpreter::CreateExecutor() { |
645 | if (IncrExecutor) |
646 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
647 | "Execution engine exists" , |
648 | Args: std::error_code()); |
649 | if (!getCodeGen()) |
650 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
651 | "No code generator available" , |
652 | Args: std::error_code()); |
653 | if (!JITBuilder) { |
654 | const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; |
655 | auto JTMB = createJITTargetMachineBuilder(TT); |
656 | if (!JTMB) |
657 | return JTMB.takeError(); |
658 | auto JB = IncrementalExecutor::createDefaultJITBuilder(JTMB: std::move(*JTMB)); |
659 | if (!JB) |
660 | return JB.takeError(); |
661 | JITBuilder = std::move(*JB); |
662 | } |
663 | |
664 | llvm::Error Err = llvm::Error::success(); |
665 | #ifdef __EMSCRIPTEN__ |
666 | auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx); |
667 | #else |
668 | auto Executor = |
669 | std::make_unique<IncrementalExecutor>(args&: *TSCtx, args&: *JITBuilder, args&: Err); |
670 | #endif |
671 | if (!Err) |
672 | IncrExecutor = std::move(Executor); |
673 | |
674 | return Err; |
675 | } |
676 | |
677 | void Interpreter::ResetExecutor() { IncrExecutor.reset(); } |
678 | |
679 | llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { |
680 | assert(T.TheModule); |
681 | LLVM_DEBUG( |
682 | llvm::dbgs() << "execute-ptu " |
683 | << (llvm::is_contained(PTUs, T) |
684 | ? std::distance(PTUs.begin(), llvm::find(PTUs, T)) |
685 | : -1) |
686 | << ": [TU=" << T.TUPart << ", M=" << T.TheModule.get() |
687 | << " (" << T.TheModule->getName() << ")]\n" ); |
688 | if (!IncrExecutor) { |
689 | auto Err = CreateExecutor(); |
690 | if (Err) |
691 | return Err; |
692 | } |
693 | // FIXME: Add a callback to retain the llvm::Module once the JIT is done. |
694 | if (auto Err = IncrExecutor->addModule(PTU&: T)) |
695 | return Err; |
696 | |
697 | if (auto Err = IncrExecutor->runCtors()) |
698 | return Err; |
699 | |
700 | return llvm::Error::success(); |
701 | } |
702 | |
703 | llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { |
704 | |
705 | auto PTU = Parse(Code); |
706 | if (!PTU) |
707 | return PTU.takeError(); |
708 | if (PTU->TheModule) |
709 | if (llvm::Error Err = Execute(T&: *PTU)) |
710 | return Err; |
711 | |
712 | if (LastValue.isValid()) { |
713 | if (!V) { |
714 | LastValue.dump(); |
715 | LastValue.clear(); |
716 | } else |
717 | *V = std::move(LastValue); |
718 | } |
719 | return llvm::Error::success(); |
720 | } |
721 | |
722 | llvm::Expected<llvm::orc::ExecutorAddr> |
723 | Interpreter::getSymbolAddress(GlobalDecl GD) const { |
724 | if (!IncrExecutor) |
725 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
726 | "No execution engine" , |
727 | Args: std::error_code()); |
728 | llvm::StringRef MangledName = getCodeGen()->GetMangledName(GD); |
729 | return getSymbolAddress(IRName: MangledName); |
730 | } |
731 | |
732 | llvm::Expected<llvm::orc::ExecutorAddr> |
733 | Interpreter::getSymbolAddress(llvm::StringRef IRName) const { |
734 | if (!IncrExecutor) |
735 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
736 | "No execution engine" , |
737 | Args: std::error_code()); |
738 | |
739 | return IncrExecutor->getSymbolAddress(Name: IRName, NameKind: IncrementalExecutor::IRName); |
740 | } |
741 | |
742 | llvm::Expected<llvm::orc::ExecutorAddr> |
743 | Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const { |
744 | if (!IncrExecutor) |
745 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
746 | "No execution engine" , |
747 | Args: std::error_code()); |
748 | |
749 | return IncrExecutor->getSymbolAddress(Name, NameKind: IncrementalExecutor::LinkerName); |
750 | } |
751 | |
752 | llvm::Error Interpreter::Undo(unsigned N) { |
753 | |
754 | if (N > getEffectivePTUSize()) |
755 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
756 | "Too many undos" , |
757 | Args: std::error_code()); |
758 | for (unsigned I = 0; I < N; I++) { |
759 | if (IncrExecutor) { |
760 | if (llvm::Error Err = IncrExecutor->removeModule(PTU&: PTUs.back())) |
761 | return Err; |
762 | } |
763 | |
764 | IncrParser->CleanUpPTU(MostRecentTU: PTUs.back().TUPart); |
765 | PTUs.pop_back(); |
766 | } |
767 | return llvm::Error::success(); |
768 | } |
769 | |
770 | llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { |
771 | #ifdef __EMSCRIPTEN__ |
772 | void *handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL); |
773 | if (!handle) { |
774 | llvm::errs() << dlerror() << '\n'; |
775 | return llvm::make_error<llvm::StringError>("Failed to load dynamic library" , |
776 | llvm::inconvertibleErrorCode()); |
777 | } |
778 | #else |
779 | auto EE = getExecutionEngine(); |
780 | if (!EE) |
781 | return EE.takeError(); |
782 | |
783 | if (llvm::Expected< |
784 | std::unique_ptr<llvm::orc::EPCDynamicLibrarySearchGenerator>> |
785 | DLSG = llvm::orc::EPCDynamicLibrarySearchGenerator::Load( |
786 | ES&: EE->getExecutionSession(), LibraryPath: name)) |
787 | // FIXME: Eventually we should put each library in its own JITDylib and |
788 | // turn off process symbols by default. |
789 | EE->getProcessSymbolsJITDylib()->addGenerator(DefGenerator: std::move(*DLSG)); |
790 | else |
791 | return DLSG.takeError(); |
792 | #endif |
793 | |
794 | return llvm::Error::success(); |
795 | } |
796 | |
797 | std::unique_ptr<llvm::Module> |
798 | Interpreter::GenModule(IncrementalAction *Action) { |
799 | static unsigned ID = 0; |
800 | if (CodeGenerator *CG = getCodeGen(Action)) { |
801 | // Clang's CodeGen is designed to work with a single llvm::Module. In many |
802 | // cases for convenience various CodeGen parts have a reference to the |
803 | // llvm::Module (TheModule or Module) which does not change when a new |
804 | // module is pushed. However, the execution engine wants to take ownership |
805 | // of the module which does not map well to CodeGen's design. To work this |
806 | // around we created an empty module to make CodeGen happy. We should make |
807 | // sure it always stays empty. |
808 | assert(((!CachedInCodeGenModule || |
809 | !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) || |
810 | (CachedInCodeGenModule->empty() && |
811 | CachedInCodeGenModule->global_empty() && |
812 | CachedInCodeGenModule->alias_empty() && |
813 | CachedInCodeGenModule->ifunc_empty())) && |
814 | "CodeGen wrote to a readonly module" ); |
815 | std::unique_ptr<llvm::Module> M(CG->ReleaseModule()); |
816 | CG->StartModule(ModuleName: "incr_module_" + std::to_string(val: ID++), C&: M->getContext()); |
817 | return M; |
818 | } |
819 | return nullptr; |
820 | } |
821 | |
822 | CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const { |
823 | if (!Action) |
824 | Action = Act.get(); |
825 | FrontendAction *WrappedAct = Action->getWrapped(); |
826 | if (!WrappedAct->hasIRSupport()) |
827 | return nullptr; |
828 | return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator(); |
829 | } |
830 | } // namespace clang |
831 | |