1fe6060f1SDimitry Andric //===------ Interpreter.cpp - Incremental Compilation and Execution -------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This file implements the component which performs incremental code 10fe6060f1SDimitry Andric // compilation and execution. 11fe6060f1SDimitry Andric // 12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 13fe6060f1SDimitry Andric 1406c3fb27SDimitry Andric #include "DeviceOffload.h" 15fe6060f1SDimitry Andric #include "IncrementalExecutor.h" 16fe6060f1SDimitry Andric #include "IncrementalParser.h" 1706c3fb27SDimitry Andric #include "InterpreterUtils.h" 180fca6ea1SDimitry Andric #ifdef __EMSCRIPTEN__ 190fca6ea1SDimitry Andric #include "Wasm.h" 200fca6ea1SDimitry Andric #endif // __EMSCRIPTEN__ 215f757f3fSDimitry Andric 22fe6060f1SDimitry Andric #include "clang/AST/ASTContext.h" 2306c3fb27SDimitry Andric #include "clang/AST/Mangle.h" 2406c3fb27SDimitry Andric #include "clang/AST/TypeVisitor.h" 2506c3fb27SDimitry Andric #include "clang/Basic/DiagnosticSema.h" 26fe6060f1SDimitry Andric #include "clang/Basic/TargetInfo.h" 2706c3fb27SDimitry Andric #include "clang/CodeGen/CodeGenAction.h" 28fe6060f1SDimitry Andric #include "clang/CodeGen/ModuleBuilder.h" 29fe6060f1SDimitry Andric #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 30fe6060f1SDimitry Andric #include "clang/Driver/Compilation.h" 31fe6060f1SDimitry Andric #include "clang/Driver/Driver.h" 32fe6060f1SDimitry Andric #include "clang/Driver/Job.h" 33fe6060f1SDimitry Andric #include "clang/Driver/Options.h" 34fe6060f1SDimitry Andric #include "clang/Driver/Tool.h" 35fe6060f1SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 36fe6060f1SDimitry Andric #include "clang/Frontend/TextDiagnosticBuffer.h" 375f757f3fSDimitry Andric #include "clang/Interpreter/Interpreter.h" 3806c3fb27SDimitry Andric #include "clang/Interpreter/Value.h" 39fe6060f1SDimitry Andric #include "clang/Lex/PreprocessorOptions.h" 4006c3fb27SDimitry Andric #include "clang/Sema/Lookup.h" 4106c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h" 4206c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/LLJIT.h" 43fe6060f1SDimitry Andric #include "llvm/IR/Module.h" 44349cc55cSDimitry Andric #include "llvm/Support/Errc.h" 4506c3fb27SDimitry Andric #include "llvm/Support/ErrorHandling.h" 4606c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 4706c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 480fca6ea1SDimitry Andric 490fca6ea1SDimitry Andric #include <cstdarg> 500fca6ea1SDimitry Andric 51fe6060f1SDimitry Andric using namespace clang; 52fe6060f1SDimitry Andric 53fe6060f1SDimitry Andric // FIXME: Figure out how to unify with namespace init_convenience from 54349cc55cSDimitry Andric // tools/clang-import-test/clang-import-test.cpp 55fe6060f1SDimitry Andric namespace { 56fe6060f1SDimitry Andric /// Retrieves the clang CC1 specific flags out of the compilation's jobs. 57fe6060f1SDimitry Andric /// \returns NULL on error. 58fe6060f1SDimitry Andric static llvm::Expected<const llvm::opt::ArgStringList *> 59fe6060f1SDimitry Andric GetCC1Arguments(DiagnosticsEngine *Diagnostics, 60fe6060f1SDimitry Andric driver::Compilation *Compilation) { 61fe6060f1SDimitry Andric // We expect to get back exactly one Command job, if we didn't something 62fe6060f1SDimitry Andric // failed. Extract that job from the Compilation. 63fe6060f1SDimitry Andric const driver::JobList &Jobs = Compilation->getJobs(); 64fe6060f1SDimitry Andric if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin())) 65349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 66fe6060f1SDimitry Andric "Driver initialization failed. " 67fe6060f1SDimitry Andric "Unable to create a driver job"); 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric // The one job we find should be to invoke clang again. 70fe6060f1SDimitry Andric const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin())); 71fe6060f1SDimitry Andric if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") 72349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 73fe6060f1SDimitry Andric "Driver initialization failed"); 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric return &Cmd->getArguments(); 76fe6060f1SDimitry Andric } 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric static llvm::Expected<std::unique_ptr<CompilerInstance>> 79fe6060f1SDimitry Andric CreateCI(const llvm::opt::ArgStringList &Argv) { 80fe6060f1SDimitry Andric std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); 81fe6060f1SDimitry Andric IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 82fe6060f1SDimitry Andric 83fe6060f1SDimitry Andric // Register the support for object-file-wrapped Clang modules. 84fe6060f1SDimitry Andric // FIXME: Clang should register these container operations automatically. 85fe6060f1SDimitry Andric auto PCHOps = Clang->getPCHContainerOperations(); 86fe6060f1SDimitry Andric PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 87fe6060f1SDimitry Andric PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric // Buffer diagnostics from argument parsing so that we can output them using 90fe6060f1SDimitry Andric // a well formed diagnostic object. 91fe6060f1SDimitry Andric IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 92fe6060f1SDimitry Andric TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 93fe6060f1SDimitry Andric DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 94fe6060f1SDimitry Andric bool Success = CompilerInvocation::CreateFromArgs( 95bdd1243dSDimitry Andric Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags); 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric // Infer the builtin include path if unspecified. 98fe6060f1SDimitry Andric if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && 99fe6060f1SDimitry Andric Clang->getHeaderSearchOpts().ResourceDir.empty()) 100fe6060f1SDimitry Andric Clang->getHeaderSearchOpts().ResourceDir = 101fe6060f1SDimitry Andric CompilerInvocation::GetResourcesPath(Argv[0], nullptr); 102fe6060f1SDimitry Andric 103fe6060f1SDimitry Andric // Create the actual diagnostics engine. 104fe6060f1SDimitry Andric Clang->createDiagnostics(); 105fe6060f1SDimitry Andric if (!Clang->hasDiagnostics()) 106349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 107fe6060f1SDimitry Andric "Initialization failed. " 108fe6060f1SDimitry Andric "Unable to create diagnostics engine"); 109fe6060f1SDimitry Andric 110fe6060f1SDimitry Andric DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); 111fe6060f1SDimitry Andric if (!Success) 112349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 113fe6060f1SDimitry Andric "Initialization failed. " 114fe6060f1SDimitry Andric "Unable to flush diagnostics"); 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric // FIXME: Merge with CompilerInstance::ExecuteAction. 117fe6060f1SDimitry Andric llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release(); 118fe6060f1SDimitry Andric Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB); 119fe6060f1SDimitry Andric 120fe6060f1SDimitry Andric Clang->setTarget(TargetInfo::CreateTargetInfo( 121fe6060f1SDimitry Andric Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); 122fe6060f1SDimitry Andric if (!Clang->hasTarget()) 123349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 124fe6060f1SDimitry Andric "Initialization failed. " 125fe6060f1SDimitry Andric "Target is missing"); 126fe6060f1SDimitry Andric 127fe6060f1SDimitry Andric Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts()); 128fe6060f1SDimitry Andric 129349cc55cSDimitry Andric // Don't clear the AST before backend codegen since we do codegen multiple 130349cc55cSDimitry Andric // times, reusing the same AST. 131349cc55cSDimitry Andric Clang->getCodeGenOpts().ClearASTBeforeBackend = false; 132349cc55cSDimitry Andric 13381ad6265SDimitry Andric Clang->getFrontendOpts().DisableFree = false; 13481ad6265SDimitry Andric Clang->getCodeGenOpts().DisableFree = false; 135fe6060f1SDimitry Andric return std::move(Clang); 136fe6060f1SDimitry Andric } 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric } // anonymous namespace 139fe6060f1SDimitry Andric 140fe6060f1SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 1410fca6ea1SDimitry Andric IncrementalCompilerBuilder::create(std::string TT, 1420fca6ea1SDimitry Andric std::vector<const char *> &ClangArgv) { 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric // If we don't know ClangArgv0 or the address of main() at this point, try 145fe6060f1SDimitry Andric // to guess it anyway (it's possible on some platforms). 146fe6060f1SDimitry Andric std::string MainExecutableName = 147fe6060f1SDimitry Andric llvm::sys::fs::getMainExecutable(nullptr, nullptr); 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str()); 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric // Prepending -c to force the driver to do something if no action was 152fe6060f1SDimitry Andric // specified. By prepending we allow users to override the default 153fe6060f1SDimitry Andric // action and use other actions in incremental mode. 154fe6060f1SDimitry Andric // FIXME: Print proper driver diagnostics if the driver flags are wrong. 155fe6060f1SDimitry Andric // We do C++ by default; append right after argv[0] if no "-x" given 156bdd1243dSDimitry Andric ClangArgv.insert(ClangArgv.end(), "-Xclang"); 157bdd1243dSDimitry Andric ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions"); 158bdd1243dSDimitry Andric ClangArgv.insert(ClangArgv.end(), "-c"); 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric // Put a dummy C++ file on to ensure there's at least one compile job for the 161fe6060f1SDimitry Andric // driver to construct. 162fe6060f1SDimitry Andric ClangArgv.push_back("<<< inputs >>>"); 163fe6060f1SDimitry Andric 164fe6060f1SDimitry Andric // Buffer diagnostics from argument parsing so that we can output them using a 165fe6060f1SDimitry Andric // well formed diagnostic object. 166fe6060f1SDimitry Andric IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 167349cc55cSDimitry Andric IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = 168349cc55cSDimitry Andric CreateAndPopulateDiagOpts(ClangArgv); 169fe6060f1SDimitry Andric TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 170fe6060f1SDimitry Andric DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 171fe6060f1SDimitry Andric 1720fca6ea1SDimitry Andric driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags); 173fe6060f1SDimitry Andric Driver.setCheckInputsExist(false); // the input comes from mem buffers 174bdd1243dSDimitry Andric llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv); 175fe6060f1SDimitry Andric std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF)); 176fe6060f1SDimitry Andric 177fe6060f1SDimitry Andric if (Compilation->getArgs().hasArg(driver::options::OPT_v)) 178fe6060f1SDimitry Andric Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false); 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get()); 181fe6060f1SDimitry Andric if (auto Err = ErrOrCC1Args.takeError()) 182fe6060f1SDimitry Andric return std::move(Err); 183fe6060f1SDimitry Andric 184fe6060f1SDimitry Andric return CreateCI(**ErrOrCC1Args); 185fe6060f1SDimitry Andric } 186fe6060f1SDimitry Andric 18706c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 18806c3fb27SDimitry Andric IncrementalCompilerBuilder::CreateCpp() { 18906c3fb27SDimitry Andric std::vector<const char *> Argv; 19006c3fb27SDimitry Andric Argv.reserve(5 + 1 + UserArgs.size()); 19106c3fb27SDimitry Andric Argv.push_back("-xc++"); 1920fca6ea1SDimitry Andric #ifdef __EMSCRIPTEN__ 1930fca6ea1SDimitry Andric Argv.push_back("-target"); 1940fca6ea1SDimitry Andric Argv.push_back("wasm32-unknown-emscripten"); 1950fca6ea1SDimitry Andric Argv.push_back("-shared"); 196*71ac745dSDimitry Andric Argv.push_back("-fvisibility=default"); 1970fca6ea1SDimitry Andric #endif 19806c3fb27SDimitry Andric Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 19906c3fb27SDimitry Andric 2000fca6ea1SDimitry Andric std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); 2010fca6ea1SDimitry Andric return IncrementalCompilerBuilder::create(TT, Argv); 20206c3fb27SDimitry Andric } 20306c3fb27SDimitry Andric 20406c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 20506c3fb27SDimitry Andric IncrementalCompilerBuilder::createCuda(bool device) { 20606c3fb27SDimitry Andric std::vector<const char *> Argv; 20706c3fb27SDimitry Andric Argv.reserve(5 + 4 + UserArgs.size()); 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric Argv.push_back("-xcuda"); 21006c3fb27SDimitry Andric if (device) 21106c3fb27SDimitry Andric Argv.push_back("--cuda-device-only"); 21206c3fb27SDimitry Andric else 21306c3fb27SDimitry Andric Argv.push_back("--cuda-host-only"); 21406c3fb27SDimitry Andric 21506c3fb27SDimitry Andric std::string SDKPathArg = "--cuda-path="; 21606c3fb27SDimitry Andric if (!CudaSDKPath.empty()) { 21706c3fb27SDimitry Andric SDKPathArg += CudaSDKPath; 21806c3fb27SDimitry Andric Argv.push_back(SDKPathArg.c_str()); 21906c3fb27SDimitry Andric } 22006c3fb27SDimitry Andric 22106c3fb27SDimitry Andric std::string ArchArg = "--offload-arch="; 22206c3fb27SDimitry Andric if (!OffloadArch.empty()) { 22306c3fb27SDimitry Andric ArchArg += OffloadArch; 22406c3fb27SDimitry Andric Argv.push_back(ArchArg.c_str()); 22506c3fb27SDimitry Andric } 22606c3fb27SDimitry Andric 22706c3fb27SDimitry Andric Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 22806c3fb27SDimitry Andric 2290fca6ea1SDimitry Andric std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); 2300fca6ea1SDimitry Andric return IncrementalCompilerBuilder::create(TT, Argv); 23106c3fb27SDimitry Andric } 23206c3fb27SDimitry Andric 23306c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 23406c3fb27SDimitry Andric IncrementalCompilerBuilder::CreateCudaDevice() { 23506c3fb27SDimitry Andric return IncrementalCompilerBuilder::createCuda(true); 23606c3fb27SDimitry Andric } 23706c3fb27SDimitry Andric 23806c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 23906c3fb27SDimitry Andric IncrementalCompilerBuilder::CreateCudaHost() { 24006c3fb27SDimitry Andric return IncrementalCompilerBuilder::createCuda(false); 24106c3fb27SDimitry Andric } 24206c3fb27SDimitry Andric 243fe6060f1SDimitry Andric Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI, 2440fca6ea1SDimitry Andric llvm::Error &ErrOut, 2450fca6ea1SDimitry Andric std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder) 2460fca6ea1SDimitry Andric : JITBuilder(std::move(JITBuilder)) { 2470fca6ea1SDimitry Andric llvm::ErrorAsOutParameter EAO(&ErrOut); 248fe6060f1SDimitry Andric auto LLVMCtx = std::make_unique<llvm::LLVMContext>(); 249fe6060f1SDimitry Andric TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx)); 2500fca6ea1SDimitry Andric IncrParser = std::make_unique<IncrementalParser>( 2510fca6ea1SDimitry Andric *this, std::move(CI), *TSCtx->getContext(), ErrOut); 2520fca6ea1SDimitry Andric if (ErrOut) 2530fca6ea1SDimitry Andric return; 2540fca6ea1SDimitry Andric 2550fca6ea1SDimitry Andric // Not all frontends support code-generation, e.g. ast-dump actions don't 2560fca6ea1SDimitry Andric if (IncrParser->getCodeGen()) { 2570fca6ea1SDimitry Andric if (llvm::Error Err = CreateExecutor()) { 2580fca6ea1SDimitry Andric ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); 2590fca6ea1SDimitry Andric return; 2600fca6ea1SDimitry Andric } 2610fca6ea1SDimitry Andric 2620fca6ea1SDimitry Andric // Process the PTUs that came from initialization. For example -include will 2630fca6ea1SDimitry Andric // give us a header that's processed at initialization of the preprocessor. 2640fca6ea1SDimitry Andric for (PartialTranslationUnit &PTU : IncrParser->getPTUs()) 2650fca6ea1SDimitry Andric if (llvm::Error Err = Execute(PTU)) { 2660fca6ea1SDimitry Andric ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); 2670fca6ea1SDimitry Andric return; 2680fca6ea1SDimitry Andric } 2690fca6ea1SDimitry Andric } 270fe6060f1SDimitry Andric } 271fe6060f1SDimitry Andric 272bdd1243dSDimitry Andric Interpreter::~Interpreter() { 273bdd1243dSDimitry Andric if (IncrExecutor) { 274bdd1243dSDimitry Andric if (llvm::Error Err = IncrExecutor->cleanUp()) 275bdd1243dSDimitry Andric llvm::report_fatal_error( 276bdd1243dSDimitry Andric llvm::Twine("Failed to clean up IncrementalExecutor: ") + 277bdd1243dSDimitry Andric toString(std::move(Err))); 278bdd1243dSDimitry Andric } 279bdd1243dSDimitry Andric } 280fe6060f1SDimitry Andric 28106c3fb27SDimitry Andric // These better to put in a runtime header but we can't. This is because we 28206c3fb27SDimitry Andric // can't find the precise resource directory in unittests so we have to hard 28306c3fb27SDimitry Andric // code them. 28406c3fb27SDimitry Andric const char *const Runtimes = R"( 2850fca6ea1SDimitry Andric #define __CLANG_REPL__ 1 2867a6dacacSDimitry Andric #ifdef __cplusplus 2870fca6ea1SDimitry Andric #define EXTERN_C extern "C" 28806c3fb27SDimitry Andric void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); 2897a6dacacSDimitry Andric struct __clang_Interpreter_NewTag{} __ci_newtag; 2907a6dacacSDimitry Andric void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; 29106c3fb27SDimitry Andric template <class T, class = T (*)() /*disable for arrays*/> 29206c3fb27SDimitry Andric void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { 29306c3fb27SDimitry Andric for (auto Idx = 0; Idx < Size; ++Idx) 2947a6dacacSDimitry Andric new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]); 29506c3fb27SDimitry Andric } 29606c3fb27SDimitry Andric template <class T, unsigned long N> 29706c3fb27SDimitry Andric void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { 29806c3fb27SDimitry Andric __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); 29906c3fb27SDimitry Andric } 3000fca6ea1SDimitry Andric #else 3010fca6ea1SDimitry Andric #define EXTERN_C extern 3027a6dacacSDimitry Andric #endif // __cplusplus 3030fca6ea1SDimitry Andric 3040fca6ea1SDimitry Andric EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); 30506c3fb27SDimitry Andric )"; 30606c3fb27SDimitry Andric 307fe6060f1SDimitry Andric llvm::Expected<std::unique_ptr<Interpreter>> 308fe6060f1SDimitry Andric Interpreter::create(std::unique_ptr<CompilerInstance> CI) { 309fe6060f1SDimitry Andric llvm::Error Err = llvm::Error::success(); 310fe6060f1SDimitry Andric auto Interp = 311fe6060f1SDimitry Andric std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err)); 312fe6060f1SDimitry Andric if (Err) 313fe6060f1SDimitry Andric return std::move(Err); 3145f757f3fSDimitry Andric 3150fca6ea1SDimitry Andric // Add runtime code and set a marker to hide it from user code. Undo will not 3160fca6ea1SDimitry Andric // go through that. 31706c3fb27SDimitry Andric auto PTU = Interp->Parse(Runtimes); 31806c3fb27SDimitry Andric if (!PTU) 31906c3fb27SDimitry Andric return PTU.takeError(); 3200fca6ea1SDimitry Andric Interp->markUserCodeStart(); 32106c3fb27SDimitry Andric 3227a6dacacSDimitry Andric Interp->ValuePrintingInfo.resize(4); 323fe6060f1SDimitry Andric return std::move(Interp); 324fe6060f1SDimitry Andric } 325fe6060f1SDimitry Andric 32606c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<Interpreter>> 32706c3fb27SDimitry Andric Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, 32806c3fb27SDimitry Andric std::unique_ptr<CompilerInstance> DCI) { 32906c3fb27SDimitry Andric // avoid writing fat binary to disk using an in-memory virtual file system 33006c3fb27SDimitry Andric llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS = 33106c3fb27SDimitry Andric std::make_unique<llvm::vfs::InMemoryFileSystem>(); 33206c3fb27SDimitry Andric llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS = 33306c3fb27SDimitry Andric std::make_unique<llvm::vfs::OverlayFileSystem>( 33406c3fb27SDimitry Andric llvm::vfs::getRealFileSystem()); 33506c3fb27SDimitry Andric OverlayVFS->pushOverlay(IMVFS); 33606c3fb27SDimitry Andric CI->createFileManager(OverlayVFS); 33706c3fb27SDimitry Andric 33806c3fb27SDimitry Andric auto Interp = Interpreter::create(std::move(CI)); 33906c3fb27SDimitry Andric if (auto E = Interp.takeError()) 34006c3fb27SDimitry Andric return std::move(E); 34106c3fb27SDimitry Andric 34206c3fb27SDimitry Andric llvm::Error Err = llvm::Error::success(); 34306c3fb27SDimitry Andric auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( 34406c3fb27SDimitry Andric **Interp, std::move(DCI), *(*Interp)->IncrParser.get(), 34506c3fb27SDimitry Andric *(*Interp)->TSCtx->getContext(), IMVFS, Err); 34606c3fb27SDimitry Andric if (Err) 34706c3fb27SDimitry Andric return std::move(Err); 34806c3fb27SDimitry Andric 34906c3fb27SDimitry Andric (*Interp)->DeviceParser = std::move(DeviceParser); 35006c3fb27SDimitry Andric 35106c3fb27SDimitry Andric return Interp; 35206c3fb27SDimitry Andric } 35306c3fb27SDimitry Andric 354fe6060f1SDimitry Andric const CompilerInstance *Interpreter::getCompilerInstance() const { 355fe6060f1SDimitry Andric return IncrParser->getCI(); 356fe6060f1SDimitry Andric } 357fe6060f1SDimitry Andric 358cb14a3feSDimitry Andric CompilerInstance *Interpreter::getCompilerInstance() { 359cb14a3feSDimitry Andric return IncrParser->getCI(); 360cb14a3feSDimitry Andric } 361cb14a3feSDimitry Andric 36206c3fb27SDimitry Andric llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { 36306c3fb27SDimitry Andric if (!IncrExecutor) { 36406c3fb27SDimitry Andric if (auto Err = CreateExecutor()) 36506c3fb27SDimitry Andric return std::move(Err); 36606c3fb27SDimitry Andric } 36706c3fb27SDimitry Andric 36806c3fb27SDimitry Andric return IncrExecutor->GetExecutionEngine(); 36906c3fb27SDimitry Andric } 37006c3fb27SDimitry Andric 37106c3fb27SDimitry Andric ASTContext &Interpreter::getASTContext() { 37206c3fb27SDimitry Andric return getCompilerInstance()->getASTContext(); 37306c3fb27SDimitry Andric } 37406c3fb27SDimitry Andric 37506c3fb27SDimitry Andric const ASTContext &Interpreter::getASTContext() const { 37606c3fb27SDimitry Andric return getCompilerInstance()->getASTContext(); 37706c3fb27SDimitry Andric } 37806c3fb27SDimitry Andric 3790fca6ea1SDimitry Andric void Interpreter::markUserCodeStart() { 3800fca6ea1SDimitry Andric assert(!InitPTUSize && "We only do this once"); 3810fca6ea1SDimitry Andric InitPTUSize = IncrParser->getPTUs().size(); 3820fca6ea1SDimitry Andric } 3830fca6ea1SDimitry Andric 38406c3fb27SDimitry Andric size_t Interpreter::getEffectivePTUSize() const { 38506c3fb27SDimitry Andric std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); 38606c3fb27SDimitry Andric assert(PTUs.size() >= InitPTUSize && "empty PTU list?"); 38706c3fb27SDimitry Andric return PTUs.size() - InitPTUSize; 3883a9a9c0cSDimitry Andric } 3893a9a9c0cSDimitry Andric 390fe6060f1SDimitry Andric llvm::Expected<PartialTranslationUnit &> 391fe6060f1SDimitry Andric Interpreter::Parse(llvm::StringRef Code) { 39206c3fb27SDimitry Andric // If we have a device parser, parse it first. 39306c3fb27SDimitry Andric // The generated code will be included in the host compilation 39406c3fb27SDimitry Andric if (DeviceParser) { 39506c3fb27SDimitry Andric auto DevicePTU = DeviceParser->Parse(Code); 39606c3fb27SDimitry Andric if (auto E = DevicePTU.takeError()) 39706c3fb27SDimitry Andric return std::move(E); 39806c3fb27SDimitry Andric } 39906c3fb27SDimitry Andric 40006c3fb27SDimitry Andric // Tell the interpreter sliently ignore unused expressions since value 40106c3fb27SDimitry Andric // printing could cause it. 40206c3fb27SDimitry Andric getCompilerInstance()->getDiagnostics().setSeverity( 40306c3fb27SDimitry Andric clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation()); 404fe6060f1SDimitry Andric return IncrParser->Parse(Code); 405fe6060f1SDimitry Andric } 406fe6060f1SDimitry Andric 4070fca6ea1SDimitry Andric static llvm::Expected<llvm::orc::JITTargetMachineBuilder> 4080fca6ea1SDimitry Andric createJITTargetMachineBuilder(const std::string &TT) { 4090fca6ea1SDimitry Andric if (TT == llvm::sys::getProcessTriple()) 4100fca6ea1SDimitry Andric // This fails immediately if the target backend is not registered 4110fca6ea1SDimitry Andric return llvm::orc::JITTargetMachineBuilder::detectHost(); 4120fca6ea1SDimitry Andric 4130fca6ea1SDimitry Andric // If the target backend is not registered, LLJITBuilder::create() will fail 4140fca6ea1SDimitry Andric return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); 4150fca6ea1SDimitry Andric } 4160fca6ea1SDimitry Andric 41706c3fb27SDimitry Andric llvm::Error Interpreter::CreateExecutor() { 4180fca6ea1SDimitry Andric if (IncrExecutor) 4190fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 4200fca6ea1SDimitry Andric "Execution engine exists", 4210fca6ea1SDimitry Andric std::error_code()); 4220fca6ea1SDimitry Andric if (!IncrParser->getCodeGen()) 4230fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 4240fca6ea1SDimitry Andric "No code generator available", 4250fca6ea1SDimitry Andric std::error_code()); 4260fca6ea1SDimitry Andric if (!JITBuilder) { 4270fca6ea1SDimitry Andric const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; 4280fca6ea1SDimitry Andric auto JTMB = createJITTargetMachineBuilder(TT); 4290fca6ea1SDimitry Andric if (!JTMB) 4300fca6ea1SDimitry Andric return JTMB.takeError(); 4310fca6ea1SDimitry Andric auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); 4320fca6ea1SDimitry Andric if (!JB) 4330fca6ea1SDimitry Andric return JB.takeError(); 4340fca6ea1SDimitry Andric JITBuilder = std::move(*JB); 4350fca6ea1SDimitry Andric } 4360fca6ea1SDimitry Andric 43706c3fb27SDimitry Andric llvm::Error Err = llvm::Error::success(); 4380fca6ea1SDimitry Andric #ifdef __EMSCRIPTEN__ 4390fca6ea1SDimitry Andric auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx); 4400fca6ea1SDimitry Andric #else 4410fca6ea1SDimitry Andric auto Executor = 4420fca6ea1SDimitry Andric std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err); 4430fca6ea1SDimitry Andric #endif 44406c3fb27SDimitry Andric if (!Err) 44506c3fb27SDimitry Andric IncrExecutor = std::move(Executor); 44606c3fb27SDimitry Andric 44706c3fb27SDimitry Andric return Err; 44806c3fb27SDimitry Andric } 44906c3fb27SDimitry Andric 4500fca6ea1SDimitry Andric void Interpreter::ResetExecutor() { IncrExecutor.reset(); } 4510fca6ea1SDimitry Andric 452fe6060f1SDimitry Andric llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { 453fe6060f1SDimitry Andric assert(T.TheModule); 454fe6060f1SDimitry Andric if (!IncrExecutor) { 45506c3fb27SDimitry Andric auto Err = CreateExecutor(); 456fe6060f1SDimitry Andric if (Err) 457fe6060f1SDimitry Andric return Err; 458fe6060f1SDimitry Andric } 459fe6060f1SDimitry Andric // FIXME: Add a callback to retain the llvm::Module once the JIT is done. 46081ad6265SDimitry Andric if (auto Err = IncrExecutor->addModule(T)) 461fe6060f1SDimitry Andric return Err; 462fe6060f1SDimitry Andric 463fe6060f1SDimitry Andric if (auto Err = IncrExecutor->runCtors()) 464fe6060f1SDimitry Andric return Err; 465fe6060f1SDimitry Andric 466fe6060f1SDimitry Andric return llvm::Error::success(); 467fe6060f1SDimitry Andric } 468349cc55cSDimitry Andric 46906c3fb27SDimitry Andric llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { 47006c3fb27SDimitry Andric 47106c3fb27SDimitry Andric auto PTU = Parse(Code); 47206c3fb27SDimitry Andric if (!PTU) 47306c3fb27SDimitry Andric return PTU.takeError(); 47406c3fb27SDimitry Andric if (PTU->TheModule) 47506c3fb27SDimitry Andric if (llvm::Error Err = Execute(*PTU)) 47606c3fb27SDimitry Andric return Err; 47706c3fb27SDimitry Andric 47806c3fb27SDimitry Andric if (LastValue.isValid()) { 47906c3fb27SDimitry Andric if (!V) { 48006c3fb27SDimitry Andric LastValue.dump(); 48106c3fb27SDimitry Andric LastValue.clear(); 48206c3fb27SDimitry Andric } else 48306c3fb27SDimitry Andric *V = std::move(LastValue); 48406c3fb27SDimitry Andric } 48506c3fb27SDimitry Andric return llvm::Error::success(); 48606c3fb27SDimitry Andric } 48706c3fb27SDimitry Andric 48806c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 489349cc55cSDimitry Andric Interpreter::getSymbolAddress(GlobalDecl GD) const { 490349cc55cSDimitry Andric if (!IncrExecutor) 491349cc55cSDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 492349cc55cSDimitry Andric "No execution engine", 493349cc55cSDimitry Andric std::error_code()); 494349cc55cSDimitry Andric llvm::StringRef MangledName = IncrParser->GetMangledName(GD); 495349cc55cSDimitry Andric return getSymbolAddress(MangledName); 496349cc55cSDimitry Andric } 497349cc55cSDimitry Andric 49806c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 499349cc55cSDimitry Andric Interpreter::getSymbolAddress(llvm::StringRef IRName) const { 500349cc55cSDimitry Andric if (!IncrExecutor) 501349cc55cSDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 502349cc55cSDimitry Andric "No execution engine", 503349cc55cSDimitry Andric std::error_code()); 504349cc55cSDimitry Andric 505349cc55cSDimitry Andric return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName); 506349cc55cSDimitry Andric } 507349cc55cSDimitry Andric 50806c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 509349cc55cSDimitry Andric Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const { 510349cc55cSDimitry Andric if (!IncrExecutor) 511349cc55cSDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 512349cc55cSDimitry Andric "No execution engine", 513349cc55cSDimitry Andric std::error_code()); 514349cc55cSDimitry Andric 515349cc55cSDimitry Andric return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName); 516349cc55cSDimitry Andric } 51781ad6265SDimitry Andric 51881ad6265SDimitry Andric llvm::Error Interpreter::Undo(unsigned N) { 51981ad6265SDimitry Andric 52081ad6265SDimitry Andric std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); 52106c3fb27SDimitry Andric if (N > getEffectivePTUSize()) 52281ad6265SDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 52381ad6265SDimitry Andric "Too many undos", 52481ad6265SDimitry Andric std::error_code()); 52581ad6265SDimitry Andric for (unsigned I = 0; I < N; I++) { 52681ad6265SDimitry Andric if (IncrExecutor) { 52781ad6265SDimitry Andric if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back())) 52881ad6265SDimitry Andric return Err; 52981ad6265SDimitry Andric } 53081ad6265SDimitry Andric 53181ad6265SDimitry Andric IncrParser->CleanUpPTU(PTUs.back()); 53281ad6265SDimitry Andric PTUs.pop_back(); 53381ad6265SDimitry Andric } 53481ad6265SDimitry Andric return llvm::Error::success(); 53581ad6265SDimitry Andric } 53606c3fb27SDimitry Andric 53706c3fb27SDimitry Andric llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { 53806c3fb27SDimitry Andric auto EE = getExecutionEngine(); 53906c3fb27SDimitry Andric if (!EE) 54006c3fb27SDimitry Andric return EE.takeError(); 54106c3fb27SDimitry Andric 54206c3fb27SDimitry Andric auto &DL = EE->getDataLayout(); 54306c3fb27SDimitry Andric 54406c3fb27SDimitry Andric if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load( 54506c3fb27SDimitry Andric name, DL.getGlobalPrefix())) 54606c3fb27SDimitry Andric EE->getMainJITDylib().addGenerator(std::move(*DLSG)); 54706c3fb27SDimitry Andric else 54806c3fb27SDimitry Andric return DLSG.takeError(); 54906c3fb27SDimitry Andric 55006c3fb27SDimitry Andric return llvm::Error::success(); 55106c3fb27SDimitry Andric } 55206c3fb27SDimitry Andric 55306c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 55406c3fb27SDimitry Andric Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) { 55506c3fb27SDimitry Andric assert(CXXRD && "Cannot compile a destructor for a nullptr"); 55606c3fb27SDimitry Andric if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end()) 55706c3fb27SDimitry Andric return Dtor->getSecond(); 55806c3fb27SDimitry Andric 55906c3fb27SDimitry Andric if (CXXRD->hasIrrelevantDestructor()) 56006c3fb27SDimitry Andric return llvm::orc::ExecutorAddr{}; 56106c3fb27SDimitry Andric 56206c3fb27SDimitry Andric CXXDestructorDecl *DtorRD = 56306c3fb27SDimitry Andric getCompilerInstance()->getSema().LookupDestructor(CXXRD); 56406c3fb27SDimitry Andric 56506c3fb27SDimitry Andric llvm::StringRef Name = 56606c3fb27SDimitry Andric IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base)); 56706c3fb27SDimitry Andric auto AddrOrErr = getSymbolAddress(Name); 56806c3fb27SDimitry Andric if (!AddrOrErr) 56906c3fb27SDimitry Andric return AddrOrErr.takeError(); 57006c3fb27SDimitry Andric 57106c3fb27SDimitry Andric Dtors[CXXRD] = *AddrOrErr; 57206c3fb27SDimitry Andric return AddrOrErr; 57306c3fb27SDimitry Andric } 57406c3fb27SDimitry Andric 57506c3fb27SDimitry Andric static constexpr llvm::StringRef MagicRuntimeInterface[] = { 57606c3fb27SDimitry Andric "__clang_Interpreter_SetValueNoAlloc", 57706c3fb27SDimitry Andric "__clang_Interpreter_SetValueWithAlloc", 5787a6dacacSDimitry Andric "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"}; 57906c3fb27SDimitry Andric 5800fca6ea1SDimitry Andric static std::unique_ptr<RuntimeInterfaceBuilder> 5810fca6ea1SDimitry Andric createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, 5820fca6ea1SDimitry Andric Sema &S); 5830fca6ea1SDimitry Andric 5840fca6ea1SDimitry Andric std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() { 58506c3fb27SDimitry Andric if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; })) 5860fca6ea1SDimitry Andric return nullptr; 58706c3fb27SDimitry Andric 58806c3fb27SDimitry Andric Sema &S = getCompilerInstance()->getSema(); 58906c3fb27SDimitry Andric ASTContext &Ctx = S.getASTContext(); 59006c3fb27SDimitry Andric 59106c3fb27SDimitry Andric auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) { 59206c3fb27SDimitry Andric LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(), 5930fca6ea1SDimitry Andric Sema::LookupOrdinaryName, 5940fca6ea1SDimitry Andric RedeclarationKind::ForVisibleRedeclaration); 59506c3fb27SDimitry Andric S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl()); 59606c3fb27SDimitry Andric if (R.empty()) 59706c3fb27SDimitry Andric return false; 59806c3fb27SDimitry Andric 59906c3fb27SDimitry Andric CXXScopeSpec CSS; 60006c3fb27SDimitry Andric Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get(); 60106c3fb27SDimitry Andric return true; 60206c3fb27SDimitry Andric }; 60306c3fb27SDimitry Andric 60406c3fb27SDimitry Andric if (!LookupInterface(ValuePrintingInfo[NoAlloc], 60506c3fb27SDimitry Andric MagicRuntimeInterface[NoAlloc])) 6060fca6ea1SDimitry Andric return nullptr; 6070fca6ea1SDimitry Andric if (Ctx.getLangOpts().CPlusPlus) { 60806c3fb27SDimitry Andric if (!LookupInterface(ValuePrintingInfo[WithAlloc], 60906c3fb27SDimitry Andric MagicRuntimeInterface[WithAlloc])) 6100fca6ea1SDimitry Andric return nullptr; 61106c3fb27SDimitry Andric if (!LookupInterface(ValuePrintingInfo[CopyArray], 61206c3fb27SDimitry Andric MagicRuntimeInterface[CopyArray])) 6130fca6ea1SDimitry Andric return nullptr; 6147a6dacacSDimitry Andric if (!LookupInterface(ValuePrintingInfo[NewTag], 6157a6dacacSDimitry Andric MagicRuntimeInterface[NewTag])) 6160fca6ea1SDimitry Andric return nullptr; 6170fca6ea1SDimitry Andric } 6180fca6ea1SDimitry Andric 6190fca6ea1SDimitry Andric return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); 62006c3fb27SDimitry Andric } 62106c3fb27SDimitry Andric 62206c3fb27SDimitry Andric namespace { 62306c3fb27SDimitry Andric 6240fca6ea1SDimitry Andric class InterfaceKindVisitor 6250fca6ea1SDimitry Andric : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> { 6260fca6ea1SDimitry Andric friend class InProcessRuntimeInterfaceBuilder; 6270fca6ea1SDimitry Andric 62806c3fb27SDimitry Andric ASTContext &Ctx; 62906c3fb27SDimitry Andric Sema &S; 63006c3fb27SDimitry Andric Expr *E; 63106c3fb27SDimitry Andric llvm::SmallVector<Expr *, 3> Args; 63206c3fb27SDimitry Andric 63306c3fb27SDimitry Andric public: 6340fca6ea1SDimitry Andric InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E) 6350fca6ea1SDimitry Andric : Ctx(Ctx), S(S), E(E) {} 63606c3fb27SDimitry Andric 63706c3fb27SDimitry Andric Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) { 63806c3fb27SDimitry Andric return Interpreter::InterfaceKind::WithAlloc; 63906c3fb27SDimitry Andric } 64006c3fb27SDimitry Andric 64106c3fb27SDimitry Andric Interpreter::InterfaceKind 64206c3fb27SDimitry Andric VisitMemberPointerType(const MemberPointerType *Ty) { 64306c3fb27SDimitry Andric return Interpreter::InterfaceKind::WithAlloc; 64406c3fb27SDimitry Andric } 64506c3fb27SDimitry Andric 64606c3fb27SDimitry Andric Interpreter::InterfaceKind 64706c3fb27SDimitry Andric VisitConstantArrayType(const ConstantArrayType *Ty) { 64806c3fb27SDimitry Andric return Interpreter::InterfaceKind::CopyArray; 64906c3fb27SDimitry Andric } 65006c3fb27SDimitry Andric 65106c3fb27SDimitry Andric Interpreter::InterfaceKind 65206c3fb27SDimitry Andric VisitFunctionProtoType(const FunctionProtoType *Ty) { 65306c3fb27SDimitry Andric HandlePtrType(Ty); 65406c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 65506c3fb27SDimitry Andric } 65606c3fb27SDimitry Andric 65706c3fb27SDimitry Andric Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) { 65806c3fb27SDimitry Andric HandlePtrType(Ty); 65906c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 66006c3fb27SDimitry Andric } 66106c3fb27SDimitry Andric 66206c3fb27SDimitry Andric Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) { 66306c3fb27SDimitry Andric ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E); 66406c3fb27SDimitry Andric assert(!AddrOfE.isInvalid() && "Can not create unary expression"); 66506c3fb27SDimitry Andric Args.push_back(AddrOfE.get()); 66606c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 66706c3fb27SDimitry Andric } 66806c3fb27SDimitry Andric 66906c3fb27SDimitry Andric Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { 67006c3fb27SDimitry Andric if (Ty->isNullPtrType()) 67106c3fb27SDimitry Andric Args.push_back(E); 67206c3fb27SDimitry Andric else if (Ty->isFloatingType()) 67306c3fb27SDimitry Andric Args.push_back(E); 67406c3fb27SDimitry Andric else if (Ty->isIntegralOrEnumerationType()) 67506c3fb27SDimitry Andric HandleIntegralOrEnumType(Ty); 67606c3fb27SDimitry Andric else if (Ty->isVoidType()) { 67706c3fb27SDimitry Andric // Do we need to still run `E`? 67806c3fb27SDimitry Andric } 67906c3fb27SDimitry Andric 68006c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 68106c3fb27SDimitry Andric } 68206c3fb27SDimitry Andric 68306c3fb27SDimitry Andric Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) { 68406c3fb27SDimitry Andric HandleIntegralOrEnumType(Ty); 68506c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 68606c3fb27SDimitry Andric } 68706c3fb27SDimitry Andric 68806c3fb27SDimitry Andric private: 6890fca6ea1SDimitry Andric // Force cast these types to the uint that fits the register size. That way we 6900fca6ea1SDimitry Andric // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`. 69106c3fb27SDimitry Andric void HandleIntegralOrEnumType(const Type *Ty) { 6920fca6ea1SDimitry Andric uint64_t PtrBits = Ctx.getTypeSize(Ctx.VoidPtrTy); 6930fca6ea1SDimitry Andric QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits); 6940fca6ea1SDimitry Andric TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy); 69506c3fb27SDimitry Andric ExprResult CastedExpr = 69606c3fb27SDimitry Andric S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 69706c3fb27SDimitry Andric assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr"); 69806c3fb27SDimitry Andric Args.push_back(CastedExpr.get()); 69906c3fb27SDimitry Andric } 70006c3fb27SDimitry Andric 70106c3fb27SDimitry Andric void HandlePtrType(const Type *Ty) { 70206c3fb27SDimitry Andric TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy); 70306c3fb27SDimitry Andric ExprResult CastedExpr = 70406c3fb27SDimitry Andric S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 70506c3fb27SDimitry Andric assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression"); 70606c3fb27SDimitry Andric Args.push_back(CastedExpr.get()); 70706c3fb27SDimitry Andric } 70806c3fb27SDimitry Andric }; 7090fca6ea1SDimitry Andric 7100fca6ea1SDimitry Andric class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder { 7110fca6ea1SDimitry Andric Interpreter &Interp; 7120fca6ea1SDimitry Andric ASTContext &Ctx; 7130fca6ea1SDimitry Andric Sema &S; 7140fca6ea1SDimitry Andric 7150fca6ea1SDimitry Andric public: 7160fca6ea1SDimitry Andric InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S) 7170fca6ea1SDimitry Andric : Interp(Interp), Ctx(C), S(S) {} 7180fca6ea1SDimitry Andric 7190fca6ea1SDimitry Andric TransformExprFunction *getPrintValueTransformer() override { 7200fca6ea1SDimitry Andric return &transformForValuePrinting; 7210fca6ea1SDimitry Andric } 7220fca6ea1SDimitry Andric 7230fca6ea1SDimitry Andric private: 7240fca6ea1SDimitry Andric static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder, 7250fca6ea1SDimitry Andric Expr *E, 7260fca6ea1SDimitry Andric ArrayRef<Expr *> FixedArgs) { 7270fca6ea1SDimitry Andric auto *B = static_cast<InProcessRuntimeInterfaceBuilder *>(Builder); 7280fca6ea1SDimitry Andric 7290fca6ea1SDimitry Andric // Get rid of ExprWithCleanups. 7300fca6ea1SDimitry Andric if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) 7310fca6ea1SDimitry Andric E = EWC->getSubExpr(); 7320fca6ea1SDimitry Andric 7330fca6ea1SDimitry Andric InterfaceKindVisitor Visitor(B->Ctx, B->S, E); 7340fca6ea1SDimitry Andric 7350fca6ea1SDimitry Andric // The Interpreter* parameter and the out parameter `OutVal`. 7360fca6ea1SDimitry Andric for (Expr *E : FixedArgs) 7370fca6ea1SDimitry Andric Visitor.Args.push_back(E); 7380fca6ea1SDimitry Andric 7390fca6ea1SDimitry Andric QualType Ty = E->getType(); 7400fca6ea1SDimitry Andric QualType DesugaredTy = Ty.getDesugaredType(B->Ctx); 7410fca6ea1SDimitry Andric 7420fca6ea1SDimitry Andric // For lvalue struct, we treat it as a reference. 7430fca6ea1SDimitry Andric if (DesugaredTy->isRecordType() && E->isLValue()) { 7440fca6ea1SDimitry Andric DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy); 7450fca6ea1SDimitry Andric Ty = B->Ctx.getLValueReferenceType(Ty); 7460fca6ea1SDimitry Andric } 7470fca6ea1SDimitry Andric 7480fca6ea1SDimitry Andric Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy, 7490fca6ea1SDimitry Andric (uintptr_t)Ty.getAsOpaquePtr()); 7500fca6ea1SDimitry Andric // The QualType parameter `OpaqueType`, represented as `void*`. 7510fca6ea1SDimitry Andric Visitor.Args.push_back(TypeArg); 7520fca6ea1SDimitry Andric 7530fca6ea1SDimitry Andric // We push the last parameter based on the type of the Expr. Note we need 7540fca6ea1SDimitry Andric // special care for rvalue struct. 7550fca6ea1SDimitry Andric Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy); 7560fca6ea1SDimitry Andric switch (Kind) { 7570fca6ea1SDimitry Andric case Interpreter::InterfaceKind::WithAlloc: 7580fca6ea1SDimitry Andric case Interpreter::InterfaceKind::CopyArray: { 7590fca6ea1SDimitry Andric // __clang_Interpreter_SetValueWithAlloc. 7600fca6ea1SDimitry Andric ExprResult AllocCall = B->S.ActOnCallExpr( 7610fca6ea1SDimitry Andric /*Scope=*/nullptr, 7620fca6ea1SDimitry Andric B->Interp 7630fca6ea1SDimitry Andric .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], 7640fca6ea1SDimitry Andric E->getBeginLoc(), Visitor.Args, E->getEndLoc()); 7650fca6ea1SDimitry Andric assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); 7660fca6ea1SDimitry Andric 7670fca6ea1SDimitry Andric TypeSourceInfo *TSI = 7680fca6ea1SDimitry Andric B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); 7690fca6ea1SDimitry Andric 7700fca6ea1SDimitry Andric // Force CodeGen to emit destructor. 7710fca6ea1SDimitry Andric if (auto *RD = Ty->getAsCXXRecordDecl()) { 7720fca6ea1SDimitry Andric auto *Dtor = B->S.LookupDestructor(RD); 7730fca6ea1SDimitry Andric Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx)); 7740fca6ea1SDimitry Andric B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( 7750fca6ea1SDimitry Andric DeclGroupRef(Dtor)); 7760fca6ea1SDimitry Andric } 7770fca6ea1SDimitry Andric 7780fca6ea1SDimitry Andric // __clang_Interpreter_SetValueCopyArr. 7790fca6ea1SDimitry Andric if (Kind == Interpreter::InterfaceKind::CopyArray) { 7800fca6ea1SDimitry Andric const auto *ConstantArrTy = 7810fca6ea1SDimitry Andric cast<ConstantArrayType>(DesugaredTy.getTypePtr()); 7820fca6ea1SDimitry Andric size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy); 7830fca6ea1SDimitry Andric Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize); 7840fca6ea1SDimitry Andric Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; 7850fca6ea1SDimitry Andric return B->S.ActOnCallExpr( 7860fca6ea1SDimitry Andric /*Scope *=*/nullptr, 7870fca6ea1SDimitry Andric B->Interp 7880fca6ea1SDimitry Andric .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], 7890fca6ea1SDimitry Andric SourceLocation(), Args, SourceLocation()); 7900fca6ea1SDimitry Andric } 7910fca6ea1SDimitry Andric Expr *Args[] = { 7920fca6ea1SDimitry Andric AllocCall.get(), 7930fca6ea1SDimitry Andric B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]}; 7940fca6ea1SDimitry Andric ExprResult CXXNewCall = B->S.BuildCXXNew( 7950fca6ea1SDimitry Andric E->getSourceRange(), 7960fca6ea1SDimitry Andric /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, 7970fca6ea1SDimitry Andric /*PlacementRParen=*/SourceLocation(), 7980fca6ea1SDimitry Andric /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, 7990fca6ea1SDimitry Andric E->getSourceRange(), E); 8000fca6ea1SDimitry Andric 8010fca6ea1SDimitry Andric assert(!CXXNewCall.isInvalid() && 8020fca6ea1SDimitry Andric "Can't create runtime placement new call!"); 8030fca6ea1SDimitry Andric 8040fca6ea1SDimitry Andric return B->S.ActOnFinishFullExpr(CXXNewCall.get(), 8050fca6ea1SDimitry Andric /*DiscardedValue=*/false); 8060fca6ea1SDimitry Andric } 8070fca6ea1SDimitry Andric // __clang_Interpreter_SetValueNoAlloc. 8080fca6ea1SDimitry Andric case Interpreter::InterfaceKind::NoAlloc: { 8090fca6ea1SDimitry Andric return B->S.ActOnCallExpr( 8100fca6ea1SDimitry Andric /*Scope=*/nullptr, 8110fca6ea1SDimitry Andric B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], 8120fca6ea1SDimitry Andric E->getBeginLoc(), Visitor.Args, E->getEndLoc()); 8130fca6ea1SDimitry Andric } 8140fca6ea1SDimitry Andric default: 8150fca6ea1SDimitry Andric llvm_unreachable("Unhandled Interpreter::InterfaceKind"); 8160fca6ea1SDimitry Andric } 8170fca6ea1SDimitry Andric } 8180fca6ea1SDimitry Andric }; 81906c3fb27SDimitry Andric } // namespace 82006c3fb27SDimitry Andric 8210fca6ea1SDimitry Andric static std::unique_ptr<RuntimeInterfaceBuilder> 8220fca6ea1SDimitry Andric createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, 8230fca6ea1SDimitry Andric Sema &S) { 8240fca6ea1SDimitry Andric return std::make_unique<InProcessRuntimeInterfaceBuilder>(Interp, Ctx, S); 8250fca6ea1SDimitry Andric } 8260fca6ea1SDimitry Andric 82706c3fb27SDimitry Andric // This synthesizes a call expression to a speciall 82806c3fb27SDimitry Andric // function that is responsible for generating the Value. 82906c3fb27SDimitry Andric // In general, we transform: 83006c3fb27SDimitry Andric // clang-repl> x 83106c3fb27SDimitry Andric // To: 83206c3fb27SDimitry Andric // // 1. If x is a built-in type like int, float. 83306c3fb27SDimitry Andric // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x); 83406c3fb27SDimitry Andric // // 2. If x is a struct, and a lvalue. 83506c3fb27SDimitry Andric // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, 83606c3fb27SDimitry Andric // &x); 83706c3fb27SDimitry Andric // // 3. If x is a struct, but a rvalue. 83806c3fb27SDimitry Andric // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue, 83906c3fb27SDimitry Andric // xQualType)) (x); 84006c3fb27SDimitry Andric 84106c3fb27SDimitry Andric Expr *Interpreter::SynthesizeExpr(Expr *E) { 84206c3fb27SDimitry Andric Sema &S = getCompilerInstance()->getSema(); 84306c3fb27SDimitry Andric ASTContext &Ctx = S.getASTContext(); 84406c3fb27SDimitry Andric 8450fca6ea1SDimitry Andric if (!RuntimeIB) { 8460fca6ea1SDimitry Andric RuntimeIB = FindRuntimeInterface(); 8470fca6ea1SDimitry Andric AddPrintValueCall = RuntimeIB->getPrintValueTransformer(); 8480fca6ea1SDimitry Andric } 8490fca6ea1SDimitry Andric 8500fca6ea1SDimitry Andric assert(AddPrintValueCall && 8510fca6ea1SDimitry Andric "We don't have a runtime interface for pretty print!"); 85206c3fb27SDimitry Andric 85306c3fb27SDimitry Andric // Create parameter `ThisInterp`. 85406c3fb27SDimitry Andric auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); 85506c3fb27SDimitry Andric 85606c3fb27SDimitry Andric // Create parameter `OutVal`. 85706c3fb27SDimitry Andric auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); 85806c3fb27SDimitry Andric 85906c3fb27SDimitry Andric // Build `__clang_Interpreter_SetValue*` call. 8600fca6ea1SDimitry Andric ExprResult Result = 8610fca6ea1SDimitry Andric AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue}); 86206c3fb27SDimitry Andric 86306c3fb27SDimitry Andric // It could fail, like printing an array type in C. (not supported) 86406c3fb27SDimitry Andric if (Result.isInvalid()) 86506c3fb27SDimitry Andric return E; 86606c3fb27SDimitry Andric return Result.get(); 86706c3fb27SDimitry Andric } 86806c3fb27SDimitry Andric 86906c3fb27SDimitry Andric // Temporary rvalue struct that need special care. 87006c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void * 87106c3fb27SDimitry Andric __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, 87206c3fb27SDimitry Andric void *OpaqueType) { 87306c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 87406c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 87506c3fb27SDimitry Andric return VRef.getPtr(); 87606c3fb27SDimitry Andric } 87706c3fb27SDimitry Andric 8780fca6ea1SDimitry Andric extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc( 8790fca6ea1SDimitry Andric void *This, void *OutVal, void *OpaqueType, ...) { 88006c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 8810fca6ea1SDimitry Andric Interpreter *I = static_cast<Interpreter *>(This); 8820fca6ea1SDimitry Andric VRef = Value(I, OpaqueType); 8830fca6ea1SDimitry Andric if (VRef.isVoid()) 8840fca6ea1SDimitry Andric return; 88506c3fb27SDimitry Andric 8860fca6ea1SDimitry Andric va_list args; 8870fca6ea1SDimitry Andric va_start(args, /*last named param*/ OpaqueType); 88806c3fb27SDimitry Andric 8890fca6ea1SDimitry Andric QualType QT = VRef.getType(); 8900fca6ea1SDimitry Andric if (VRef.getKind() == Value::K_PtrOrObj) { 8910fca6ea1SDimitry Andric VRef.setPtr(va_arg(args, void *)); 8920fca6ea1SDimitry Andric } else { 89306c3fb27SDimitry Andric if (const auto *ET = QT->getAs<EnumType>()) 89406c3fb27SDimitry Andric QT = ET->getDecl()->getIntegerType(); 89506c3fb27SDimitry Andric switch (QT->castAs<BuiltinType>()->getKind()) { 89606c3fb27SDimitry Andric default: 89706c3fb27SDimitry Andric llvm_unreachable("unknown type kind!"); 89806c3fb27SDimitry Andric break; 8990fca6ea1SDimitry Andric // Types shorter than int are resolved as int, else va_arg has UB. 9000fca6ea1SDimitry Andric case BuiltinType::Bool: 9010fca6ea1SDimitry Andric VRef.setBool(va_arg(args, int)); 9020fca6ea1SDimitry Andric break; 9030fca6ea1SDimitry Andric case BuiltinType::Char_S: 9040fca6ea1SDimitry Andric VRef.setChar_S(va_arg(args, int)); 9050fca6ea1SDimitry Andric break; 9060fca6ea1SDimitry Andric case BuiltinType::SChar: 9070fca6ea1SDimitry Andric VRef.setSChar(va_arg(args, int)); 9080fca6ea1SDimitry Andric break; 9090fca6ea1SDimitry Andric case BuiltinType::Char_U: 9100fca6ea1SDimitry Andric VRef.setChar_U(va_arg(args, unsigned)); 9110fca6ea1SDimitry Andric break; 9120fca6ea1SDimitry Andric case BuiltinType::UChar: 9130fca6ea1SDimitry Andric VRef.setUChar(va_arg(args, unsigned)); 9140fca6ea1SDimitry Andric break; 9150fca6ea1SDimitry Andric case BuiltinType::Short: 9160fca6ea1SDimitry Andric VRef.setShort(va_arg(args, int)); 9170fca6ea1SDimitry Andric break; 9180fca6ea1SDimitry Andric case BuiltinType::UShort: 9190fca6ea1SDimitry Andric VRef.setUShort(va_arg(args, unsigned)); 9200fca6ea1SDimitry Andric break; 9210fca6ea1SDimitry Andric case BuiltinType::Int: 9220fca6ea1SDimitry Andric VRef.setInt(va_arg(args, int)); 9230fca6ea1SDimitry Andric break; 9240fca6ea1SDimitry Andric case BuiltinType::UInt: 9250fca6ea1SDimitry Andric VRef.setUInt(va_arg(args, unsigned)); 9260fca6ea1SDimitry Andric break; 9270fca6ea1SDimitry Andric case BuiltinType::Long: 9280fca6ea1SDimitry Andric VRef.setLong(va_arg(args, long)); 9290fca6ea1SDimitry Andric break; 9300fca6ea1SDimitry Andric case BuiltinType::ULong: 9310fca6ea1SDimitry Andric VRef.setULong(va_arg(args, unsigned long)); 9320fca6ea1SDimitry Andric break; 9330fca6ea1SDimitry Andric case BuiltinType::LongLong: 9340fca6ea1SDimitry Andric VRef.setLongLong(va_arg(args, long long)); 9350fca6ea1SDimitry Andric break; 9360fca6ea1SDimitry Andric case BuiltinType::ULongLong: 9370fca6ea1SDimitry Andric VRef.setULongLong(va_arg(args, unsigned long long)); 9380fca6ea1SDimitry Andric break; 9390fca6ea1SDimitry Andric // Types shorter than double are resolved as double, else va_arg has UB. 9400fca6ea1SDimitry Andric case BuiltinType::Float: 9410fca6ea1SDimitry Andric VRef.setFloat(va_arg(args, double)); 9420fca6ea1SDimitry Andric break; 9430fca6ea1SDimitry Andric case BuiltinType::Double: 9440fca6ea1SDimitry Andric VRef.setDouble(va_arg(args, double)); 9450fca6ea1SDimitry Andric break; 9460fca6ea1SDimitry Andric case BuiltinType::LongDouble: 9470fca6ea1SDimitry Andric VRef.setLongDouble(va_arg(args, long double)); 9480fca6ea1SDimitry Andric break; 9490fca6ea1SDimitry Andric // See REPL_BUILTIN_TYPES. 95006c3fb27SDimitry Andric } 95106c3fb27SDimitry Andric } 9520fca6ea1SDimitry Andric va_end(args); 95306c3fb27SDimitry Andric } 9547a6dacacSDimitry Andric 9557a6dacacSDimitry Andric // A trampoline to work around the fact that operator placement new cannot 9567a6dacacSDimitry Andric // really be forward declared due to libc++ and libstdc++ declaration mismatch. 9577a6dacacSDimitry Andric // FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same 9587a6dacacSDimitry Andric // definition in the interpreter runtime. We should move it in a runtime header 9597a6dacacSDimitry Andric // which gets included by the interpreter and here. 9607a6dacacSDimitry Andric struct __clang_Interpreter_NewTag {}; 9617a6dacacSDimitry Andric REPL_EXTERNAL_VISIBILITY void * 9627a6dacacSDimitry Andric operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept { 9637a6dacacSDimitry Andric // Just forward to the standard operator placement new. 9647a6dacacSDimitry Andric return operator new(__sz, __p); 9657a6dacacSDimitry Andric } 966