clang 20.0.0git
Interpreter.cpp
Go to the documentation of this file.
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#endif // __EMSCRIPTEN__
22
25#include "clang/AST/Mangle.h"
33#include "clang/Driver/Driver.h"
34#include "clang/Driver/Job.h"
36#include "clang/Driver/Tool.h"
45#include "clang/Sema/Lookup.h"
47#include "llvm/ExecutionEngine/JITSymbol.h"
48#include "llvm/ExecutionEngine/Orc/LLJIT.h"
49#include "llvm/IR/Module.h"
50#include "llvm/Support/Errc.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/raw_ostream.h"
53#include "llvm/TargetParser/Host.h"
54#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule
55
56#define DEBUG_TYPE "clang-repl"
57
58using namespace clang;
59// FIXME: Figure out how to unify with namespace init_convenience from
60// tools/clang-import-test/clang-import-test.cpp
61namespace {
62/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
63/// \returns NULL on error.
65GetCC1Arguments(DiagnosticsEngine *Diagnostics,
66 driver::Compilation *Compilation) {
67 // We expect to get back exactly one Command job, if we didn't something
68 // failed. Extract that job from the Compilation.
69 const driver::JobList &Jobs = Compilation->getJobs();
70 if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))
71 return llvm::createStringError(llvm::errc::not_supported,
72 "Driver initialization failed. "
73 "Unable to create a driver job");
74
75 // The one job we find should be to invoke clang again.
76 const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
77 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
78 return llvm::createStringError(llvm::errc::not_supported,
79 "Driver initialization failed");
80
81 return &Cmd->getArguments();
82}
83
85CreateCI(const llvm::opt::ArgStringList &Argv) {
86 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
88
89 // Register the support for object-file-wrapped Clang modules.
90 // FIXME: Clang should register these container operations automatically.
91 auto PCHOps = Clang->getPCHContainerOperations();
92 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
93 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
94
95 // Buffer diagnostics from argument parsing so that we can output them using
96 // a well formed diagnostic object.
99 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
101 Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
102
103 // Infer the builtin include path if unspecified.
104 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
105 Clang->getHeaderSearchOpts().ResourceDir.empty())
106 Clang->getHeaderSearchOpts().ResourceDir =
107 CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
108
109 // Create the actual diagnostics engine.
110 Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
111 if (!Clang->hasDiagnostics())
112 return llvm::createStringError(llvm::errc::not_supported,
113 "Initialization failed. "
114 "Unable to create diagnostics engine");
115
116 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
117 if (!Success)
118 return llvm::createStringError(llvm::errc::not_supported,
119 "Initialization failed. "
120 "Unable to flush diagnostics");
121
122 // FIXME: Merge with CompilerInstance::ExecuteAction.
123 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
124 Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
125
126 Clang->setTarget(TargetInfo::CreateTargetInfo(
127 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
128 if (!Clang->hasTarget())
129 return llvm::createStringError(llvm::errc::not_supported,
130 "Initialization failed. "
131 "Target is missing");
132
133 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
134
135 // Don't clear the AST before backend codegen since we do codegen multiple
136 // times, reusing the same AST.
137 Clang->getCodeGenOpts().ClearASTBeforeBackend = false;
138
139 Clang->getFrontendOpts().DisableFree = false;
140 Clang->getCodeGenOpts().DisableFree = false;
141 return std::move(Clang);
142}
143
144} // anonymous namespace
145
146namespace clang {
147
149IncrementalCompilerBuilder::create(std::string TT,
150 std::vector<const char *> &ClangArgv) {
151
152 // If we don't know ClangArgv0 or the address of main() at this point, try
153 // to guess it anyway (it's possible on some platforms).
154 std::string MainExecutableName =
155 llvm::sys::fs::getMainExecutable(nullptr, nullptr);
156
157 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
158
159 // Prepending -c to force the driver to do something if no action was
160 // specified. By prepending we allow users to override the default
161 // action and use other actions in incremental mode.
162 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
163 // We do C++ by default; append right after argv[0] if no "-x" given
164 ClangArgv.insert(ClangArgv.end(), "-Xclang");
165 ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
166 ClangArgv.insert(ClangArgv.end(), "-c");
167
168 // Put a dummy C++ file on to ensure there's at least one compile job for the
169 // driver to construct.
170 ClangArgv.push_back("<<< inputs >>>");
171
172 // Buffer diagnostics from argument parsing so that we can output them using a
173 // well formed diagnostic object.
176 CreateAndPopulateDiagOpts(ClangArgv);
178 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
179
180 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
181 Driver.setCheckInputsExist(false); // the input comes from mem buffers
183 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
184
185 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
186 Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
187
188 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
189 if (auto Err = ErrOrCC1Args.takeError())
190 return std::move(Err);
191
192 return CreateCI(**ErrOrCC1Args);
193}
194
197 std::vector<const char *> Argv;
198 Argv.reserve(5 + 1 + UserArgs.size());
199 Argv.push_back("-xc++");
200#ifdef __EMSCRIPTEN__
201 Argv.push_back("-target");
202 Argv.push_back("wasm32-unknown-emscripten");
203 Argv.push_back("-fvisibility=default");
204#endif
205 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
206
207 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
208 return IncrementalCompilerBuilder::create(TT, Argv);
209}
210
212IncrementalCompilerBuilder::createCuda(bool device) {
213 std::vector<const char *> Argv;
214 Argv.reserve(5 + 4 + UserArgs.size());
215
216 Argv.push_back("-xcuda");
217 if (device)
218 Argv.push_back("--cuda-device-only");
219 else
220 Argv.push_back("--cuda-host-only");
221
222 std::string SDKPathArg = "--cuda-path=";
223 if (!CudaSDKPath.empty()) {
224 SDKPathArg += CudaSDKPath;
225 Argv.push_back(SDKPathArg.c_str());
226 }
227
228 std::string ArchArg = "--offload-arch=";
229 if (!OffloadArch.empty()) {
230 ArchArg += OffloadArch;
231 Argv.push_back(ArchArg.c_str());
232 }
233
234 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
235
236 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
237 return IncrementalCompilerBuilder::create(TT, Argv);
238}
239
242 return IncrementalCompilerBuilder::createCuda(true);
243}
244
247 return IncrementalCompilerBuilder::createCuda(false);
248}
249
251 Interpreter &Interp;
252
253public:
254 InProcessPrintingASTConsumer(std::unique_ptr<ASTConsumer> C, Interpreter &I)
255 : MultiplexConsumer(std::move(C)), Interp(I) {}
256 bool HandleTopLevelDecl(DeclGroupRef DGR) override final {
257 if (DGR.isNull())
258 return true;
259
260 for (Decl *D : DGR)
261 if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D))
262 if (TLSD && TLSD->isSemiMissing()) {
263 auto ExprOrErr =
264 Interp.ExtractValueFromExpr(cast<Expr>(TLSD->getStmt()));
265 if (llvm::Error E = ExprOrErr.takeError()) {
266 llvm::logAllUnhandledErrors(std::move(E), llvm::errs(),
267 "Value printing failed: ");
268 return false; // abort parsing
269 }
270 TLSD->setStmt(*ExprOrErr);
271 }
272
274 }
275};
276
277/// A custom action enabling the incremental processing functionality.
278///
279/// The usual \p FrontendAction expects one call to ExecuteAction and once it
280/// sees a call to \p EndSourceFile it deletes some of the important objects
281/// such as \p Preprocessor and \p Sema assuming no further input will come.
282///
283/// \p IncrementalAction ensures it keep its underlying action's objects alive
284/// as long as the \p IncrementalParser needs them.
285///
287private:
288 bool IsTerminating = false;
289 Interpreter &Interp;
290 std::unique_ptr<ASTConsumer> Consumer;
291
292public:
293 IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx,
294 llvm::Error &Err, Interpreter &I,
295 std::unique_ptr<ASTConsumer> Consumer = nullptr)
296 : WrapperFrontendAction([&]() {
297 llvm::ErrorAsOutParameter EAO(&Err);
298 std::unique_ptr<FrontendAction> Act;
299 switch (CI.getFrontendOpts().ProgramAction) {
300 default:
301 Err = llvm::createStringError(
302 std::errc::state_not_recoverable,
303 "Driver initialization failed. "
304 "Incremental mode for action %d is not supported",
306 return Act;
310 Act = CreateFrontendAction(CI);
311 break;
314 case frontend::EmitBC:
318 Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
319 break;
320 }
321 return Act;
322 }()),
323 Interp(I), Consumer(std::move(Consumer)) {}
324 FrontendAction *getWrapped() const { return WrappedAction.get(); }
326 return TU_Incremental;
327 }
328
329 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
330 StringRef InFile) override {
331 std::unique_ptr<ASTConsumer> C =
333
334 if (Consumer) {
335 std::vector<std::unique_ptr<ASTConsumer>> Cs;
336 Cs.push_back(std::move(Consumer));
337 Cs.push_back(std::move(C));
338 return std::make_unique<MultiplexConsumer>(std::move(Cs));
339 }
340
341 return std::make_unique<InProcessPrintingASTConsumer>(std::move(C), Interp);
342 }
343
344 void ExecuteAction() override {
347 }
348
349 // Do not terminate after processing the input. This allows us to keep various
350 // clang objects alive and to incrementally grow the current TU.
351 void EndSourceFile() override {
352 // The WrappedAction can be nullptr if we issued an error in the ctor.
353 if (IsTerminating && getWrapped())
355 }
356
358 assert(!IsTerminating && "Already finalized!");
359 IsTerminating = true;
361 }
362};
363
364Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
365 llvm::Error &ErrOut,
366 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,
367 std::unique_ptr<clang::ASTConsumer> Consumer)
368 : JITBuilder(std::move(JITBuilder)) {
369 CI = std::move(Instance);
370 llvm::ErrorAsOutParameter EAO(&ErrOut);
371 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
372 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
373
374 Act = std::make_unique<IncrementalAction>(*CI, *TSCtx->getContext(), ErrOut,
375 *this, std::move(Consumer));
376 if (ErrOut)
377 return;
378 CI->ExecuteAction(*Act);
379
380 IncrParser = std::make_unique<IncrementalParser>(*CI, ErrOut);
381
382 if (ErrOut)
383 return;
384
385 if (getCodeGen()) {
386 CachedInCodeGenModule = GenModule();
387 // The initial PTU is filled by `-include` or by CUDA includes
388 // automatically.
389 if (!CI->getPreprocessorOpts().Includes.empty()) {
390 // We can't really directly pass the CachedInCodeGenModule to the Jit
391 // because it will steal it, causing dangling references as explained in
392 // Interpreter::Execute
393 auto M = llvm::CloneModule(*CachedInCodeGenModule);
394 ASTContext &C = CI->getASTContext();
395 RegisterPTU(C.getTranslationUnitDecl(), std::move(M));
396 }
397 if (llvm::Error Err = CreateExecutor()) {
398 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
399 return;
400 }
401 }
402
403 // Not all frontends support code-generation, e.g. ast-dump actions don't
404 if (getCodeGen()) {
405 // Process the PTUs that came from initialization. For example -include will
406 // give us a header that's processed at initialization of the preprocessor.
407 for (PartialTranslationUnit &PTU : PTUs)
408 if (llvm::Error Err = Execute(PTU)) {
409 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
410 return;
411 }
412 }
413}
414
416 IncrParser.reset();
417 Act->FinalizeAction();
418 if (IncrExecutor) {
419 if (llvm::Error Err = IncrExecutor->cleanUp())
420 llvm::report_fatal_error(
421 llvm::Twine("Failed to clean up IncrementalExecutor: ") +
422 toString(std::move(Err)));
423 }
424}
425
426// These better to put in a runtime header but we can't. This is because we
427// can't find the precise resource directory in unittests so we have to hard
428// code them.
429const char *const Runtimes = R"(
430 #define __CLANG_REPL__ 1
431#ifdef __cplusplus
432 #define EXTERN_C extern "C"
433 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
434 struct __clang_Interpreter_NewTag{} __ci_newtag;
435 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
436 template <class T, class = T (*)() /*disable for arrays*/>
437 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
438 for (auto Idx = 0; Idx < Size; ++Idx)
439 new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
440 }
441 template <class T, unsigned long N>
442 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
443 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
444 }
445#else
446 #define EXTERN_C extern
447#endif // __cplusplus
448
449 EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
450)";
451
453Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
454 llvm::Error Err = llvm::Error::success();
455 auto Interp =
456 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
457 if (Err)
458 return std::move(Err);
459
460 // Add runtime code and set a marker to hide it from user code. Undo will not
461 // go through that.
462 auto PTU = Interp->Parse(Runtimes);
463 if (!PTU)
464 return PTU.takeError();
465 Interp->markUserCodeStart();
466
467 Interp->ValuePrintingInfo.resize(4);
468 return std::move(Interp);
470
472Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
473 std::unique_ptr<CompilerInstance> DCI) {
474 // avoid writing fat binary to disk using an in-memory virtual file system
476 std::make_unique<llvm::vfs::InMemoryFileSystem>();
478 std::make_unique<llvm::vfs::OverlayFileSystem>(
479 llvm::vfs::getRealFileSystem());
480 OverlayVFS->pushOverlay(IMVFS);
481 CI->createFileManager(OverlayVFS);
482
483 auto Interp = Interpreter::create(std::move(CI));
484 if (auto E = Interp.takeError())
485 return std::move(E);
486
487 llvm::Error Err = llvm::Error::success();
488 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
489 std::move(DCI), *(*Interp)->getCompilerInstance(), IMVFS, Err,
490 (*Interp)->PTUs);
491 if (Err)
492 return std::move(Err);
493
494 (*Interp)->DeviceParser = std::move(DeviceParser);
495
496 return Interp;
497}
498
500 return CI.get();
501}
504
506 if (!IncrExecutor) {
507 if (auto Err = CreateExecutor())
508 return std::move(Err);
509 }
510
511 return IncrExecutor->GetExecutionEngine();
512}
513
516}
517
520}
521
522void Interpreter::markUserCodeStart() {
523 assert(!InitPTUSize && "We only do this once");
524 InitPTUSize = PTUs.size();
525}
526
527size_t Interpreter::getEffectivePTUSize() const {
528 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
529 return PTUs.size() - InitPTUSize;
530}
531
533Interpreter::RegisterPTU(TranslationUnitDecl *TU,
534 std::unique_ptr<llvm::Module> M /*={}*/) {
535 PTUs.emplace_back(PartialTranslationUnit());
536 PartialTranslationUnit &LastPTU = PTUs.back();
537 LastPTU.TUPart = TU;
538
539 if (!M)
540 M = GenModule();
541
542 assert((!getCodeGen() || M) && "Must have a llvm::Module at this point");
543
544 LastPTU.TheModule = std::move(M);
545 LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1
546 << ": [TU=" << LastPTU.TUPart);
547 if (LastPTU.TheModule)
548 LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " ("
549 << LastPTU.TheModule->getName() << ")");
550 LLVM_DEBUG(llvm::dbgs() << "]\n");
551 return LastPTU;
553
555Interpreter::Parse(llvm::StringRef Code) {
556 // If we have a device parser, parse it first. The generated code will be
557 // included in the host compilation
558 if (DeviceParser) {
559 llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Code);
560 if (auto E = DeviceTU.takeError())
561 return std::move(E);
562 }
563
564 // Tell the interpreter sliently ignore unused expressions since value
565 // printing could cause it.
567 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
568
569 llvm::Expected<TranslationUnitDecl *> TuOrErr = IncrParser->Parse(Code);
570 if (!TuOrErr)
571 return TuOrErr.takeError();
572
573 return RegisterPTU(*TuOrErr);
575
577createJITTargetMachineBuilder(const std::string &TT) {
578 if (TT == llvm::sys::getProcessTriple())
579 // This fails immediately if the target backend is not registered
580 return llvm::orc::JITTargetMachineBuilder::detectHost();
581
582 // If the target backend is not registered, LLJITBuilder::create() will fail
583 return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
584}
585
586llvm::Error Interpreter::CreateExecutor() {
587 if (IncrExecutor)
588 return llvm::make_error<llvm::StringError>("Operation failed. "
589 "Execution engine exists",
590 std::error_code());
591 if (!getCodeGen())
592 return llvm::make_error<llvm::StringError>("Operation failed. "
593 "No code generator available",
594 std::error_code());
595 if (!JITBuilder) {
596 const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
597 auto JTMB = createJITTargetMachineBuilder(TT);
598 if (!JTMB)
599 return JTMB.takeError();
600 auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
601 if (!JB)
602 return JB.takeError();
603 JITBuilder = std::move(*JB);
604 }
605
606 llvm::Error Err = llvm::Error::success();
607#ifdef __EMSCRIPTEN__
608 auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
609#else
610 auto Executor =
611 std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
612#endif
613 if (!Err)
614 IncrExecutor = std::move(Executor);
615
616 return Err;
617}
619void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
620
622 assert(T.TheModule);
623 LLVM_DEBUG(llvm::dbgs()
624 << "execute-ptu "
625 << ((std::find(PTUs.begin(), PTUs.end(), T) != PTUs.end())
626 ? std::distance(PTUs.begin(),
627 std::find(PTUs.begin(), PTUs.end(), T))
628 : -1)
629 << ": [TU=" << T.TUPart << ", M=" << T.TheModule.get() << " ("
630 << T.TheModule->getName() << ")]\n");
631 if (!IncrExecutor) {
632 auto Err = CreateExecutor();
633 if (Err)
634 return Err;
635 }
636 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
637 if (auto Err = IncrExecutor->addModule(T))
638 return Err;
639
640 if (auto Err = IncrExecutor->runCtors())
641 return Err;
642
643 return llvm::Error::success();
644}
645
646llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
647
648 auto PTU = Parse(Code);
649 if (!PTU)
650 return PTU.takeError();
651 if (PTU->TheModule)
652 if (llvm::Error Err = Execute(*PTU))
653 return Err;
654
655 if (LastValue.isValid()) {
656 if (!V) {
657 LastValue.dump();
658 LastValue.clear();
659 } else
660 *V = std::move(LastValue);
661 }
662 return llvm::Error::success();
664
667 if (!IncrExecutor)
668 return llvm::make_error<llvm::StringError>("Operation failed. "
669 "No execution engine",
670 std::error_code());
671 llvm::StringRef MangledName = getCodeGen()->GetMangledName(GD);
672 return getSymbolAddress(MangledName);
674
676Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
677 if (!IncrExecutor)
678 return llvm::make_error<llvm::StringError>("Operation failed. "
679 "No execution engine",
680 std::error_code());
681
682 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
684
686Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
687 if (!IncrExecutor)
688 return llvm::make_error<llvm::StringError>("Operation failed. "
689 "No execution engine",
690 std::error_code());
691
692 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
693}
694
695llvm::Error Interpreter::Undo(unsigned N) {
696
697 if (N > getEffectivePTUSize())
698 return llvm::make_error<llvm::StringError>("Operation failed. "
699 "Too many undos",
700 std::error_code());
701 for (unsigned I = 0; I < N; I++) {
702 if (IncrExecutor) {
703 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
704 return Err;
705 }
706
707 IncrParser->CleanUpPTU(PTUs.back().TUPart);
708 PTUs.pop_back();
709 }
710 return llvm::Error::success();
711}
712
713llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
714 auto EE = getExecutionEngine();
715 if (!EE)
716 return EE.takeError();
717
718 auto &DL = EE->getDataLayout();
719
720 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
721 name, DL.getGlobalPrefix()))
722 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
723 else
724 return DLSG.takeError();
725
726 return llvm::Error::success();
727}
728
729std::unique_ptr<llvm::Module> Interpreter::GenModule() {
730 static unsigned ID = 0;
731 if (CodeGenerator *CG = getCodeGen()) {
732 // Clang's CodeGen is designed to work with a single llvm::Module. In many
733 // cases for convenience various CodeGen parts have a reference to the
734 // llvm::Module (TheModule or Module) which does not change when a new
735 // module is pushed. However, the execution engine wants to take ownership
736 // of the module which does not map well to CodeGen's design. To work this
737 // around we created an empty module to make CodeGen happy. We should make
738 // sure it always stays empty.
739 assert(((!CachedInCodeGenModule ||
740 !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) ||
741 (CachedInCodeGenModule->empty() &&
742 CachedInCodeGenModule->global_empty() &&
743 CachedInCodeGenModule->alias_empty() &&
744 CachedInCodeGenModule->ifunc_empty())) &&
745 "CodeGen wrote to a readonly module");
746 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
747 CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
748 return M;
749 }
750 return nullptr;
751}
752
753CodeGenerator *Interpreter::getCodeGen() const {
754 FrontendAction *WrappedAct = Act->getWrapped();
755 if (!WrappedAct->hasIRSupport())
756 return nullptr;
757 return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
758}
759} // namespace clang
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3443
const Decl * D
Expr * E
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
CompileCommand Cmd
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
The primary public interface to the Clang code generator.
Definition: ModuleBuilder.h:52
llvm::StringRef GetMangledName(GlobalDecl GD)
Given a global declaration, return a mangled name for this declaration which has been added to this c...
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
ASTContext & getASTContext() const
TargetOptions & getTargetOpts()
FrontendOptions & getFrontendOpts()
static std::string GetResourcesPath(const char *Argv0, void *MainAddr)
Get the directory where the compiler headers reside, relative to the compiler binary (found by the pa...
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:231
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
Definition: Diagnostic.cpp:344
Abstract base class for actions which can be performed by the frontend.
virtual bool hasIRSupport() const
Does this action support use with IR files?
CompilerInstance & getCompilerInstance() const
frontend::ActionKind ProgramAction
The frontend action to perform.
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:56
bool HandleTopLevelDecl(DeclGroupRef DGR) override final
HandleTopLevelDecl - Handle the specified top-level declaration.
InProcessPrintingASTConsumer(std::unique_ptr< ASTConsumer > C, Interpreter &I)
A custom action enabling the incremental processing functionality.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, llvm::Error &Err, Interpreter &I, std::unique_ptr< ASTConsumer > Consumer=nullptr)
TranslationUnitKind getTranslationUnitKind() override
For AST-based actions, the kind of translation unit we're handling.
FrontendAction * getWrapped() const
void EndSourceFile() override
Perform any per-file post processing, deallocate per-file objects, and run statistics and output file...
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaHost()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaDevice()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCpp()
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB)
Provides top-level interfaces for incremental compilation and execution.
Definition: Interpreter.h:85
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V=nullptr)
llvm::Error CreateExecutor()
Interpreter(std::unique_ptr< CompilerInstance > Instance, llvm::Error &Err, std::unique_ptr< llvm::orc::LLJITBuilder > JITBuilder=nullptr, std::unique_ptr< clang::ASTConsumer > Consumer=nullptr)
static llvm::Expected< std::unique_ptr< Interpreter > > create(std::unique_ptr< CompilerInstance > CI)
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
llvm::Error LoadDynamicLibrary(const char *name)
Link a dynamic library.
static llvm::Expected< std::unique_ptr< Interpreter > > createWithCUDA(std::unique_ptr< CompilerInstance > CI, std::unique_ptr< CompilerInstance > DCI)
virtual ~Interpreter()
llvm::Expected< PartialTranslationUnit & > Parse(llvm::StringRef Code)
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const
llvm::Error Undo(unsigned N=1)
Undo N previous incremental inputs.
const CompilerInstance * getCompilerInstance() const
const ASTContext & getASTContext() const
llvm::Expected< llvm::orc::LLJIT & > getExecutionEngine()
llvm::Error Execute(PartialTranslationUnit &T)
bool HandleTopLevelDecl(DeclGroupRef D) override
HandleTopLevelDecl - Handle the specified top-level declaration.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1043
Encodes a location in the source.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
Definition: Targets.cpp:755
std::string Triple
The name of the target triple to compile for.
Definition: TargetOptions.h:29
void FlushDiagnostics(DiagnosticsEngine &Diags) const
FlushDiagnostics - Flush the buffered diagnostics to an given diagnostic engine.
The top declaration context.
Definition: Decl.h:84
void dump() const
Definition: Value.cpp:256
void clear()
Definition: Value.cpp:218
bool isValid() const
Definition: Value.h:133
A frontend action which simply wraps some other runtime-specified frontend action.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
std::unique_ptr< FrontendAction > WrappedAction
void EndSourceFile() override
Perform any per-file post processing, deallocate per-file objects, and run statistics and output file...
Command - An executable path/name and argument vector to execute.
Definition: Job.h:106
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:77
JobList - A sequence of jobs to perform.
Definition: Job.h:260
size_type size() const
Definition: Job.h:283
iterator begin()
Definition: Job.h:284
Defines the clang::TargetInfo interface.
@ Ignored
Do not present this diagnostic, ignore it.
@ PrintPreprocessedInput
-E mode.
@ ParseSyntaxOnly
Parse and perform semantic analysis.
@ EmitBC
Emit a .bc file.
@ PluginAction
Run a plugin action,.
@ EmitObj
Emit a .o file.
@ ASTPrint
Parse ASTs and print them.
@ ASTDump
Parse ASTs and dump them.
@ EmitAssembly
Emit a .s file.
@ EmitLLVMOnly
Generate LLVM IR, but do not emit anything.
The JSON file list parser is used to communicate input to InstallAPI.
static llvm::Expected< llvm::orc::JITTargetMachineBuilder > createJITTargetMachineBuilder(const std::string &TT)
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
OffloadArch
Definition: Cuda.h:56
std::unique_ptr< FrontendAction > CreateFrontendAction(CompilerInstance &CI)
Construct the FrontendAction of a compiler invocation based on the options specified for the compiler...
const char *const Runtimes
TranslationUnitKind
Describes the kind of translation unit being processed.
Definition: LangOptions.h:1096
@ TU_Incremental
The translation unit is a is a complete translation unit that we might incrementally extend later.
Definition: LangOptions.h:1109
const FunctionProtoType * T
@ Success
Template argument deduction was successful.
bool(*)(llvm::ArrayRef< const char * >, llvm::raw_ostream &, llvm::raw_ostream &, bool, bool) Driver
Definition: Wasm.cpp:36
The class keeps track of various objects created as part of processing incremental inputs.
std::unique_ptr< llvm::Module > TheModule
The llvm IR produced for the input.