38#include "llvm/ExecutionEngine/JITSymbol.h"
39#include "llvm/ExecutionEngine/Orc/LLJIT.h"
40#include "llvm/IR/Module.h"
41#include "llvm/Support/Errc.h"
42#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/raw_ostream.h"
44#include "llvm/TargetParser/Host.h"
58 if (!Jobs.
size() || !isa<driver::Command>(*Jobs.
begin()))
59 return llvm::createStringError(llvm::errc::not_supported,
60 "Driver initialization failed. "
61 "Unable to create a driver job");
65 if (llvm::StringRef(
Cmd->getCreator().getName()) !=
"clang")
66 return llvm::createStringError(llvm::errc::not_supported,
67 "Driver initialization failed");
69 return &
Cmd->getArguments();
73CreateCI(
const llvm::opt::ArgStringList &Argv) {
79 auto PCHOps = Clang->getPCHContainerOperations();
80 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
81 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
89 Clang->getInvocation(),
llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
92 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
93 Clang->getHeaderSearchOpts().ResourceDir.empty())
94 Clang->getHeaderSearchOpts().ResourceDir =
98 Clang->createDiagnostics();
99 if (!Clang->hasDiagnostics())
100 return llvm::createStringError(llvm::errc::not_supported,
101 "Initialization failed. "
102 "Unable to create diagnostics engine");
106 return llvm::createStringError(llvm::errc::not_supported,
107 "Initialization failed. "
108 "Unable to flush diagnostics");
111 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(
"").release();
112 Clang->getPreprocessorOpts().addRemappedFile(
"<<< inputs >>>", MB);
115 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
116 if (!Clang->hasTarget())
117 return llvm::createStringError(llvm::errc::not_supported,
118 "Initialization failed. "
119 "Target is missing");
121 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
125 Clang->getCodeGenOpts().ClearASTBeforeBackend =
false;
127 Clang->getFrontendOpts().DisableFree =
false;
128 Clang->getCodeGenOpts().DisableFree =
false;
129 return std::move(Clang);
135IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
139 std::string MainExecutableName =
140 llvm::sys::fs::getMainExecutable(
nullptr,
nullptr);
142 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
149 ClangArgv.insert(ClangArgv.end(),
"-Xclang");
150 ClangArgv.insert(ClangArgv.end(),
"-fincremental-extensions");
151 ClangArgv.insert(ClangArgv.end(),
"-c");
155 ClangArgv.push_back(
"<<< inputs >>>");
166 llvm::sys::getProcessTriple(), Diags);
167 Driver.setCheckInputsExist(
false);
169 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
171 if (Compilation->
getArgs().hasArg(driver::options::OPT_v))
172 Compilation->
getJobs().
Print(llvm::errs(),
"\n",
false);
174 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
175 if (
auto Err = ErrOrCC1Args.takeError())
176 return std::move(Err);
178 return CreateCI(**ErrOrCC1Args);
183 std::vector<const char *> Argv;
184 Argv.reserve(5 + 1 + UserArgs.size());
185 Argv.push_back(
"-xc++");
186 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
188 return IncrementalCompilerBuilder::create(Argv);
192IncrementalCompilerBuilder::createCuda(
bool device) {
193 std::vector<const char *> Argv;
194 Argv.reserve(5 + 4 + UserArgs.size());
196 Argv.push_back(
"-xcuda");
198 Argv.push_back(
"--cuda-device-only");
200 Argv.push_back(
"--cuda-host-only");
202 std::string SDKPathArg =
"--cuda-path=";
203 if (!CudaSDKPath.empty()) {
204 SDKPathArg += CudaSDKPath;
205 Argv.push_back(SDKPathArg.c_str());
208 std::string ArchArg =
"--offload-arch=";
209 if (!OffloadArch.empty()) {
210 ArchArg += OffloadArch;
211 Argv.push_back(ArchArg.c_str());
214 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
216 return IncrementalCompilerBuilder::create(Argv);
221 return IncrementalCompilerBuilder::createCuda(
true);
226 return IncrementalCompilerBuilder::createCuda(
false);
229Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
231 llvm::ErrorAsOutParameter EAO(&Err);
232 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
233 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
234 IncrParser = std::make_unique<IncrementalParser>(*
this, std::move(CI),
235 *TSCtx->getContext(), Err);
240 if (llvm::Error Err = IncrExecutor->cleanUp())
241 llvm::report_fatal_error(
242 llvm::Twine(
"Failed to clean up IncrementalExecutor: ") +
251 void* operator new(__SIZE_TYPE__, void* __p) noexcept;
252 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
253 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
254 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
255 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
256 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
257 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
258 void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
259 template <class T, class = T (*)() /*disable for arrays*/>
260 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
261 for (auto Idx = 0; Idx < Size; ++Idx)
262 new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]);
264 template <class T, unsigned long N>
265 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
266 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
272 llvm::Error Err = llvm::Error::success();
274 std::unique_ptr<Interpreter>(
new Interpreter(std::move(CI), Err));
276 return std::move(Err);
280 return PTU.takeError();
282 Interp->ValuePrintingInfo.resize(3);
286 Interp->InitPTUSize = Interp->IncrParser->getPTUs().size();
287 return std::move(Interp);
292 std::unique_ptr<CompilerInstance> DCI) {
295 std::make_unique<llvm::vfs::InMemoryFileSystem>();
297 std::make_unique<llvm::vfs::OverlayFileSystem>(
298 llvm::vfs::getRealFileSystem());
299 OverlayVFS->pushOverlay(IMVFS);
300 CI->createFileManager(OverlayVFS);
303 if (
auto E = Interp.takeError())
306 llvm::Error Err = llvm::Error::success();
307 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
308 **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
309 *(*Interp)->TSCtx->getContext(), IMVFS, Err);
311 return std::move(Err);
313 (*Interp)->DeviceParser = std::move(DeviceParser);
319 return IncrParser->getCI();
324 if (
auto Err = CreateExecutor())
325 return std::move(Err);
328 return IncrExecutor->GetExecutionEngine();
339size_t Interpreter::getEffectivePTUSize()
const {
340 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
341 assert(PTUs.size() >= InitPTUSize &&
"empty PTU list?");
342 return PTUs.size() - InitPTUSize;
350 auto DevicePTU = DeviceParser->Parse(Code);
351 if (
auto E = DevicePTU.takeError())
359 return IncrParser->Parse(Code);
362llvm::Error Interpreter::CreateExecutor() {
365 llvm::Error Err = llvm::Error::success();
366 auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI);
368 IncrExecutor = std::move(Executor);
376 auto Err = CreateExecutor();
381 if (
auto Err = IncrExecutor->addModule(T))
384 if (
auto Err = IncrExecutor->runCtors())
387 return llvm::Error::success();
392 auto PTU =
Parse(Code);
394 return PTU.takeError();
396 if (llvm::Error Err =
Execute(*PTU))
404 *
V = std::move(LastValue);
406 return llvm::Error::success();
412 return llvm::make_error<llvm::StringError>(
"Operation failed. "
413 "No execution engine",
415 llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
422 return llvm::make_error<llvm::StringError>(
"Operation failed. "
423 "No execution engine",
432 return llvm::make_error<llvm::StringError>(
"Operation failed. "
433 "No execution engine",
441 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
442 if (N > getEffectivePTUSize())
443 return llvm::make_error<llvm::StringError>(
"Operation failed. "
446 for (
unsigned I = 0; I < N; I++) {
448 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
452 IncrParser->CleanUpPTU(PTUs.back());
455 return llvm::Error::success();
461 return EE.takeError();
463 auto &DL = EE->getDataLayout();
465 if (
auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
466 name, DL.getGlobalPrefix()))
467 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
469 return DLSG.takeError();
471 return llvm::Error::success();
476 assert(CXXRD &&
"Cannot compile a destructor for a nullptr");
477 if (
auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
478 return Dtor->getSecond();
481 return llvm::orc::ExecutorAddr{};
486 llvm::StringRef Name =
490 return AddrOrErr.takeError();
492 Dtors[CXXRD] = *AddrOrErr;
497 "__clang_Interpreter_SetValueNoAlloc",
498 "__clang_Interpreter_SetValueWithAlloc",
499 "__clang_Interpreter_SetValueCopyArr"};
501bool Interpreter::FindRuntimeInterface() {
502 if (llvm::all_of(ValuePrintingInfo, [](
Expr *E) {
return E !=
nullptr; }))
508 auto LookupInterface = [&](
Expr *&Interface, llvm::StringRef Name) {
520 if (!LookupInterface(ValuePrintingInfo[
NoAlloc],
523 if (!LookupInterface(ValuePrintingInfo[
WithAlloc],
526 if (!LookupInterface(ValuePrintingInfo[
CopyArray],
534class RuntimeInterfaceBuilder
535 :
public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> {
545 : Interp(In), Ctx(
C), S(SemaRef), E(VE) {
547 for (
Expr *E : FixedArgs)
551 if (
auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
552 E = EWC->getSubExpr();
568 Args.push_back(TypeArg);
574 case Interpreter::InterfaceKind::WithAlloc:
575 case Interpreter::InterfaceKind::CopyArray: {
581 assert(!AllocCall.
isInvalid() &&
"Can't create runtime interface call!");
588 Dtor->
addAttr(UsedAttr::CreateImplicit(Ctx));
594 if (Kind == Interpreter::InterfaceKind::CopyArray) {
595 const auto *ConstantArrTy =
596 cast<ConstantArrayType>(DesugaredTy.
getTypePtr());
599 Expr *Args[] = {E, AllocCall.
get(), ArrSizeExpr};
603 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
606 Expr *Args[] = {AllocCall.
get()};
615 "Can't create runtime placement new call!");
621 case Interpreter::InterfaceKind::NoAlloc: {
628 llvm_unreachable(
"Unhandled Interpreter::InterfaceKind");
632 return Interpreter::InterfaceKind::WithAlloc;
637 return Interpreter::InterfaceKind::WithAlloc;
642 return Interpreter::InterfaceKind::CopyArray;
648 return Interpreter::InterfaceKind::NoAlloc;
653 return Interpreter::InterfaceKind::NoAlloc;
658 assert(!AddrOfE.
isInvalid() &&
"Can not create unary expression");
659 Args.push_back(AddrOfE.
get());
660 return Interpreter::InterfaceKind::NoAlloc;
669 HandleIntegralOrEnumType(Ty);
674 return Interpreter::InterfaceKind::NoAlloc;
678 HandleIntegralOrEnumType(Ty);
679 return Interpreter::InterfaceKind::NoAlloc;
685 void HandleIntegralOrEnumType(
const Type *Ty) {
689 assert(!CastedExpr.
isInvalid() &&
"Cannot create cstyle cast expr");
690 Args.push_back(CastedExpr.
get());
693 void HandlePtrType(
const Type *Ty) {
697 assert(!CastedExpr.
isInvalid() &&
"Can not create cstyle cast expression");
698 Args.push_back(CastedExpr.
get());
721 if (!FindRuntimeInterface())
722 llvm_unreachable(
"We can't find the runtime iterface for pretty print!");
731 RuntimeInterfaceBuilder Builder(*
this, Ctx, S, E, {ThisInterp, OutValue});
768 QT = ET->getDecl()->getIntegerType();
772 llvm_unreachable(
"unknown type kind!");
773#define X(type, name) \
774 case BuiltinType::name: \
784 unsigned long long Val) {
811 VRef.setLongDouble(Val);
Defines the clang::ASTContext interface.
#define REPL_EXTERNAL_VISIBILITY
#define REPL_BUILTIN_TYPES
static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data)
const char *const Runtimes
REPL_EXTERNAL_VISIBILITY void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, void *Val)
REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
static constexpr llvm::StringRef MagicRuntimeInterface[]
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType UnsignedLongLongTy
const TargetInfo & getTargetInfo() const
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
This class is used for builtin types like 'int'.
Represents a C++ destructor within a class.
Represents a C++ struct/union/class.
bool hasIrrelevantDestructor() const
Determine whether this class has a destructor which has no semantic effect.
Represents a C++ nested-name-specifier or a global scope specifier.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
ASTContext & getASTContext() const
ASTConsumer & getASTConsumer() const
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.
Represents the canonical version of C arrays with a specified constant size.
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.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
This represents one expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Represents a prototype with parameter type info, e.g.
GlobalDecl - represents a global declaration.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaHost()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCpp()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaDevice()
Provides top-level interfaces for incremental compilation and execution.
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
llvm::Error Execute(PartialTranslationUnit &T)
llvm::Expected< llvm::orc::LLJIT & > getExecutionEngine()
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const
static llvm::Expected< std::unique_ptr< Interpreter > > createWithCUDA(std::unique_ptr< CompilerInstance > CI, std::unique_ptr< CompilerInstance > DCI)
const CompilerInstance * getCompilerInstance() const
llvm::Expected< llvm::orc::ExecutorAddr > CompileDtorCall(CXXRecordDecl *CXXRD)
llvm::Error LoadDynamicLibrary(const char *name)
Link a dynamic library.
const llvm::SmallVectorImpl< Expr * > & getValuePrintingInfo() const
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V=nullptr)
Expr * SynthesizeExpr(Expr *E)
static llvm::Expected< std::unique_ptr< Interpreter > > create(std::unique_ptr< CompilerInstance > CI)
llvm::Expected< PartialTranslationUnit & > Parse(llvm::StringRef Code)
llvm::Error Undo(unsigned N=1)
Undo N previous incremental inputs.
const ASTContext & getASTContext() const
Represents the results of name lookup.
A pointer to member type per C++ 8.3.3 - Pointers to members.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
void * getAsOpaquePtr() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Base for LValueReferenceType and RValueReferenceType.
Sema - This implements semantic analysis and AST building for C.
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
ASTContext & getASTContext() const
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, QualType AllocType, TypeSourceInfo *AllocTypeInfo, std::optional< Expr * > ArraySize, SourceRange DirectInitRange, Expr *Initializer)
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
Exposes information about the current target.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
void FlushDiagnostics(DiagnosticsEngine &Diags) const
FlushDiagnostics - Flush the buffered diagnostics to an given diagnostic engine.
A container of type source information.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs<specific type>.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
bool isRecordType() const
Command - An executable path/name and argument vector to execute.
Compilation - A set of tasks to perform for a single driver invocation.
const llvm::opt::DerivedArgList & getArgs() const
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
JobList - A sequence of jobs to perform.
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo=nullptr) const
Defines the clang::TargetInfo interface.
@ Ignored
Do not present this diagnostic, ignore it.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
IntegerLiteral * IntegerLiteralExpr(ASTContext &C, uint64_t Val)
@ Dtor_Base
Base object dtor.
Expr * CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
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.