18#include "llvm/Support/VirtualFileSystem.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"
56#define DEBUG_TYPE "clang-repl"
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");
77 if (llvm::StringRef(
Cmd->getCreator().getName()) !=
"clang")
78 return llvm::createStringError(llvm::errc::not_supported,
79 "Driver initialization failed");
81 return &
Cmd->getArguments();
85CreateCI(
const llvm::opt::ArgStringList &Argv) {
91 auto PCHOps = Clang->getPCHContainerOperations();
92 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
93 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
101 Clang->getInvocation(),
llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
104 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
105 Clang->getHeaderSearchOpts().ResourceDir.empty())
106 Clang->getHeaderSearchOpts().ResourceDir =
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");
118 return llvm::createStringError(llvm::errc::not_supported,
119 "Initialization failed. "
120 "Unable to flush diagnostics");
123 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(
"").release();
124 Clang->getPreprocessorOpts().addRemappedFile(
"<<< inputs >>>", MB);
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");
133 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
137 Clang->getCodeGenOpts().ClearASTBeforeBackend =
false;
139 Clang->getFrontendOpts().DisableFree =
false;
140 Clang->getCodeGenOpts().DisableFree =
false;
141 return std::move(Clang);
149IncrementalCompilerBuilder::create(std::string TT,
150 std::vector<const char *> &ClangArgv) {
154 std::string MainExecutableName =
155 llvm::sys::fs::getMainExecutable(
nullptr,
nullptr);
157 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
164 ClangArgv.insert(ClangArgv.end(),
"-Xclang");
165 ClangArgv.insert(ClangArgv.end(),
"-fincremental-extensions");
166 ClangArgv.insert(ClangArgv.end(),
"-c");
170 ClangArgv.push_back(
"<<< inputs >>>");
181 Driver.setCheckInputsExist(
false);
183 std::unique_ptr<driver::Compilation> Compilation(
Driver.BuildCompilation(RF));
185 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
186 Compilation->getJobs().Print(llvm::errs(),
"\n",
false);
188 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
189 if (
auto Err = ErrOrCC1Args.takeError())
190 return std::move(Err);
192 return CreateCI(**ErrOrCC1Args);
197 std::vector<const char *> Argv;
198 Argv.reserve(5 + 1 + UserArgs.size());
199 Argv.push_back(
"-xc++");
201 Argv.push_back(
"-target");
202 Argv.push_back(
"wasm32-unknown-emscripten");
203 Argv.push_back(
"-fvisibility=default");
205 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
207 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
208 return IncrementalCompilerBuilder::create(TT, Argv);
212IncrementalCompilerBuilder::createCuda(
bool device) {
213 std::vector<const char *> Argv;
214 Argv.reserve(5 + 4 + UserArgs.size());
216 Argv.push_back(
"-xcuda");
218 Argv.push_back(
"--cuda-device-only");
220 Argv.push_back(
"--cuda-host-only");
222 std::string SDKPathArg =
"--cuda-path=";
223 if (!CudaSDKPath.empty()) {
224 SDKPathArg += CudaSDKPath;
225 Argv.push_back(SDKPathArg.c_str());
228 std::string ArchArg =
"--offload-arch=";
231 Argv.push_back(ArchArg.c_str());
234 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
236 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
237 return IncrementalCompilerBuilder::create(TT, Argv);
242 return IncrementalCompilerBuilder::createCuda(
true);
247 return IncrementalCompilerBuilder::createCuda(
false);
261 if (
auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(
D))
262 if (TLSD && TLSD->isSemiMissing()) {
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: ");
270 TLSD->setStmt(*ExprOrErr);
288 bool IsTerminating =
false;
290 std::unique_ptr<ASTConsumer> Consumer;
295 std::unique_ptr<ASTConsumer> Consumer =
nullptr)
297 llvm::ErrorAsOutParameter EAO(&Err);
298 std::unique_ptr<FrontendAction> Act;
301 Err = llvm::createStringError(
302 std::errc::state_not_recoverable,
303 "Driver initialization failed. "
304 "Incremental mode for action %d is not supported",
323 Interp(I), Consumer(std::move(Consumer)) {}
330 StringRef InFile)
override {
331 std::unique_ptr<ASTConsumer>
C =
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));
341 return std::make_unique<InProcessPrintingASTConsumer>(std::move(
C), Interp);
358 assert(!IsTerminating &&
"Already finalized!");
359 IsTerminating =
true;
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));
374 Act = std::make_unique<IncrementalAction>(*CI, *TSCtx->getContext(), ErrOut,
375 *
this, std::move(Consumer));
378 CI->ExecuteAction(*Act);
380 IncrParser = std::make_unique<IncrementalParser>(*CI, ErrOut);
386 CachedInCodeGenModule = GenModule();
389 if (!CI->getPreprocessorOpts().Includes.empty()) {
393 auto M = llvm::CloneModule(*CachedInCodeGenModule);
395 RegisterPTU(
C.getTranslationUnitDecl(), std::move(M));
398 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
408 if (llvm::Error Err =
Execute(PTU)) {
409 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
417 Act->FinalizeAction();
419 if (llvm::Error Err = IncrExecutor->cleanUp())
420 llvm::report_fatal_error(
421 llvm::Twine(
"Failed to clean up IncrementalExecutor: ") +
430 #define __CLANG_REPL__ 1
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]);
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);
446 #define EXTERN_C extern
449 EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
454 llvm::Error Err = llvm::Error::success();
456 std::unique_ptr<Interpreter>(
new Interpreter(std::move(CI), Err));
458 return std::move(Err);
464 return PTU.takeError();
465 Interp->markUserCodeStart();
467 Interp->ValuePrintingInfo.resize(4);
468 return std::move(Interp);
473 std::unique_ptr<CompilerInstance> DCI) {
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);
484 if (
auto E = Interp.takeError())
487 llvm::Error Err = llvm::Error::success();
488 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
489 std::move(DCI), *(*Interp)->getCompilerInstance(), IMVFS, Err,
492 return std::move(Err);
494 (*Interp)->DeviceParser = std::move(DeviceParser);
508 return std::move(Err);
511 return IncrExecutor->GetExecutionEngine();
522void Interpreter::markUserCodeStart() {
523 assert(!InitPTUSize &&
"We only do this once");
524 InitPTUSize = PTUs.size();
527size_t Interpreter::getEffectivePTUSize()
const {
528 assert(PTUs.size() >= InitPTUSize &&
"empty PTU list?");
529 return PTUs.size() - InitPTUSize;
534 std::unique_ptr<llvm::Module> M ) {
542 assert((!getCodeGen() || M) &&
"Must have a llvm::Module at this point");
545 LLVM_DEBUG(llvm::dbgs() <<
"compile-ptu " << PTUs.size() - 1
546 <<
": [TU=" << LastPTU.
TUPart);
548 LLVM_DEBUG(llvm::dbgs() <<
", M=" << LastPTU.
TheModule.get() <<
" ("
550 LLVM_DEBUG(llvm::dbgs() <<
"]\n");
560 if (
auto E = DeviceTU.takeError())
571 return TuOrErr.takeError();
573 return RegisterPTU(*TuOrErr);
578 if (TT == llvm::sys::getProcessTriple())
580 return llvm::orc::JITTargetMachineBuilder::detectHost();
583 return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
588 return llvm::make_error<llvm::StringError>(
"Operation failed. "
589 "Execution engine exists",
592 return llvm::make_error<llvm::StringError>(
"Operation failed. "
593 "No code generator available",
599 return JTMB.takeError();
602 return JB.takeError();
603 JITBuilder = std::move(*JB);
606 llvm::Error Err = llvm::Error::success();
608 auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
611 std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
614 IncrExecutor = std::move(Executor);
623 LLVM_DEBUG(llvm::dbgs()
625 << ((std::find(PTUs.begin(), PTUs.end(),
T) != PTUs.end())
626 ? std::distance(PTUs.begin(),
627 std::find(PTUs.begin(), PTUs.end(),
T))
629 <<
": [TU=" <<
T.TUPart <<
", M=" <<
T.TheModule.get() <<
" ("
630 <<
T.TheModule->getName() <<
")]\n");
637 if (
auto Err = IncrExecutor->addModule(
T))
640 if (
auto Err = IncrExecutor->runCtors())
643 return llvm::Error::success();
648 auto PTU =
Parse(Code);
650 return PTU.takeError();
652 if (llvm::Error Err =
Execute(*PTU))
660 *
V = std::move(LastValue);
662 return llvm::Error::success();
668 return llvm::make_error<llvm::StringError>(
"Operation failed. "
669 "No execution engine",
678 return llvm::make_error<llvm::StringError>(
"Operation failed. "
679 "No execution engine",
688 return llvm::make_error<llvm::StringError>(
"Operation failed. "
689 "No execution engine",
697 if (N > getEffectivePTUSize())
698 return llvm::make_error<llvm::StringError>(
"Operation failed. "
701 for (
unsigned I = 0; I < N; I++) {
703 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
707 IncrParser->CleanUpPTU(PTUs.back().TUPart);
710 return llvm::Error::success();
716 return EE.takeError();
718 auto &DL = EE->getDataLayout();
720 if (
auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
721 name, DL.getGlobalPrefix()))
722 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
724 return DLSG.takeError();
726 return llvm::Error::success();
729std::unique_ptr<llvm::Module> Interpreter::GenModule() {
730 static unsigned ID = 0;
739 assert(((!CachedInCodeGenModule ||
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());
757 return static_cast<CodeGenAction *
>(WrappedAct)->getCodeGenerator();
Defines the clang::ASTContext interface.
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
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 ...
The primary public interface to the Clang code generator.
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.
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.
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
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.
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.
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)
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.
Encodes a location in the source.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
std::string Triple
The name of the target triple to compile for.
void FlushDiagnostics(DiagnosticsEngine &Diags) const
FlushDiagnostics - Flush the buffered diagnostics to an given diagnostic engine.
The top declaration context.
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.
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
JobList - A sequence of jobs to perform.
Defines the clang::TargetInfo interface.
@ Ignored
Do not present this diagnostic, ignore it.
@ PrintPreprocessedInput
-E mode.
@ ParseSyntaxOnly
Parse and perform semantic analysis.
@ PluginAction
Run a plugin action,.
@ 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)
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.
@ TU_Incremental
The translation unit is a is a complete translation unit that we might incrementally extend later.
const FunctionProtoType * T
@ Success
Template argument deduction was successful.
bool(*)(llvm::ArrayRef< const char * >, llvm::raw_ostream &, llvm::raw_ostream &, bool, bool) Driver
The class keeps track of various objects created as part of processing incremental inputs.
TranslationUnitDecl * TUPart
std::unique_ptr< llvm::Module > TheModule
The llvm IR produced for the input.