19#include "llvm/Support/VirtualFileSystem.h"
48#include "llvm/ExecutionEngine/JITSymbol.h"
49#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
50#include "llvm/ExecutionEngine/Orc/LLJIT.h"
51#include "llvm/IR/Module.h"
52#include "llvm/Support/Errc.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/raw_ostream.h"
55#include "llvm/TargetParser/Host.h"
56#include "llvm/Transforms/Utils/Cloning.h"
58#define DEBUG_TYPE "clang-repl"
72 if (!Jobs.
size() || !isa<driver::Command>(*Jobs.
begin()))
73 return llvm::createStringError(llvm::errc::not_supported,
74 "Driver initialization failed. "
75 "Unable to create a driver job");
79 if (llvm::StringRef(
Cmd->getCreator().getName()) !=
"clang")
80 return llvm::createStringError(llvm::errc::not_supported,
81 "Driver initialization failed");
83 return &
Cmd->getArguments();
87CreateCI(
const llvm::opt::ArgStringList &Argv) {
92 auto PCHOps = Clang->getPCHContainerOperations();
93 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
94 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
102 Clang->getInvocation(),
llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
105 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
106 Clang->getHeaderSearchOpts().ResourceDir.empty())
107 Clang->getHeaderSearchOpts().ResourceDir =
111 Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
112 if (!Clang->hasDiagnostics())
113 return llvm::createStringError(llvm::errc::not_supported,
114 "Initialization failed. "
115 "Unable to create diagnostics engine");
119 return llvm::createStringError(llvm::errc::not_supported,
120 "Initialization failed. "
121 "Unable to flush diagnostics");
124 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(
"").release();
125 Clang->getPreprocessorOpts().addRemappedFile(
"<<< inputs >>>", MB);
128 Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));
129 if (!Clang->hasTarget())
130 return llvm::createStringError(llvm::errc::not_supported,
131 "Initialization failed. "
132 "Target is missing");
134 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts(),
135 Clang->getAuxTarget());
139 Clang->getCodeGenOpts().ClearASTBeforeBackend =
false;
141 Clang->getFrontendOpts().DisableFree =
false;
142 Clang->getCodeGenOpts().DisableFree =
false;
143 return std::move(Clang);
151IncrementalCompilerBuilder::create(std::string TT,
152 std::vector<const char *> &ClangArgv) {
156 std::string MainExecutableName =
157 llvm::sys::fs::getMainExecutable(
nullptr,
nullptr);
159 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
166 ClangArgv.insert(ClangArgv.end(),
"-Xclang");
167 ClangArgv.insert(ClangArgv.end(),
"-fincremental-extensions");
168 ClangArgv.insert(ClangArgv.end(),
"-c");
172 ClangArgv.push_back(
"<<< inputs >>>");
176 std::unique_ptr<DiagnosticOptions> DiagOpts =
182 Driver.setCheckInputsExist(
false);
184 std::unique_ptr<driver::Compilation> Compilation(
Driver.BuildCompilation(RF));
186 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
187 Compilation->getJobs().Print(llvm::errs(),
"\n",
false);
189 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
190 if (
auto Err = ErrOrCC1Args.takeError())
191 return std::move(Err);
193 return CreateCI(**ErrOrCC1Args);
198 std::vector<const char *> Argv;
199 Argv.reserve(5 + 1 + UserArgs.size());
200 Argv.push_back(
"-xc++");
202 Argv.push_back(
"-target");
203 Argv.push_back(
"wasm32-unknown-emscripten");
204 Argv.push_back(
"-fvisibility=default");
206 llvm::append_range(Argv, UserArgs);
208 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
209 return IncrementalCompilerBuilder::create(TT, Argv);
213IncrementalCompilerBuilder::createCuda(
bool device) {
214 std::vector<const char *> Argv;
215 Argv.reserve(5 + 4 + UserArgs.size());
217 Argv.push_back(
"-xcuda");
219 Argv.push_back(
"--cuda-device-only");
221 Argv.push_back(
"--cuda-host-only");
223 std::string SDKPathArg =
"--cuda-path=";
224 if (!CudaSDKPath.empty()) {
225 SDKPathArg += CudaSDKPath;
226 Argv.push_back(SDKPathArg.c_str());
229 std::string ArchArg =
"--offload-arch=";
232 Argv.push_back(ArchArg.c_str());
235 llvm::append_range(Argv, UserArgs);
237 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
238 return IncrementalCompilerBuilder::create(TT, Argv);
243 return IncrementalCompilerBuilder::createCuda(
true);
248 return IncrementalCompilerBuilder::createCuda(
false);
253 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,
254 std::unique_ptr<clang::ASTConsumer> Consumer)
255 : JITBuilder(
std::move(JITBuilder)) {
256 CI = std::move(Instance);
257 llvm::ErrorAsOutParameter EAO(&ErrOut);
258 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
259 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
261 Act = TSCtx->withContextDo([&](llvm::LLVMContext *Ctx) {
262 return std::make_unique<IncrementalAction>(*CI, *Ctx, ErrOut, *
this,
263 std::move(Consumer));
268 CI->ExecuteAction(*Act);
271 std::make_unique<IncrementalParser>(*CI, Act.get(), ErrOut, PTUs);
276 if (Act->getCodeGen()) {
277 Act->CacheCodeGenModule();
280 if (!CI->getPreprocessorOpts().Includes.empty()) {
284 auto M = llvm::CloneModule(*Act->getCachedCodeGenModule());
286 IncrParser->RegisterPTU(
C.getTranslationUnitDecl(), std::move(M));
289 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
295 if (Act->getCodeGen()) {
299 if (llvm::Error Err =
Execute(PTU)) {
300 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
308 Act->FinalizeAction();
310 DeviceParser.reset();
312 DeviceAct->FinalizeAction();
314 if (llvm::Error Err = IncrExecutor->cleanUp())
315 llvm::report_fatal_error(
316 llvm::Twine(
"Failed to clean up IncrementalExecutor: ") +
325 #define __CLANG_REPL__ 1
327 #define EXTERN_C extern "C"
328 struct __clang_Interpreter_NewTag{} __ci_newtag;
329 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
330 template <class T, class = T (*)() /*disable for arrays*/>
331 void __clang_Interpreter_SetValueCopyArr(const T* Src, void* Placement, unsigned long Size) {
332 for (auto Idx = 0; Idx < Size; ++Idx)
333 new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
335 template <class T, unsigned long N>
336 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
337 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
340 #define EXTERN_C extern
341 EXTERN_C void *memcpy(void *restrict dst, const void *restrict src, __SIZE_TYPE__ n);
342 EXTERN_C inline void __clang_Interpreter_SetValueCopyArr(const void* Src, void* Placement, unsigned long Size) {
343 memcpy(Placement, Src, Size);
346 EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
347 EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
352 std::unique_ptr<llvm::orc::LLJITBuilder> JB) {
353 llvm::Error Err = llvm::Error::success();
354 auto Interp = std::unique_ptr<Interpreter>(
355 new Interpreter(std::move(CI), Err, JB ? std::move(JB) :
nullptr));
357 return std::move(Err);
361 Err = Interp->ParseAndExecute(
Runtimes);
363 return std::move(Err);
365 Interp->markUserCodeStart();
367 return std::move(Interp);
372 std::unique_ptr<CompilerInstance> DCI) {
375 std::make_unique<llvm::vfs::InMemoryFileSystem>();
377 std::make_unique<llvm::vfs::OverlayFileSystem>(
378 llvm::vfs::getRealFileSystem());
379 OverlayVFS->pushOverlay(IMVFS);
380 CI->createFileManager(OverlayVFS);
387 std::unique_ptr<Interpreter> Interp = std::move(*InterpOrErr);
389 llvm::Error Err = llvm::Error::success();
391 auto DeviceAct = Interp->TSCtx->withContextDo([&](llvm::LLVMContext *Ctx) {
392 return std::make_unique<IncrementalAction>(*DCI, *Ctx, Err, *Interp);
396 return std::move(Err);
398 Interp->DeviceAct = std::move(DeviceAct);
400 DCI->ExecuteAction(*Interp->DeviceAct);
402 Interp->DeviceCI = std::move(DCI);
404 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
405 *Interp->DeviceCI, *Interp->getCompilerInstance(),
406 Interp->DeviceAct.get(), IMVFS, Err, Interp->PTUs);
409 return std::move(Err);
411 Interp->DeviceParser = std::move(DeviceParser);
412 return std::move(Interp);
423 return std::move(Err);
426 return IncrExecutor->GetExecutionEngine();
437void Interpreter::markUserCodeStart() {
438 assert(!InitPTUSize &&
"We only do this once");
439 InitPTUSize = PTUs.size();
442size_t Interpreter::getEffectivePTUSize()
const {
443 assert(PTUs.size() >= InitPTUSize &&
"empty PTU list?");
444 return PTUs.size() - InitPTUSize;
453 if (
auto E = DeviceTU.takeError())
456 DeviceParser->RegisterPTU(*DeviceTU);
460 return PTX.takeError();
462 llvm::Error Err = DeviceParser->GenerateFatbinary();
464 return std::move(Err);
474 return TuOrErr.takeError();
478 LastPTU.
TUPart = *TuOrErr;
480 if (std::unique_ptr<llvm::Module> M = Act->GenModule())
488 if (TT == llvm::sys::getProcessTriple())
490 return llvm::orc::JITTargetMachineBuilder::detectHost();
493 return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
498 std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
499 llvm::StringRef OrcRuntimePath) {
500 const std::string &TT = EPC->getTargetTriple().getTriple();
503 return JTMB.takeError();
506 return JB.takeError();
508 (*JB)->setExecutorProcessControl(std::move(EPC));
509 (*JB)->setPlatformSetUp(
510 llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str()));
512 return std::move(*JB);
517 return llvm::make_error<llvm::StringError>(
"Operation failed. "
518 "Execution engine exists",
520 if (!Act->getCodeGen())
521 return llvm::make_error<llvm::StringError>(
"Operation failed. "
522 "No code generator available",
528 return JTMB.takeError();
531 return JB.takeError();
532 JITBuilder = std::move(*JB);
535 llvm::Error Err = llvm::Error::success();
537 auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
540 std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
543 IncrExecutor = std::move(Executor);
553 llvm::dbgs() <<
"execute-ptu "
554 << (llvm::is_contained(PTUs,
T)
555 ? std::distance(PTUs.begin(), llvm::find(PTUs,
T))
557 <<
": [TU=" <<
T.TUPart <<
", M=" <<
T.TheModule.get()
558 <<
" (" <<
T.TheModule->getName() <<
")]\n");
565 if (
auto Err = IncrExecutor->addModule(
T))
568 if (
auto Err = IncrExecutor->runCtors())
571 return llvm::Error::success();
576 auto PTU =
Parse(Code);
578 return PTU.takeError();
580 if (llvm::Error Err =
Execute(*PTU))
588 *
V = std::move(LastValue);
590 return llvm::Error::success();
596 return llvm::make_error<llvm::StringError>(
"Operation failed. "
597 "No execution engine",
599 llvm::StringRef MangledName = Act->getCodeGen()->GetMangledName(GD);
606 return llvm::make_error<llvm::StringError>(
"Operation failed. "
607 "No execution engine",
616 return llvm::make_error<llvm::StringError>(
"Operation failed. "
617 "No execution engine",
625 if (getEffectivePTUSize() == 0) {
626 return llvm::make_error<llvm::StringError>(
"Operation failed. "
627 "No input left to undo",
629 }
else if (N > getEffectivePTUSize()) {
630 return llvm::make_error<llvm::StringError>(
632 "Operation failed. Wanted to undo {0} inputs, only have {1}.", N,
633 getEffectivePTUSize()),
637 for (
unsigned I = 0; I < N; I++) {
639 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
643 IncrParser->CleanUpPTU(PTUs.back().TUPart);
646 return llvm::Error::success();
651 void *handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
653 llvm::errs() << dlerror() <<
'\n';
654 return llvm::make_error<llvm::StringError>(
"Failed to load dynamic library",
655 llvm::inconvertibleErrorCode());
660 return EE.takeError();
663 std::unique_ptr<llvm::orc::EPCDynamicLibrarySearchGenerator>>
664 DLSG = llvm::orc::EPCDynamicLibrarySearchGenerator::Load(
665 EE->getExecutionSession(), name))
668 EE->getProcessSymbolsJITDylib()->addGenerator(std::move(*DLSG));
670 return DLSG.takeError();
673 return llvm::Error::success();
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 ...
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()
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.
static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()
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.
GlobalDecl - represents a global declaration.
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)
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
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createLLJITBuilder(std::unique_ptr< llvm::orc::ExecutorProcessControl > EPC, llvm::StringRef OrcRuntimePath)
static llvm::Expected< std::unique_ptr< Interpreter > > create(std::unique_ptr< CompilerInstance > CI, std::unique_ptr< llvm::orc::LLJITBuilder > JITBuilder=nullptr)
const ASTContext & getASTContext() const
llvm::Expected< llvm::orc::LLJIT & > getExecutionEngine()
llvm::Error Execute(PartialTranslationUnit &T)
Encodes a location in the source.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, 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.
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.
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)
@ Success
Annotation was successful.
@ Parse
Parse the block; this code is always used.
const char *const Runtimes
const FunctionProtoType * T
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.