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