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 "IncrementalAction.h"
16#include "IncrementalParser.h"
17#include "InterpreterUtils.h"
18
19#include "clang/AST/ASTConsumer.h"
20#include "clang/AST/ASTContext.h"
21#include "clang/AST/Mangle.h"
22#include "clang/AST/TypeVisitor.h"
23#include "clang/Basic/DiagnosticSema.h"
24#include "clang/Basic/FileManager.h"
25#include "clang/Basic/TargetInfo.h"
26#include "clang/CodeGen/CodeGenAction.h"
27#include "clang/CodeGen/ObjectFilePCHContainerWriter.h"
28#include "clang/Driver/Compilation.h"
29#include "clang/Driver/Driver.h"
30#include "clang/Driver/Job.h"
31#include "clang/Driver/Tool.h"
32#include "clang/Frontend/CompilerInstance.h"
33#include "clang/Frontend/FrontendAction.h"
34#include "clang/Frontend/FrontendOptions.h"
35#include "clang/Frontend/MultiplexConsumer.h"
36#include "clang/Frontend/TextDiagnosticBuffer.h"
37#include "clang/FrontendTool/Utils.h"
38#include "clang/Interpreter/IncrementalExecutor.h"
39#include "clang/Interpreter/Interpreter.h"
40#include "clang/Interpreter/Value.h"
41#include "clang/Lex/PreprocessorOptions.h"
42#include "clang/Options/OptionUtils.h"
43#include "clang/Options/Options.h"
44#include "clang/Sema/Lookup.h"
45#include "clang/Serialization/ASTReader.h"
46#include "clang/Serialization/ModuleCache.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/VirtualFileSystem.h"
55#include "llvm/Support/raw_ostream.h"
56#include "llvm/TargetParser/Host.h"
57#include "llvm/TargetParser/Triple.h"
58#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule
59
60#define DEBUG_TYPE "clang-repl"
61
62using namespace clang;
63// FIXME: Figure out how to unify with namespace init_convenience from
64// tools/clang-import-test/clang-import-test.cpp
65namespace {
66/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
67/// \returns NULL on error.
68static llvm::Expected<const llvm::opt::ArgStringList *>
69GetCC1Arguments(DiagnosticsEngine *Diagnostics,
70 driver::Compilation *Compilation) {
71 // We expect to get back exactly one Command job, if we didn't something
72 // failed. Extract that job from the Compilation.
73 const driver::JobList &Jobs = Compilation->getJobs();
74 if (!Jobs.size())
75 return llvm::createStringError(EC: llvm::errc::not_supported,
76 S: "Driver initialization failed. "
77 "Unable to create a driver job");
78
79 // The one job we find should be to invoke clang again.
80 const driver::Command *Cmd = &*Jobs.begin();
81 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
82 return llvm::createStringError(EC: llvm::errc::not_supported,
83 S: "Driver initialization failed");
84
85 return &Cmd->getArguments();
86}
87
88// ASTReaderListener that captures the PIC level stored in a serialized AST
89// file (PCH or PCM) so the interpreter can compare it against its own.
90class PICLevelReader : public ASTReaderListener {
91 unsigned &PICLevel;
92
93public:
94 PICLevelReader(unsigned &PICLevel) : PICLevel(PICLevel) {}
95
96 bool ReadLanguageOptions(const LangOptions &LangOpts,
97 StringRef ModuleFilename, bool Complain,
98 bool AllowCompatibleDifferences) override {
99 PICLevel = LangOpts.PICLevel;
100 return false;
101 }
102};
103
104// clang-repl always compiles position-independent code (it injects -fPIC), so a
105// PCH/PCM that was built with a different PIC level is incompatible: mixing the
106// two leads to relocations that may be out of range once the JIT maps code more
107// than 2GB away. PICLevel is a "compatible" language option, so the ASTReader
108// would otherwise accept the mismatch silently. Reject it up front.
109//
110// The file is probed with its own FileManager and ModuleCache (sharing only the
111// VFS) so this read leaves the CompilerInstance's state untouched for the real
112// load performed later by ExecuteAction().
113static llvm::Error checkASTFilePICLevel(CompilerInstance &Clang,
114 StringRef Filename) {
115 llvm::IntrusiveRefCntPtr<FileManager> FileMgr(new FileManager(
116 Clang.getFileSystemOpts(), Clang.getVirtualFileSystemPtr()));
117 std::shared_ptr<ModuleCache> ModCache = createCrossProcessModuleCache();
118 unsigned ASTPICLevel = 0;
119 PICLevelReader Reader(ASTPICLevel);
120 if (!ASTReader::readASTFileControlBlock(
121 Filename, FileMgr&: *FileMgr, ModCache: *ModCache, PCHContainerRdr: Clang.getPCHContainerReader(),
122 /*FindModuleFileExtensions=*/false, Listener&: Reader,
123 /*ValidateDiagnosticOptions=*/false) &&
124 ASTPICLevel != Clang.getLangOpts().PICLevel)
125 return llvm::createStringError(
126 EC: llvm::errc::not_supported,
127 Fmt: "AST file '%s' was built with PIC level %u, which is incompatible "
128 "with clang-repl's PIC level %u",
129 Vals: Filename.str().c_str(), Vals: ASTPICLevel, Vals: Clang.getLangOpts().PICLevel);
130 return llvm::Error::success();
131}
132
133static llvm::Expected<std::unique_ptr<CompilerInstance>>
134CreateCI(const llvm::opt::ArgStringList &Argv) {
135 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
136
137 // Register the support for object-file-wrapped Clang modules.
138 // FIXME: Clang should register these container operations automatically.
139 auto PCHOps = Clang->getPCHContainerOperations();
140 PCHOps->registerWriter(Writer: std::make_unique<ObjectFilePCHContainerWriter>());
141 PCHOps->registerReader(Reader: std::make_unique<ObjectFilePCHContainerReader>());
142
143 // Buffer diagnostics from argument parsing so that we can output them using
144 // a well formed diagnostic object.
145 DiagnosticOptions DiagOpts;
146 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
147 DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagsBuffer);
148 bool Success = CompilerInvocation::CreateFromArgs(
149 Res&: Clang->getInvocation(), CommandLineArgs: llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
150
151 // Infer the builtin include path if unspecified.
152 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
153 Clang->getHeaderSearchOpts().ResourceDir.empty())
154 Clang->getHeaderSearchOpts().ResourceDir =
155 GetResourcesPath(Argv0: Argv[0], MainAddr: nullptr);
156
157 Clang->createVirtualFileSystem();
158
159 // Create the actual diagnostics engine.
160 Clang->createDiagnostics();
161
162 DiagsBuffer->FlushDiagnostics(Diags&: Clang->getDiagnostics());
163 if (!Success)
164 return llvm::createStringError(EC: llvm::errc::not_supported,
165 S: "Initialization failed. "
166 "Unable to flush diagnostics");
167
168 // FIXME: Merge with CompilerInstance::ExecuteAction.
169 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(InputData: "").release();
170 Clang->getPreprocessorOpts().addRemappedFile(From: "<<< inputs >>>", To: MB);
171
172 Clang->setTarget(TargetInfo::CreateTargetInfo(
173 Diags&: Clang->getDiagnostics(), Opts&: Clang->getInvocation().getTargetOpts()));
174 if (!Clang->hasTarget())
175 return llvm::createStringError(EC: llvm::errc::not_supported,
176 S: "Initialization failed. "
177 "Target is missing");
178
179 Clang->getTarget().adjust(Diags&: Clang->getDiagnostics(), Opts&: Clang->getLangOpts(),
180 Aux: Clang->getAuxTarget());
181
182 // Don't clear the AST before backend codegen since we do codegen multiple
183 // times, reusing the same AST.
184 Clang->getCodeGenOpts().ClearASTBeforeBackend = false;
185
186 Clang->getFrontendOpts().DisableFree = false;
187 Clang->getCodeGenOpts().DisableFree = false;
188
189 // Reject any precompiled input (PCH or PCM) built with a PIC level that
190 // differs from clang-repl's own, before any Interpreter/FrontendAction is
191 // constructed. See checkASTFilePICLevel for the rationale.
192 StringRef PCHInclude = Clang->getPreprocessorOpts().ImplicitPCHInclude;
193 if (!PCHInclude.empty())
194 if (llvm::Error Err = checkASTFilePICLevel(Clang&: *Clang, Filename: PCHInclude))
195 return std::move(Err);
196
197 // Explicitly loaded modules: -fmodule-file=<path> and
198 // -fmodule-file=<name>=<path>.
199 for (StringRef ModuleFile : Clang->getFrontendOpts().ModuleFiles)
200 if (llvm::Error Err = checkASTFilePICLevel(Clang&: *Clang, Filename: ModuleFile))
201 return std::move(Err);
202 for (const auto &NameAndFile :
203 Clang->getHeaderSearchOpts().PrebuiltModuleFiles)
204 if (llvm::Error Err = checkASTFilePICLevel(Clang&: *Clang, Filename: NameAndFile.second))
205 return std::move(Err);
206
207 return std::move(Clang);
208}
209
210static llvm::Error ExecuteIncrementalAction(CompilerInstance &CI,
211 IncrementalAction &Act) {
212 if (!CI.ExecuteAction(Act) || CI.getDiagnostics().hasErrorOccurred()) {
213 return llvm::createStringError(EC: llvm::errc::not_supported,
214 S: "Failed to execute incremental action");
215 }
216 return llvm::Error::success();
217}
218
219} // anonymous namespace
220
221namespace clang {
222
223llvm::Expected<std::unique_ptr<CompilerInstance>>
224IncrementalCompilerBuilder::create(std::string TT,
225 std::vector<const char *> &ClangArgv) {
226
227 // If we don't know ClangArgv0 or the address of main() at this point, try
228 // to guess it anyway (it's possible on some platforms).
229 std::string MainExecutableName =
230 llvm::sys::fs::getMainExecutable(argv0: nullptr, MainExecAddr: nullptr);
231
232 ClangArgv.insert(position: ClangArgv.begin(), x: MainExecutableName.c_str());
233
234 // Compile as position-independent code. This prevents the frontend from
235 // marking external symbols (e.g. C++ type-info such as _ZTIPKc used for
236 // exception handling) as dso_local and emitting direct PC-relative
237 // references. JITLink can place the GOT entry near the JIT'd code, keeping
238 // the relocation in range. Without -fPIC, a direct Delta32 relocation to a
239 // host symbol may be out of range when the JIT memory is mapped more than
240 // 2GB away (as on FreeBSD), breaking tests such as
241 // Interpreter/simple-exception.cpp. Insert before user arguments so it can
242 // still be overridden. On Windows (excluding Cygwin/MinGW) an explicit
243 // -fPIC is an unsupported driver option that would drop non-x86_64 targets
244 // to PIC level 0; PIC is already the forced default there where relevant,
245 // so don't inject it.
246 llvm::Triple TargetTriple(TT);
247 if (!TargetTriple.isOSWindows() || TargetTriple.isOSCygMing())
248 ClangArgv.insert(position: ClangArgv.begin() + 1, x: "-fPIC");
249
250 // Prepending -c to force the driver to do something if no action was
251 // specified. By prepending we allow users to override the default
252 // action and use other actions in incremental mode.
253 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
254 // We do C++ by default; append right after argv[0] if no "-x" given
255 ClangArgv.insert(position: ClangArgv.end(), x: "-Xclang");
256 ClangArgv.insert(position: ClangArgv.end(), x: "-fincremental-extensions");
257 ClangArgv.insert(position: ClangArgv.end(), x: "-c");
258
259 // Put a dummy C++ file on to ensure there's at least one compile job for the
260 // driver to construct.
261 ClangArgv.push_back(x: "<<< inputs >>>");
262
263 // Buffer diagnostics from argument parsing so that we can output them using a
264 // well formed diagnostic object.
265 std::unique_ptr<DiagnosticOptions> DiagOpts =
266 CreateAndPopulateDiagOpts(Argv: ClangArgv);
267 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
268 DiagnosticsEngine Diags(DiagnosticIDs::create(), *DiagOpts, DiagsBuffer);
269
270 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
271 Driver.setCheckInputsExist(false); // the input comes from mem buffers
272 llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv);
273 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(Args: RF));
274
275 if (CompilationCB)
276 if (auto Err = (*CompilationCB)(*Compilation.get()))
277 return std::move(Err);
278
279 if (Compilation->getArgs().hasArg(Ids: options::OPT_v))
280 Compilation->getJobs().Print(OS&: llvm::errs(), Terminator: "\n", /*Quote=*/false);
281
282 auto ErrOrCC1Args = GetCC1Arguments(Diagnostics: &Diags, Compilation: Compilation.get());
283 if (auto Err = ErrOrCC1Args.takeError())
284 return std::move(Err);
285
286 return CreateCI(Argv: **ErrOrCC1Args);
287}
288
289llvm::Expected<std::unique_ptr<CompilerInstance>>
290IncrementalCompilerBuilder::CreateCpp() {
291 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
292
293 std::vector<const char *> Argv;
294 Argv.reserve(n: 5 + 1 + UserArgs.size());
295 Argv.push_back(x: "-xc++");
296#ifdef __EMSCRIPTEN__
297 Argv.push_back("-target");
298 Argv.push_back(TT.c_str());
299 Argv.push_back("-fvisibility=default");
300#endif
301 llvm::append_range(C&: Argv, R&: UserArgs);
302
303 return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv);
304}
305
306llvm::Expected<std::unique_ptr<CompilerInstance>>
307IncrementalCompilerBuilder::createCuda(bool device) {
308 std::vector<const char *> Argv;
309 Argv.reserve(n: 5 + 4 + UserArgs.size());
310
311 Argv.push_back(x: "-xcuda");
312 if (device)
313 Argv.push_back(x: "--cuda-device-only");
314 else
315 Argv.push_back(x: "--cuda-host-only");
316
317 std::string SDKPathArg = "--cuda-path=";
318 if (!CudaSDKPath.empty()) {
319 SDKPathArg += CudaSDKPath;
320 Argv.push_back(x: SDKPathArg.c_str());
321 }
322
323 std::string ArchArg = "--offload-arch=";
324 if (!OffloadArch.empty()) {
325 ArchArg += OffloadArch;
326 Argv.push_back(x: ArchArg.c_str());
327 }
328
329 llvm::append_range(C&: Argv, R&: UserArgs);
330
331 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
332 return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv);
333}
334
335llvm::Expected<std::unique_ptr<CompilerInstance>>
336IncrementalCompilerBuilder::CreateCudaDevice() {
337 return IncrementalCompilerBuilder::createCuda(device: true);
338}
339
340llvm::Expected<std::unique_ptr<CompilerInstance>>
341IncrementalCompilerBuilder::CreateCudaHost() {
342 return IncrementalCompilerBuilder::createCuda(device: false);
343}
344
345Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
346 llvm::Error &ErrOut,
347 std::unique_ptr<IncrementalExecutorBuilder> IEB,
348 std::unique_ptr<clang::ASTConsumer> Consumer)
349 : IncrExecutorBuilder(std::move(IEB)) {
350 CI = std::move(Instance);
351 llvm::ErrorAsOutParameter EAO(&ErrOut);
352 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
353 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(args: std::move(LLVMCtx));
354
355 // Honor -mllvm options
356 CI->parseLLVMArgs();
357
358 Act = TSCtx->withContextDo(F: [&](llvm::LLVMContext *Ctx) {
359 return std::make_unique<IncrementalAction>(args&: *CI, args&: *Ctx, args&: ErrOut, args&: *this,
360 args: std::move(Consumer));
361 });
362
363 if (ErrOut)
364 return;
365
366 if (llvm::Error E = ExecuteIncrementalAction(CI&: *CI, Act&: *Act)) {
367 ErrOut = joinErrors(E1: std::move(ErrOut), E2: std::move(E));
368 return;
369 }
370
371 IncrParser =
372 std::make_unique<IncrementalParser>(args&: *CI, args: Act.get(), args&: ErrOut, args&: PTUs);
373
374 if (ErrOut)
375 return;
376
377 if (Act->getCodeGen()) {
378 Act->CacheCodeGenModule();
379 // The initial PTU is filled by `-include`/`-include-pch` or by CUDA
380 // includes automatically.
381 if (!CI->getPreprocessorOpts().Includes.empty() ||
382 !CI->getPreprocessorOpts().ImplicitPCHInclude.empty()) {
383 // We can't really directly pass the CachedInCodeGenModule to the Jit
384 // because it will steal it, causing dangling references as explained in
385 // Interpreter::Execute
386 auto M = llvm::CloneModule(M: *Act->getCachedCodeGenModule());
387 ASTContext &C = CI->getASTContext();
388 IncrParser->RegisterPTU(TU: C.getTranslationUnitDecl(), M: std::move(M));
389 }
390 if (llvm::Error Err = CreateExecutor()) {
391 ErrOut = joinErrors(E1: std::move(ErrOut), E2: std::move(Err));
392 return;
393 }
394 }
395
396 // Not all frontends support code-generation, e.g. ast-dump actions don't
397 if (Act->getCodeGen()) {
398 // Process the PTUs that came from initialization. For example -include will
399 // give us a header that's processed at initialization of the preprocessor.
400 for (PartialTranslationUnit &PTU : PTUs)
401 if (llvm::Error Err = Execute(T&: PTU)) {
402 ErrOut = joinErrors(E1: std::move(ErrOut), E2: std::move(Err));
403 return;
404 }
405 }
406}
407
408Interpreter::~Interpreter() {
409 IncrParser.reset();
410 Act->FinalizeAction();
411 if (DeviceParser)
412 DeviceParser.reset();
413 if (DeviceAct)
414 DeviceAct->FinalizeAction();
415 if (IncrExecutor) {
416 if (llvm::Error Err = IncrExecutor->cleanUp())
417 llvm::report_fatal_error(
418 reason: llvm::Twine("Failed to clean up IncrementalExecutor: ") +
419 toString(E: std::move(Err)));
420 }
421}
422
423// These better to put in a runtime header but we can't. This is because we
424// can't find the precise resource directory in unittests so we have to hard
425// code them.
426const char *const Runtimes = R"(
427 #define __CLANG_REPL__ 1
428#ifdef __cplusplus
429 #define EXTERN_C extern "C"
430 struct __clang_Interpreter_NewTag{} __ci_newtag;
431 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
432 template <class T, class = T (*)() /*disable for arrays*/>
433 void __clang_Interpreter_SetValueCopyArr(const T* Src, void* Placement, unsigned long Size) {
434 for (unsigned long Idx = 0; Idx < Size; ++Idx)
435 new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
436 }
437 template <class T, unsigned long N>
438 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
439 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
440 }
441#else
442 #if __STDC_VERSION__ < 199901L
443 #define CI_RESTRICT
444 #define CI_INLINE
445 #else
446 #define CI_RESTRICT restrict
447 #define CI_INLINE inline
448 #endif
449 #define EXTERN_C extern
450 EXTERN_C void *memcpy(void *CI_RESTRICT dst, const void *CI_RESTRICT src, __SIZE_TYPE__ n);
451 EXTERN_C CI_INLINE void __clang_Interpreter_SetValueCopyArr(const void* Src, void* Placement, unsigned long Size) {
452 memcpy(Placement, Src, Size);
453 }
454#endif // __cplusplus
455 EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
456 EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
457)";
458
459llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create(
460 std::unique_ptr<CompilerInstance> CI,
461 std::unique_ptr<IncrementalExecutorBuilder> IEB /*=nullptr*/) {
462 llvm::Error Err = llvm::Error::success();
463
464 auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
465 std::move(CI), Err, std::move(IEB), /*Consumer=*/nullptr));
466 if (auto E = std::move(Err))
467 return std::move(E);
468
469 // Add runtime code and set a marker to hide it from user code. Undo will not
470 // go through that.
471 if (auto E = Interp->ParseAndExecute(Code: Runtimes))
472 return std::move(E);
473
474 Interp->markUserCodeStart();
475
476 return std::move(Interp);
477}
478
479llvm::Expected<std::unique_ptr<Interpreter>>
480Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
481 std::unique_ptr<CompilerInstance> DCI) {
482 // avoid writing fat binary to disk using an in-memory virtual file system
483 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS =
484 std::make_unique<llvm::vfs::InMemoryFileSystem>();
485 llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
486 std::make_unique<llvm::vfs::OverlayFileSystem>(
487 args: llvm::vfs::getRealFileSystem());
488 OverlayVFS->pushOverlay(FS: IMVFS);
489 CI->createVirtualFileSystem(BaseFS: OverlayVFS);
490 CI->createFileManager();
491
492 llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =
493 Interpreter::create(CI: std::move(CI));
494 if (!InterpOrErr)
495 return InterpOrErr;
496
497 std::unique_ptr<Interpreter> Interp = std::move(*InterpOrErr);
498
499 llvm::Error Err = llvm::Error::success();
500
501 auto DeviceAct = Interp->TSCtx->withContextDo(F: [&](llvm::LLVMContext *Ctx) {
502 return std::make_unique<IncrementalAction>(args&: *DCI, args&: *Ctx, args&: Err, args&: *Interp);
503 });
504
505 if (Err)
506 return std::move(Err);
507
508 Interp->DeviceAct = std::move(DeviceAct);
509
510 if (llvm::Error E = ExecuteIncrementalAction(CI&: *DCI, Act&: *Interp->DeviceAct))
511 return std::move(E);
512
513 // Set the finalized initial device module aside, as the host path does.
514 Interp->DeviceAct->CacheCodeGenModule();
515
516 Interp->DeviceCI = std::move(DCI);
517
518 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
519 args&: *Interp->DeviceCI, args&: *Interp->getCompilerInstance(),
520 args: Interp->DeviceAct.get(), args&: IMVFS, args&: Err, args&: Interp->PTUs);
521
522 if (Err)
523 return std::move(Err);
524
525 Interp->DeviceParser = std::move(DeviceParser);
526 return std::move(Interp);
527}
528
529CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); }
530const CompilerInstance *Interpreter::getCompilerInstance() const {
531 return const_cast<Interpreter *>(this)->getCompilerInstance();
532}
533
534llvm::Expected<IncrementalExecutor &> Interpreter::getExecutionEngine() {
535 if (!IncrExecutor) {
536 if (auto Err = CreateExecutor())
537 return std::move(Err);
538 }
539
540 return *IncrExecutor.get();
541}
542
543ASTContext &Interpreter::getASTContext() {
544 return getCompilerInstance()->getASTContext();
545}
546
547const ASTContext &Interpreter::getASTContext() const {
548 return getCompilerInstance()->getASTContext();
549}
550
551void Interpreter::markUserCodeStart() {
552 assert(!InitPTUSize && "We only do this once");
553 InitPTUSize = PTUs.size();
554}
555
556size_t Interpreter::getEffectivePTUSize() const {
557 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
558 return PTUs.size() - InitPTUSize;
559}
560
561llvm::Expected<PartialTranslationUnit &>
562Interpreter::Parse(llvm::StringRef Code) {
563 // If we have a device parser, parse it first. The generated code will be
564 // included in the host compilation
565 if (DeviceParser) {
566 llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Input: Code);
567 if (auto E = DeviceTU.takeError())
568 return std::move(E);
569
570 DeviceParser->RegisterPTU(TU: *DeviceTU);
571
572 llvm::Expected<llvm::StringRef> PTX = DeviceParser->GeneratePTX();
573 if (!PTX)
574 return PTX.takeError();
575
576 llvm::Error Err = DeviceParser->GenerateFatbinary();
577 if (Err)
578 return std::move(Err);
579 }
580
581 // Tell the interpreter sliently ignore unused expressions since value
582 // printing could cause it.
583 getCompilerInstance()->getDiagnostics().setSeverity(
584 Diag: clang::diag::warn_unused_expr, Map: diag::Severity::Ignored, Loc: SourceLocation());
585
586 llvm::Expected<TranslationUnitDecl *> TuOrErr = IncrParser->Parse(Input: Code);
587 if (!TuOrErr)
588 return TuOrErr.takeError();
589
590 PartialTranslationUnit &LastPTU = IncrParser->RegisterPTU(TU: *TuOrErr);
591
592 // Under -emit-llvm, print the module IR.
593 if (InitPTUSize && LastPTU.TheModule &&
594 getCompilerInstance()->getFrontendOpts().ProgramAction ==
595 frontend::EmitLLVM)
596 LastPTU.TheModule->print(OS&: llvm::outs(), /*AAW=*/nullptr);
597
598 return LastPTU;
599}
600
601llvm::Error Interpreter::CreateExecutor() {
602 if (IncrExecutor)
603 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
604 "Execution engine exists",
605 Args: std::error_code());
606 if (!Act->getCodeGen())
607 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
608 "No code generator available",
609 Args: std::error_code());
610
611 if (!IncrExecutorBuilder)
612 IncrExecutorBuilder = std::make_unique<IncrementalExecutorBuilder>();
613
614 // Propagate mllvm args so the wasm executor can restore them after each
615 // lldMain invocation (which resets all cl options for test isolation).
616 IncrExecutorBuilder->LLVMArgs = CI->getFrontendOpts().LLVMArgs;
617
618 auto ExecutorOrErr = IncrExecutorBuilder->create(TSC&: *TSCtx, TI: CI->getTarget());
619 if (ExecutorOrErr)
620 IncrExecutor = std::move(*ExecutorOrErr);
621
622 return ExecutorOrErr.takeError();
623}
624
625llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
626 assert(T.TheModule);
627 LLVM_DEBUG(
628 llvm::dbgs() << "execute-ptu "
629 << (llvm::is_contained(PTUs, T)
630 ? std::distance(PTUs.begin(), llvm::find(PTUs, T))
631 : -1)
632 << ": [TU=" << T.TUPart << ", M=" << T.TheModule.get()
633 << " (" << T.TheModule->getName() << ")]\n");
634 if (!IncrExecutor) {
635 auto Err = CreateExecutor();
636 if (Err)
637 return Err;
638 }
639 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
640 if (auto Err = IncrExecutor->addModule(PTU&: T))
641 return Err;
642
643 if (auto Err = IncrExecutor->runCtors())
644 return Err;
645
646 return llvm::Error::success();
647}
648
649llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
650
651 auto PTU = Parse(Code);
652 if (!PTU)
653 return PTU.takeError();
654 if (PTU->TheModule)
655 if (llvm::Error Err = Execute(T&: *PTU))
656 return Err;
657
658 if (LastValue.isValid()) {
659 if (!V) {
660 LastValue.dump();
661 LastValue.clear();
662 } else
663 *V = std::move(LastValue);
664 }
665 return llvm::Error::success();
666}
667
668llvm::Expected<llvm::orc::ExecutorAddr>
669Interpreter::getSymbolAddress(GlobalDecl GD) const {
670 if (!IncrExecutor)
671 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
672 "No execution engine",
673 Args: std::error_code());
674 llvm::StringRef MangledName = Act->getCodeGen()->GetMangledName(GD);
675 return getSymbolAddress(IRName: MangledName);
676}
677
678llvm::Expected<llvm::orc::ExecutorAddr>
679Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
680 if (!IncrExecutor)
681 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
682 "No execution engine",
683 Args: std::error_code());
684
685 return IncrExecutor->getSymbolAddress(Name: IRName, NameKind: IncrementalExecutor::IRName);
686}
687
688llvm::Expected<llvm::orc::ExecutorAddr>
689Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
690 if (!IncrExecutor)
691 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
692 "No execution engine",
693 Args: std::error_code());
694
695 return IncrExecutor->getSymbolAddress(Name, NameKind: IncrementalExecutor::LinkerName);
696}
697
698llvm::Error Interpreter::Undo(unsigned N) {
699
700 if (getEffectivePTUSize() == 0) {
701 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
702 "No input left to undo",
703 Args: std::error_code());
704 } else if (N > getEffectivePTUSize()) {
705 return llvm::make_error<llvm::StringError>(
706 Args: llvm::formatv(
707 Fmt: "Operation failed. Wanted to undo {0} inputs, only have {1}.", Vals&: N,
708 Vals: getEffectivePTUSize()),
709 Args: std::error_code());
710 }
711
712 for (unsigned I = 0; I < N; I++) {
713 if (IncrExecutor) {
714 if (llvm::Error Err = IncrExecutor->removeModule(PTU&: PTUs.back()))
715 return Err;
716 }
717
718 IncrParser->CleanUpPTU(MostRecentTU: PTUs.back().TUPart);
719 PTUs.pop_back();
720 }
721 return llvm::Error::success();
722}
723
724llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
725 auto EEOrErr = getExecutionEngine();
726 if (!EEOrErr)
727 return EEOrErr.takeError();
728
729 return EEOrErr->LoadDynamicLibrary(name);
730}
731} // end namespace clang
732