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 14fe6060f1SDimitry Andric #include "clang/Interpreter/Interpreter.h" 15fe6060f1SDimitry Andric 16*06c3fb27SDimitry Andric #include "DeviceOffload.h" 17fe6060f1SDimitry Andric #include "IncrementalExecutor.h" 18fe6060f1SDimitry Andric #include "IncrementalParser.h" 19fe6060f1SDimitry Andric 20*06c3fb27SDimitry Andric #include "InterpreterUtils.h" 21fe6060f1SDimitry Andric #include "clang/AST/ASTContext.h" 22*06c3fb27SDimitry Andric #include "clang/AST/Mangle.h" 23*06c3fb27SDimitry Andric #include "clang/AST/TypeVisitor.h" 24*06c3fb27SDimitry Andric #include "clang/Basic/DiagnosticSema.h" 25fe6060f1SDimitry Andric #include "clang/Basic/TargetInfo.h" 26*06c3fb27SDimitry Andric #include "clang/CodeGen/CodeGenAction.h" 27fe6060f1SDimitry Andric #include "clang/CodeGen/ModuleBuilder.h" 28fe6060f1SDimitry Andric #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 29fe6060f1SDimitry Andric #include "clang/Driver/Compilation.h" 30fe6060f1SDimitry Andric #include "clang/Driver/Driver.h" 31fe6060f1SDimitry Andric #include "clang/Driver/Job.h" 32fe6060f1SDimitry Andric #include "clang/Driver/Options.h" 33fe6060f1SDimitry Andric #include "clang/Driver/Tool.h" 34fe6060f1SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 35fe6060f1SDimitry Andric #include "clang/Frontend/TextDiagnosticBuffer.h" 36*06c3fb27SDimitry Andric #include "clang/Interpreter/Value.h" 37fe6060f1SDimitry Andric #include "clang/Lex/PreprocessorOptions.h" 38*06c3fb27SDimitry Andric #include "clang/Sema/Lookup.h" 39*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h" 40*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/LLJIT.h" 41fe6060f1SDimitry Andric #include "llvm/IR/Module.h" 42349cc55cSDimitry Andric #include "llvm/Support/Errc.h" 43*06c3fb27SDimitry Andric #include "llvm/Support/ErrorHandling.h" 44*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 45*06c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 46fe6060f1SDimitry Andric using namespace clang; 47fe6060f1SDimitry Andric 48fe6060f1SDimitry Andric // FIXME: Figure out how to unify with namespace init_convenience from 49349cc55cSDimitry Andric // tools/clang-import-test/clang-import-test.cpp 50fe6060f1SDimitry Andric namespace { 51fe6060f1SDimitry Andric /// Retrieves the clang CC1 specific flags out of the compilation's jobs. 52fe6060f1SDimitry Andric /// \returns NULL on error. 53fe6060f1SDimitry Andric static llvm::Expected<const llvm::opt::ArgStringList *> 54fe6060f1SDimitry Andric GetCC1Arguments(DiagnosticsEngine *Diagnostics, 55fe6060f1SDimitry Andric driver::Compilation *Compilation) { 56fe6060f1SDimitry Andric // We expect to get back exactly one Command job, if we didn't something 57fe6060f1SDimitry Andric // failed. Extract that job from the Compilation. 58fe6060f1SDimitry Andric const driver::JobList &Jobs = Compilation->getJobs(); 59fe6060f1SDimitry Andric if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin())) 60349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 61fe6060f1SDimitry Andric "Driver initialization failed. " 62fe6060f1SDimitry Andric "Unable to create a driver job"); 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric // The one job we find should be to invoke clang again. 65fe6060f1SDimitry Andric const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin())); 66fe6060f1SDimitry Andric if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") 67349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 68fe6060f1SDimitry Andric "Driver initialization failed"); 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric return &Cmd->getArguments(); 71fe6060f1SDimitry Andric } 72fe6060f1SDimitry Andric 73fe6060f1SDimitry Andric static llvm::Expected<std::unique_ptr<CompilerInstance>> 74fe6060f1SDimitry Andric CreateCI(const llvm::opt::ArgStringList &Argv) { 75fe6060f1SDimitry Andric std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); 76fe6060f1SDimitry Andric IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric // Register the support for object-file-wrapped Clang modules. 79fe6060f1SDimitry Andric // FIXME: Clang should register these container operations automatically. 80fe6060f1SDimitry Andric auto PCHOps = Clang->getPCHContainerOperations(); 81fe6060f1SDimitry Andric PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 82fe6060f1SDimitry Andric PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 83fe6060f1SDimitry Andric 84fe6060f1SDimitry Andric // Buffer diagnostics from argument parsing so that we can output them using 85fe6060f1SDimitry Andric // a well formed diagnostic object. 86fe6060f1SDimitry Andric IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 87fe6060f1SDimitry Andric TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 88fe6060f1SDimitry Andric DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 89fe6060f1SDimitry Andric bool Success = CompilerInvocation::CreateFromArgs( 90bdd1243dSDimitry Andric Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags); 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric // Infer the builtin include path if unspecified. 93fe6060f1SDimitry Andric if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && 94fe6060f1SDimitry Andric Clang->getHeaderSearchOpts().ResourceDir.empty()) 95fe6060f1SDimitry Andric Clang->getHeaderSearchOpts().ResourceDir = 96fe6060f1SDimitry Andric CompilerInvocation::GetResourcesPath(Argv[0], nullptr); 97fe6060f1SDimitry Andric 98fe6060f1SDimitry Andric // Create the actual diagnostics engine. 99fe6060f1SDimitry Andric Clang->createDiagnostics(); 100fe6060f1SDimitry Andric if (!Clang->hasDiagnostics()) 101349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 102fe6060f1SDimitry Andric "Initialization failed. " 103fe6060f1SDimitry Andric "Unable to create diagnostics engine"); 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); 106fe6060f1SDimitry Andric if (!Success) 107349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 108fe6060f1SDimitry Andric "Initialization failed. " 109fe6060f1SDimitry Andric "Unable to flush diagnostics"); 110fe6060f1SDimitry Andric 111fe6060f1SDimitry Andric // FIXME: Merge with CompilerInstance::ExecuteAction. 112fe6060f1SDimitry Andric llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release(); 113fe6060f1SDimitry Andric Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB); 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric Clang->setTarget(TargetInfo::CreateTargetInfo( 116fe6060f1SDimitry Andric Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); 117fe6060f1SDimitry Andric if (!Clang->hasTarget()) 118349cc55cSDimitry Andric return llvm::createStringError(llvm::errc::not_supported, 119fe6060f1SDimitry Andric "Initialization failed. " 120fe6060f1SDimitry Andric "Target is missing"); 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts()); 123fe6060f1SDimitry Andric 124349cc55cSDimitry Andric // Don't clear the AST before backend codegen since we do codegen multiple 125349cc55cSDimitry Andric // times, reusing the same AST. 126349cc55cSDimitry Andric Clang->getCodeGenOpts().ClearASTBeforeBackend = false; 127349cc55cSDimitry Andric 12881ad6265SDimitry Andric Clang->getFrontendOpts().DisableFree = false; 12981ad6265SDimitry Andric Clang->getCodeGenOpts().DisableFree = false; 13081ad6265SDimitry Andric 131fe6060f1SDimitry Andric return std::move(Clang); 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric } // anonymous namespace 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 137fe6060f1SDimitry Andric IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) { 138fe6060f1SDimitry Andric 139fe6060f1SDimitry Andric // If we don't know ClangArgv0 or the address of main() at this point, try 140fe6060f1SDimitry Andric // to guess it anyway (it's possible on some platforms). 141fe6060f1SDimitry Andric std::string MainExecutableName = 142fe6060f1SDimitry Andric llvm::sys::fs::getMainExecutable(nullptr, nullptr); 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str()); 145fe6060f1SDimitry Andric 146fe6060f1SDimitry Andric // Prepending -c to force the driver to do something if no action was 147fe6060f1SDimitry Andric // specified. By prepending we allow users to override the default 148fe6060f1SDimitry Andric // action and use other actions in incremental mode. 149fe6060f1SDimitry Andric // FIXME: Print proper driver diagnostics if the driver flags are wrong. 150fe6060f1SDimitry Andric // We do C++ by default; append right after argv[0] if no "-x" given 151bdd1243dSDimitry Andric ClangArgv.insert(ClangArgv.end(), "-Xclang"); 152bdd1243dSDimitry Andric ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions"); 153bdd1243dSDimitry Andric ClangArgv.insert(ClangArgv.end(), "-c"); 154fe6060f1SDimitry Andric 155fe6060f1SDimitry Andric // Put a dummy C++ file on to ensure there's at least one compile job for the 156fe6060f1SDimitry Andric // driver to construct. 157fe6060f1SDimitry Andric ClangArgv.push_back("<<< inputs >>>"); 158fe6060f1SDimitry Andric 159fe6060f1SDimitry Andric // Buffer diagnostics from argument parsing so that we can output them using a 160fe6060f1SDimitry Andric // well formed diagnostic object. 161fe6060f1SDimitry Andric IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 162349cc55cSDimitry Andric IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = 163349cc55cSDimitry Andric CreateAndPopulateDiagOpts(ClangArgv); 164fe6060f1SDimitry Andric TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 165fe6060f1SDimitry Andric DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 166fe6060f1SDimitry Andric 167fe6060f1SDimitry Andric driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], 168fe6060f1SDimitry Andric llvm::sys::getProcessTriple(), Diags); 169fe6060f1SDimitry Andric Driver.setCheckInputsExist(false); // the input comes from mem buffers 170bdd1243dSDimitry Andric llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv); 171fe6060f1SDimitry Andric std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF)); 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric if (Compilation->getArgs().hasArg(driver::options::OPT_v)) 174fe6060f1SDimitry Andric Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false); 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get()); 177fe6060f1SDimitry Andric if (auto Err = ErrOrCC1Args.takeError()) 178fe6060f1SDimitry Andric return std::move(Err); 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric return CreateCI(**ErrOrCC1Args); 181fe6060f1SDimitry Andric } 182fe6060f1SDimitry Andric 183*06c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 184*06c3fb27SDimitry Andric IncrementalCompilerBuilder::CreateCpp() { 185*06c3fb27SDimitry Andric std::vector<const char *> Argv; 186*06c3fb27SDimitry Andric Argv.reserve(5 + 1 + UserArgs.size()); 187*06c3fb27SDimitry Andric Argv.push_back("-xc++"); 188*06c3fb27SDimitry Andric Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 189*06c3fb27SDimitry Andric 190*06c3fb27SDimitry Andric return IncrementalCompilerBuilder::create(Argv); 191*06c3fb27SDimitry Andric } 192*06c3fb27SDimitry Andric 193*06c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 194*06c3fb27SDimitry Andric IncrementalCompilerBuilder::createCuda(bool device) { 195*06c3fb27SDimitry Andric std::vector<const char *> Argv; 196*06c3fb27SDimitry Andric Argv.reserve(5 + 4 + UserArgs.size()); 197*06c3fb27SDimitry Andric 198*06c3fb27SDimitry Andric Argv.push_back("-xcuda"); 199*06c3fb27SDimitry Andric if (device) 200*06c3fb27SDimitry Andric Argv.push_back("--cuda-device-only"); 201*06c3fb27SDimitry Andric else 202*06c3fb27SDimitry Andric Argv.push_back("--cuda-host-only"); 203*06c3fb27SDimitry Andric 204*06c3fb27SDimitry Andric std::string SDKPathArg = "--cuda-path="; 205*06c3fb27SDimitry Andric if (!CudaSDKPath.empty()) { 206*06c3fb27SDimitry Andric SDKPathArg += CudaSDKPath; 207*06c3fb27SDimitry Andric Argv.push_back(SDKPathArg.c_str()); 208*06c3fb27SDimitry Andric } 209*06c3fb27SDimitry Andric 210*06c3fb27SDimitry Andric std::string ArchArg = "--offload-arch="; 211*06c3fb27SDimitry Andric if (!OffloadArch.empty()) { 212*06c3fb27SDimitry Andric ArchArg += OffloadArch; 213*06c3fb27SDimitry Andric Argv.push_back(ArchArg.c_str()); 214*06c3fb27SDimitry Andric } 215*06c3fb27SDimitry Andric 216*06c3fb27SDimitry Andric Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); 217*06c3fb27SDimitry Andric 218*06c3fb27SDimitry Andric return IncrementalCompilerBuilder::create(Argv); 219*06c3fb27SDimitry Andric } 220*06c3fb27SDimitry Andric 221*06c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 222*06c3fb27SDimitry Andric IncrementalCompilerBuilder::CreateCudaDevice() { 223*06c3fb27SDimitry Andric return IncrementalCompilerBuilder::createCuda(true); 224*06c3fb27SDimitry Andric } 225*06c3fb27SDimitry Andric 226*06c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<CompilerInstance>> 227*06c3fb27SDimitry Andric IncrementalCompilerBuilder::CreateCudaHost() { 228*06c3fb27SDimitry Andric return IncrementalCompilerBuilder::createCuda(false); 229*06c3fb27SDimitry Andric } 230*06c3fb27SDimitry Andric 231fe6060f1SDimitry Andric Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI, 232fe6060f1SDimitry Andric llvm::Error &Err) { 233fe6060f1SDimitry Andric llvm::ErrorAsOutParameter EAO(&Err); 234fe6060f1SDimitry Andric auto LLVMCtx = std::make_unique<llvm::LLVMContext>(); 235fe6060f1SDimitry Andric TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx)); 236*06c3fb27SDimitry Andric IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI), 237fe6060f1SDimitry Andric *TSCtx->getContext(), Err); 238fe6060f1SDimitry Andric } 239fe6060f1SDimitry Andric 240bdd1243dSDimitry Andric Interpreter::~Interpreter() { 241bdd1243dSDimitry Andric if (IncrExecutor) { 242bdd1243dSDimitry Andric if (llvm::Error Err = IncrExecutor->cleanUp()) 243bdd1243dSDimitry Andric llvm::report_fatal_error( 244bdd1243dSDimitry Andric llvm::Twine("Failed to clean up IncrementalExecutor: ") + 245bdd1243dSDimitry Andric toString(std::move(Err))); 246bdd1243dSDimitry Andric } 247bdd1243dSDimitry Andric } 248fe6060f1SDimitry Andric 249*06c3fb27SDimitry Andric // These better to put in a runtime header but we can't. This is because we 250*06c3fb27SDimitry Andric // can't find the precise resource directory in unittests so we have to hard 251*06c3fb27SDimitry Andric // code them. 252*06c3fb27SDimitry Andric const char *const Runtimes = R"( 253*06c3fb27SDimitry Andric void* operator new(__SIZE_TYPE__, void* __p) noexcept; 254*06c3fb27SDimitry Andric void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); 255*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); 256*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); 257*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); 258*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); 259*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); 260*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long); 261*06c3fb27SDimitry Andric template <class T, class = T (*)() /*disable for arrays*/> 262*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { 263*06c3fb27SDimitry Andric for (auto Idx = 0; Idx < Size; ++Idx) 264*06c3fb27SDimitry Andric new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]); 265*06c3fb27SDimitry Andric } 266*06c3fb27SDimitry Andric template <class T, unsigned long N> 267*06c3fb27SDimitry Andric void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { 268*06c3fb27SDimitry Andric __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); 269*06c3fb27SDimitry Andric } 270*06c3fb27SDimitry Andric )"; 271*06c3fb27SDimitry Andric 272fe6060f1SDimitry Andric llvm::Expected<std::unique_ptr<Interpreter>> 273fe6060f1SDimitry Andric Interpreter::create(std::unique_ptr<CompilerInstance> CI) { 274fe6060f1SDimitry Andric llvm::Error Err = llvm::Error::success(); 275fe6060f1SDimitry Andric auto Interp = 276fe6060f1SDimitry Andric std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err)); 277fe6060f1SDimitry Andric if (Err) 278fe6060f1SDimitry Andric return std::move(Err); 279*06c3fb27SDimitry Andric auto PTU = Interp->Parse(Runtimes); 280*06c3fb27SDimitry Andric if (!PTU) 281*06c3fb27SDimitry Andric return PTU.takeError(); 282*06c3fb27SDimitry Andric 283*06c3fb27SDimitry Andric Interp->ValuePrintingInfo.resize(3); 284*06c3fb27SDimitry Andric // FIXME: This is a ugly hack. Undo command checks its availability by looking 285*06c3fb27SDimitry Andric // at the size of the PTU list. However we have parsed something in the 286*06c3fb27SDimitry Andric // beginning of the REPL so we have to mark them as 'Irrevocable'. 287*06c3fb27SDimitry Andric Interp->InitPTUSize = Interp->IncrParser->getPTUs().size(); 288fe6060f1SDimitry Andric return std::move(Interp); 289fe6060f1SDimitry Andric } 290fe6060f1SDimitry Andric 291*06c3fb27SDimitry Andric llvm::Expected<std::unique_ptr<Interpreter>> 292*06c3fb27SDimitry Andric Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, 293*06c3fb27SDimitry Andric std::unique_ptr<CompilerInstance> DCI) { 294*06c3fb27SDimitry Andric // avoid writing fat binary to disk using an in-memory virtual file system 295*06c3fb27SDimitry Andric llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS = 296*06c3fb27SDimitry Andric std::make_unique<llvm::vfs::InMemoryFileSystem>(); 297*06c3fb27SDimitry Andric llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS = 298*06c3fb27SDimitry Andric std::make_unique<llvm::vfs::OverlayFileSystem>( 299*06c3fb27SDimitry Andric llvm::vfs::getRealFileSystem()); 300*06c3fb27SDimitry Andric OverlayVFS->pushOverlay(IMVFS); 301*06c3fb27SDimitry Andric CI->createFileManager(OverlayVFS); 302*06c3fb27SDimitry Andric 303*06c3fb27SDimitry Andric auto Interp = Interpreter::create(std::move(CI)); 304*06c3fb27SDimitry Andric if (auto E = Interp.takeError()) 305*06c3fb27SDimitry Andric return std::move(E); 306*06c3fb27SDimitry Andric 307*06c3fb27SDimitry Andric llvm::Error Err = llvm::Error::success(); 308*06c3fb27SDimitry Andric auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( 309*06c3fb27SDimitry Andric **Interp, std::move(DCI), *(*Interp)->IncrParser.get(), 310*06c3fb27SDimitry Andric *(*Interp)->TSCtx->getContext(), IMVFS, Err); 311*06c3fb27SDimitry Andric if (Err) 312*06c3fb27SDimitry Andric return std::move(Err); 313*06c3fb27SDimitry Andric 314*06c3fb27SDimitry Andric (*Interp)->DeviceParser = std::move(DeviceParser); 315*06c3fb27SDimitry Andric 316*06c3fb27SDimitry Andric return Interp; 317*06c3fb27SDimitry Andric } 318*06c3fb27SDimitry Andric 319fe6060f1SDimitry Andric const CompilerInstance *Interpreter::getCompilerInstance() const { 320fe6060f1SDimitry Andric return IncrParser->getCI(); 321fe6060f1SDimitry Andric } 322fe6060f1SDimitry Andric 323*06c3fb27SDimitry Andric llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { 324*06c3fb27SDimitry Andric if (!IncrExecutor) { 325*06c3fb27SDimitry Andric if (auto Err = CreateExecutor()) 326*06c3fb27SDimitry Andric return std::move(Err); 327*06c3fb27SDimitry Andric } 328*06c3fb27SDimitry Andric 329*06c3fb27SDimitry Andric return IncrExecutor->GetExecutionEngine(); 330*06c3fb27SDimitry Andric } 331*06c3fb27SDimitry Andric 332*06c3fb27SDimitry Andric ASTContext &Interpreter::getASTContext() { 333*06c3fb27SDimitry Andric return getCompilerInstance()->getASTContext(); 334*06c3fb27SDimitry Andric } 335*06c3fb27SDimitry Andric 336*06c3fb27SDimitry Andric const ASTContext &Interpreter::getASTContext() const { 337*06c3fb27SDimitry Andric return getCompilerInstance()->getASTContext(); 338*06c3fb27SDimitry Andric } 339*06c3fb27SDimitry Andric 340*06c3fb27SDimitry Andric size_t Interpreter::getEffectivePTUSize() const { 341*06c3fb27SDimitry Andric std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); 342*06c3fb27SDimitry Andric assert(PTUs.size() >= InitPTUSize && "empty PTU list?"); 343*06c3fb27SDimitry Andric return PTUs.size() - InitPTUSize; 3443a9a9c0cSDimitry Andric } 3453a9a9c0cSDimitry Andric 346fe6060f1SDimitry Andric llvm::Expected<PartialTranslationUnit &> 347fe6060f1SDimitry Andric Interpreter::Parse(llvm::StringRef Code) { 348*06c3fb27SDimitry Andric // If we have a device parser, parse it first. 349*06c3fb27SDimitry Andric // The generated code will be included in the host compilation 350*06c3fb27SDimitry Andric if (DeviceParser) { 351*06c3fb27SDimitry Andric auto DevicePTU = DeviceParser->Parse(Code); 352*06c3fb27SDimitry Andric if (auto E = DevicePTU.takeError()) 353*06c3fb27SDimitry Andric return std::move(E); 354*06c3fb27SDimitry Andric } 355*06c3fb27SDimitry Andric 356*06c3fb27SDimitry Andric // Tell the interpreter sliently ignore unused expressions since value 357*06c3fb27SDimitry Andric // printing could cause it. 358*06c3fb27SDimitry Andric getCompilerInstance()->getDiagnostics().setSeverity( 359*06c3fb27SDimitry Andric clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation()); 360fe6060f1SDimitry Andric return IncrParser->Parse(Code); 361fe6060f1SDimitry Andric } 362fe6060f1SDimitry Andric 363*06c3fb27SDimitry Andric llvm::Error Interpreter::CreateExecutor() { 364*06c3fb27SDimitry Andric const clang::TargetInfo &TI = 365*06c3fb27SDimitry Andric getCompilerInstance()->getASTContext().getTargetInfo(); 366*06c3fb27SDimitry Andric llvm::Error Err = llvm::Error::success(); 367*06c3fb27SDimitry Andric auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI); 368*06c3fb27SDimitry Andric if (!Err) 369*06c3fb27SDimitry Andric IncrExecutor = std::move(Executor); 370*06c3fb27SDimitry Andric 371*06c3fb27SDimitry Andric return Err; 372*06c3fb27SDimitry Andric } 373*06c3fb27SDimitry Andric 374fe6060f1SDimitry Andric llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { 375fe6060f1SDimitry Andric assert(T.TheModule); 376fe6060f1SDimitry Andric if (!IncrExecutor) { 377*06c3fb27SDimitry Andric auto Err = CreateExecutor(); 378fe6060f1SDimitry Andric if (Err) 379fe6060f1SDimitry Andric return Err; 380fe6060f1SDimitry Andric } 381fe6060f1SDimitry Andric // FIXME: Add a callback to retain the llvm::Module once the JIT is done. 38281ad6265SDimitry Andric if (auto Err = IncrExecutor->addModule(T)) 383fe6060f1SDimitry Andric return Err; 384fe6060f1SDimitry Andric 385fe6060f1SDimitry Andric if (auto Err = IncrExecutor->runCtors()) 386fe6060f1SDimitry Andric return Err; 387fe6060f1SDimitry Andric 388fe6060f1SDimitry Andric return llvm::Error::success(); 389fe6060f1SDimitry Andric } 390349cc55cSDimitry Andric 391*06c3fb27SDimitry Andric llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { 392*06c3fb27SDimitry Andric 393*06c3fb27SDimitry Andric auto PTU = Parse(Code); 394*06c3fb27SDimitry Andric if (!PTU) 395*06c3fb27SDimitry Andric return PTU.takeError(); 396*06c3fb27SDimitry Andric if (PTU->TheModule) 397*06c3fb27SDimitry Andric if (llvm::Error Err = Execute(*PTU)) 398*06c3fb27SDimitry Andric return Err; 399*06c3fb27SDimitry Andric 400*06c3fb27SDimitry Andric if (LastValue.isValid()) { 401*06c3fb27SDimitry Andric if (!V) { 402*06c3fb27SDimitry Andric LastValue.dump(); 403*06c3fb27SDimitry Andric LastValue.clear(); 404*06c3fb27SDimitry Andric } else 405*06c3fb27SDimitry Andric *V = std::move(LastValue); 406*06c3fb27SDimitry Andric } 407*06c3fb27SDimitry Andric return llvm::Error::success(); 408*06c3fb27SDimitry Andric } 409*06c3fb27SDimitry Andric 410*06c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 411349cc55cSDimitry Andric Interpreter::getSymbolAddress(GlobalDecl GD) const { 412349cc55cSDimitry Andric if (!IncrExecutor) 413349cc55cSDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 414349cc55cSDimitry Andric "No execution engine", 415349cc55cSDimitry Andric std::error_code()); 416349cc55cSDimitry Andric llvm::StringRef MangledName = IncrParser->GetMangledName(GD); 417349cc55cSDimitry Andric return getSymbolAddress(MangledName); 418349cc55cSDimitry Andric } 419349cc55cSDimitry Andric 420*06c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 421349cc55cSDimitry Andric Interpreter::getSymbolAddress(llvm::StringRef IRName) const { 422349cc55cSDimitry Andric if (!IncrExecutor) 423349cc55cSDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 424349cc55cSDimitry Andric "No execution engine", 425349cc55cSDimitry Andric std::error_code()); 426349cc55cSDimitry Andric 427349cc55cSDimitry Andric return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName); 428349cc55cSDimitry Andric } 429349cc55cSDimitry Andric 430*06c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 431349cc55cSDimitry Andric Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const { 432349cc55cSDimitry Andric if (!IncrExecutor) 433349cc55cSDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 434349cc55cSDimitry Andric "No execution engine", 435349cc55cSDimitry Andric std::error_code()); 436349cc55cSDimitry Andric 437349cc55cSDimitry Andric return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName); 438349cc55cSDimitry Andric } 43981ad6265SDimitry Andric 44081ad6265SDimitry Andric llvm::Error Interpreter::Undo(unsigned N) { 44181ad6265SDimitry Andric 44281ad6265SDimitry Andric std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs(); 443*06c3fb27SDimitry Andric if (N > getEffectivePTUSize()) 44481ad6265SDimitry Andric return llvm::make_error<llvm::StringError>("Operation failed. " 44581ad6265SDimitry Andric "Too many undos", 44681ad6265SDimitry Andric std::error_code()); 44781ad6265SDimitry Andric for (unsigned I = 0; I < N; I++) { 44881ad6265SDimitry Andric if (IncrExecutor) { 44981ad6265SDimitry Andric if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back())) 45081ad6265SDimitry Andric return Err; 45181ad6265SDimitry Andric } 45281ad6265SDimitry Andric 45381ad6265SDimitry Andric IncrParser->CleanUpPTU(PTUs.back()); 45481ad6265SDimitry Andric PTUs.pop_back(); 45581ad6265SDimitry Andric } 45681ad6265SDimitry Andric return llvm::Error::success(); 45781ad6265SDimitry Andric } 458*06c3fb27SDimitry Andric 459*06c3fb27SDimitry Andric llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { 460*06c3fb27SDimitry Andric auto EE = getExecutionEngine(); 461*06c3fb27SDimitry Andric if (!EE) 462*06c3fb27SDimitry Andric return EE.takeError(); 463*06c3fb27SDimitry Andric 464*06c3fb27SDimitry Andric auto &DL = EE->getDataLayout(); 465*06c3fb27SDimitry Andric 466*06c3fb27SDimitry Andric if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load( 467*06c3fb27SDimitry Andric name, DL.getGlobalPrefix())) 468*06c3fb27SDimitry Andric EE->getMainJITDylib().addGenerator(std::move(*DLSG)); 469*06c3fb27SDimitry Andric else 470*06c3fb27SDimitry Andric return DLSG.takeError(); 471*06c3fb27SDimitry Andric 472*06c3fb27SDimitry Andric return llvm::Error::success(); 473*06c3fb27SDimitry Andric } 474*06c3fb27SDimitry Andric 475*06c3fb27SDimitry Andric llvm::Expected<llvm::orc::ExecutorAddr> 476*06c3fb27SDimitry Andric Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) { 477*06c3fb27SDimitry Andric assert(CXXRD && "Cannot compile a destructor for a nullptr"); 478*06c3fb27SDimitry Andric if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end()) 479*06c3fb27SDimitry Andric return Dtor->getSecond(); 480*06c3fb27SDimitry Andric 481*06c3fb27SDimitry Andric if (CXXRD->hasIrrelevantDestructor()) 482*06c3fb27SDimitry Andric return llvm::orc::ExecutorAddr{}; 483*06c3fb27SDimitry Andric 484*06c3fb27SDimitry Andric CXXDestructorDecl *DtorRD = 485*06c3fb27SDimitry Andric getCompilerInstance()->getSema().LookupDestructor(CXXRD); 486*06c3fb27SDimitry Andric 487*06c3fb27SDimitry Andric llvm::StringRef Name = 488*06c3fb27SDimitry Andric IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base)); 489*06c3fb27SDimitry Andric auto AddrOrErr = getSymbolAddress(Name); 490*06c3fb27SDimitry Andric if (!AddrOrErr) 491*06c3fb27SDimitry Andric return AddrOrErr.takeError(); 492*06c3fb27SDimitry Andric 493*06c3fb27SDimitry Andric Dtors[CXXRD] = *AddrOrErr; 494*06c3fb27SDimitry Andric return AddrOrErr; 495*06c3fb27SDimitry Andric } 496*06c3fb27SDimitry Andric 497*06c3fb27SDimitry Andric static constexpr llvm::StringRef MagicRuntimeInterface[] = { 498*06c3fb27SDimitry Andric "__clang_Interpreter_SetValueNoAlloc", 499*06c3fb27SDimitry Andric "__clang_Interpreter_SetValueWithAlloc", 500*06c3fb27SDimitry Andric "__clang_Interpreter_SetValueCopyArr"}; 501*06c3fb27SDimitry Andric 502*06c3fb27SDimitry Andric bool Interpreter::FindRuntimeInterface() { 503*06c3fb27SDimitry Andric if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; })) 504*06c3fb27SDimitry Andric return true; 505*06c3fb27SDimitry Andric 506*06c3fb27SDimitry Andric Sema &S = getCompilerInstance()->getSema(); 507*06c3fb27SDimitry Andric ASTContext &Ctx = S.getASTContext(); 508*06c3fb27SDimitry Andric 509*06c3fb27SDimitry Andric auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) { 510*06c3fb27SDimitry Andric LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(), 511*06c3fb27SDimitry Andric Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration); 512*06c3fb27SDimitry Andric S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl()); 513*06c3fb27SDimitry Andric if (R.empty()) 514*06c3fb27SDimitry Andric return false; 515*06c3fb27SDimitry Andric 516*06c3fb27SDimitry Andric CXXScopeSpec CSS; 517*06c3fb27SDimitry Andric Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get(); 518*06c3fb27SDimitry Andric return true; 519*06c3fb27SDimitry Andric }; 520*06c3fb27SDimitry Andric 521*06c3fb27SDimitry Andric if (!LookupInterface(ValuePrintingInfo[NoAlloc], 522*06c3fb27SDimitry Andric MagicRuntimeInterface[NoAlloc])) 523*06c3fb27SDimitry Andric return false; 524*06c3fb27SDimitry Andric if (!LookupInterface(ValuePrintingInfo[WithAlloc], 525*06c3fb27SDimitry Andric MagicRuntimeInterface[WithAlloc])) 526*06c3fb27SDimitry Andric return false; 527*06c3fb27SDimitry Andric if (!LookupInterface(ValuePrintingInfo[CopyArray], 528*06c3fb27SDimitry Andric MagicRuntimeInterface[CopyArray])) 529*06c3fb27SDimitry Andric return false; 530*06c3fb27SDimitry Andric return true; 531*06c3fb27SDimitry Andric } 532*06c3fb27SDimitry Andric 533*06c3fb27SDimitry Andric namespace { 534*06c3fb27SDimitry Andric 535*06c3fb27SDimitry Andric class RuntimeInterfaceBuilder 536*06c3fb27SDimitry Andric : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> { 537*06c3fb27SDimitry Andric clang::Interpreter &Interp; 538*06c3fb27SDimitry Andric ASTContext &Ctx; 539*06c3fb27SDimitry Andric Sema &S; 540*06c3fb27SDimitry Andric Expr *E; 541*06c3fb27SDimitry Andric llvm::SmallVector<Expr *, 3> Args; 542*06c3fb27SDimitry Andric 543*06c3fb27SDimitry Andric public: 544*06c3fb27SDimitry Andric RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef, 545*06c3fb27SDimitry Andric Expr *VE, ArrayRef<Expr *> FixedArgs) 546*06c3fb27SDimitry Andric : Interp(In), Ctx(C), S(SemaRef), E(VE) { 547*06c3fb27SDimitry Andric // The Interpreter* parameter and the out parameter `OutVal`. 548*06c3fb27SDimitry Andric for (Expr *E : FixedArgs) 549*06c3fb27SDimitry Andric Args.push_back(E); 550*06c3fb27SDimitry Andric 551*06c3fb27SDimitry Andric // Get rid of ExprWithCleanups. 552*06c3fb27SDimitry Andric if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E)) 553*06c3fb27SDimitry Andric E = EWC->getSubExpr(); 554*06c3fb27SDimitry Andric } 555*06c3fb27SDimitry Andric 556*06c3fb27SDimitry Andric ExprResult getCall() { 557*06c3fb27SDimitry Andric QualType Ty = E->getType(); 558*06c3fb27SDimitry Andric QualType DesugaredTy = Ty.getDesugaredType(Ctx); 559*06c3fb27SDimitry Andric 560*06c3fb27SDimitry Andric // For lvalue struct, we treat it as a reference. 561*06c3fb27SDimitry Andric if (DesugaredTy->isRecordType() && E->isLValue()) { 562*06c3fb27SDimitry Andric DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy); 563*06c3fb27SDimitry Andric Ty = Ctx.getLValueReferenceType(Ty); 564*06c3fb27SDimitry Andric } 565*06c3fb27SDimitry Andric 566*06c3fb27SDimitry Andric Expr *TypeArg = 567*06c3fb27SDimitry Andric CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); 568*06c3fb27SDimitry Andric // The QualType parameter `OpaqueType`, represented as `void*`. 569*06c3fb27SDimitry Andric Args.push_back(TypeArg); 570*06c3fb27SDimitry Andric 571*06c3fb27SDimitry Andric // We push the last parameter based on the type of the Expr. Note we need 572*06c3fb27SDimitry Andric // special care for rvalue struct. 573*06c3fb27SDimitry Andric Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy); 574*06c3fb27SDimitry Andric switch (Kind) { 575*06c3fb27SDimitry Andric case Interpreter::InterfaceKind::WithAlloc: 576*06c3fb27SDimitry Andric case Interpreter::InterfaceKind::CopyArray: { 577*06c3fb27SDimitry Andric // __clang_Interpreter_SetValueWithAlloc. 578*06c3fb27SDimitry Andric ExprResult AllocCall = S.ActOnCallExpr( 579*06c3fb27SDimitry Andric /*Scope=*/nullptr, 580*06c3fb27SDimitry Andric Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], 581*06c3fb27SDimitry Andric E->getBeginLoc(), Args, E->getEndLoc()); 582*06c3fb27SDimitry Andric assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); 583*06c3fb27SDimitry Andric 584*06c3fb27SDimitry Andric TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); 585*06c3fb27SDimitry Andric 586*06c3fb27SDimitry Andric // Force CodeGen to emit destructor. 587*06c3fb27SDimitry Andric if (auto *RD = Ty->getAsCXXRecordDecl()) { 588*06c3fb27SDimitry Andric auto *Dtor = S.LookupDestructor(RD); 589*06c3fb27SDimitry Andric Dtor->addAttr(UsedAttr::CreateImplicit(Ctx)); 590*06c3fb27SDimitry Andric Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( 591*06c3fb27SDimitry Andric DeclGroupRef(Dtor)); 592*06c3fb27SDimitry Andric } 593*06c3fb27SDimitry Andric 594*06c3fb27SDimitry Andric // __clang_Interpreter_SetValueCopyArr. 595*06c3fb27SDimitry Andric if (Kind == Interpreter::InterfaceKind::CopyArray) { 596*06c3fb27SDimitry Andric const auto *ConstantArrTy = 597*06c3fb27SDimitry Andric cast<ConstantArrayType>(DesugaredTy.getTypePtr()); 598*06c3fb27SDimitry Andric size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy); 599*06c3fb27SDimitry Andric Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize); 600*06c3fb27SDimitry Andric Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; 601*06c3fb27SDimitry Andric return S.ActOnCallExpr( 602*06c3fb27SDimitry Andric /*Scope *=*/nullptr, 603*06c3fb27SDimitry Andric Interp 604*06c3fb27SDimitry Andric .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], 605*06c3fb27SDimitry Andric SourceLocation(), Args, SourceLocation()); 606*06c3fb27SDimitry Andric } 607*06c3fb27SDimitry Andric Expr *Args[] = {AllocCall.get()}; 608*06c3fb27SDimitry Andric ExprResult CXXNewCall = S.BuildCXXNew( 609*06c3fb27SDimitry Andric E->getSourceRange(), 610*06c3fb27SDimitry Andric /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, 611*06c3fb27SDimitry Andric /*PlacementRParen=*/SourceLocation(), 612*06c3fb27SDimitry Andric /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, 613*06c3fb27SDimitry Andric E->getSourceRange(), E); 614*06c3fb27SDimitry Andric 615*06c3fb27SDimitry Andric assert(!CXXNewCall.isInvalid() && 616*06c3fb27SDimitry Andric "Can't create runtime placement new call!"); 617*06c3fb27SDimitry Andric 618*06c3fb27SDimitry Andric return S.ActOnFinishFullExpr(CXXNewCall.get(), 619*06c3fb27SDimitry Andric /*DiscardedValue=*/false); 620*06c3fb27SDimitry Andric } 621*06c3fb27SDimitry Andric // __clang_Interpreter_SetValueNoAlloc. 622*06c3fb27SDimitry Andric case Interpreter::InterfaceKind::NoAlloc: { 623*06c3fb27SDimitry Andric return S.ActOnCallExpr( 624*06c3fb27SDimitry Andric /*Scope=*/nullptr, 625*06c3fb27SDimitry Andric Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], 626*06c3fb27SDimitry Andric E->getBeginLoc(), Args, E->getEndLoc()); 627*06c3fb27SDimitry Andric } 628*06c3fb27SDimitry Andric } 629*06c3fb27SDimitry Andric llvm_unreachable("Unhandled Interpreter::InterfaceKind"); 630*06c3fb27SDimitry Andric } 631*06c3fb27SDimitry Andric 632*06c3fb27SDimitry Andric Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) { 633*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::WithAlloc; 634*06c3fb27SDimitry Andric } 635*06c3fb27SDimitry Andric 636*06c3fb27SDimitry Andric Interpreter::InterfaceKind 637*06c3fb27SDimitry Andric VisitMemberPointerType(const MemberPointerType *Ty) { 638*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::WithAlloc; 639*06c3fb27SDimitry Andric } 640*06c3fb27SDimitry Andric 641*06c3fb27SDimitry Andric Interpreter::InterfaceKind 642*06c3fb27SDimitry Andric VisitConstantArrayType(const ConstantArrayType *Ty) { 643*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::CopyArray; 644*06c3fb27SDimitry Andric } 645*06c3fb27SDimitry Andric 646*06c3fb27SDimitry Andric Interpreter::InterfaceKind 647*06c3fb27SDimitry Andric VisitFunctionProtoType(const FunctionProtoType *Ty) { 648*06c3fb27SDimitry Andric HandlePtrType(Ty); 649*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 650*06c3fb27SDimitry Andric } 651*06c3fb27SDimitry Andric 652*06c3fb27SDimitry Andric Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) { 653*06c3fb27SDimitry Andric HandlePtrType(Ty); 654*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 655*06c3fb27SDimitry Andric } 656*06c3fb27SDimitry Andric 657*06c3fb27SDimitry Andric Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) { 658*06c3fb27SDimitry Andric ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E); 659*06c3fb27SDimitry Andric assert(!AddrOfE.isInvalid() && "Can not create unary expression"); 660*06c3fb27SDimitry Andric Args.push_back(AddrOfE.get()); 661*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 662*06c3fb27SDimitry Andric } 663*06c3fb27SDimitry Andric 664*06c3fb27SDimitry Andric Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { 665*06c3fb27SDimitry Andric if (Ty->isNullPtrType()) 666*06c3fb27SDimitry Andric Args.push_back(E); 667*06c3fb27SDimitry Andric else if (Ty->isFloatingType()) 668*06c3fb27SDimitry Andric Args.push_back(E); 669*06c3fb27SDimitry Andric else if (Ty->isIntegralOrEnumerationType()) 670*06c3fb27SDimitry Andric HandleIntegralOrEnumType(Ty); 671*06c3fb27SDimitry Andric else if (Ty->isVoidType()) { 672*06c3fb27SDimitry Andric // Do we need to still run `E`? 673*06c3fb27SDimitry Andric } 674*06c3fb27SDimitry Andric 675*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 676*06c3fb27SDimitry Andric } 677*06c3fb27SDimitry Andric 678*06c3fb27SDimitry Andric Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) { 679*06c3fb27SDimitry Andric HandleIntegralOrEnumType(Ty); 680*06c3fb27SDimitry Andric return Interpreter::InterfaceKind::NoAlloc; 681*06c3fb27SDimitry Andric } 682*06c3fb27SDimitry Andric 683*06c3fb27SDimitry Andric private: 684*06c3fb27SDimitry Andric // Force cast these types to uint64 to reduce the number of overloads of 685*06c3fb27SDimitry Andric // `__clang_Interpreter_SetValueNoAlloc`. 686*06c3fb27SDimitry Andric void HandleIntegralOrEnumType(const Type *Ty) { 687*06c3fb27SDimitry Andric TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.UnsignedLongLongTy); 688*06c3fb27SDimitry Andric ExprResult CastedExpr = 689*06c3fb27SDimitry Andric S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 690*06c3fb27SDimitry Andric assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr"); 691*06c3fb27SDimitry Andric Args.push_back(CastedExpr.get()); 692*06c3fb27SDimitry Andric } 693*06c3fb27SDimitry Andric 694*06c3fb27SDimitry Andric void HandlePtrType(const Type *Ty) { 695*06c3fb27SDimitry Andric TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy); 696*06c3fb27SDimitry Andric ExprResult CastedExpr = 697*06c3fb27SDimitry Andric S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E); 698*06c3fb27SDimitry Andric assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression"); 699*06c3fb27SDimitry Andric Args.push_back(CastedExpr.get()); 700*06c3fb27SDimitry Andric } 701*06c3fb27SDimitry Andric }; 702*06c3fb27SDimitry Andric } // namespace 703*06c3fb27SDimitry Andric 704*06c3fb27SDimitry Andric // This synthesizes a call expression to a speciall 705*06c3fb27SDimitry Andric // function that is responsible for generating the Value. 706*06c3fb27SDimitry Andric // In general, we transform: 707*06c3fb27SDimitry Andric // clang-repl> x 708*06c3fb27SDimitry Andric // To: 709*06c3fb27SDimitry Andric // // 1. If x is a built-in type like int, float. 710*06c3fb27SDimitry Andric // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x); 711*06c3fb27SDimitry Andric // // 2. If x is a struct, and a lvalue. 712*06c3fb27SDimitry Andric // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, 713*06c3fb27SDimitry Andric // &x); 714*06c3fb27SDimitry Andric // // 3. If x is a struct, but a rvalue. 715*06c3fb27SDimitry Andric // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue, 716*06c3fb27SDimitry Andric // xQualType)) (x); 717*06c3fb27SDimitry Andric 718*06c3fb27SDimitry Andric Expr *Interpreter::SynthesizeExpr(Expr *E) { 719*06c3fb27SDimitry Andric Sema &S = getCompilerInstance()->getSema(); 720*06c3fb27SDimitry Andric ASTContext &Ctx = S.getASTContext(); 721*06c3fb27SDimitry Andric 722*06c3fb27SDimitry Andric if (!FindRuntimeInterface()) 723*06c3fb27SDimitry Andric llvm_unreachable("We can't find the runtime iterface for pretty print!"); 724*06c3fb27SDimitry Andric 725*06c3fb27SDimitry Andric // Create parameter `ThisInterp`. 726*06c3fb27SDimitry Andric auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); 727*06c3fb27SDimitry Andric 728*06c3fb27SDimitry Andric // Create parameter `OutVal`. 729*06c3fb27SDimitry Andric auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); 730*06c3fb27SDimitry Andric 731*06c3fb27SDimitry Andric // Build `__clang_Interpreter_SetValue*` call. 732*06c3fb27SDimitry Andric RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue}); 733*06c3fb27SDimitry Andric 734*06c3fb27SDimitry Andric ExprResult Result = Builder.getCall(); 735*06c3fb27SDimitry Andric // It could fail, like printing an array type in C. (not supported) 736*06c3fb27SDimitry Andric if (Result.isInvalid()) 737*06c3fb27SDimitry Andric return E; 738*06c3fb27SDimitry Andric return Result.get(); 739*06c3fb27SDimitry Andric } 740*06c3fb27SDimitry Andric 741*06c3fb27SDimitry Andric // Temporary rvalue struct that need special care. 742*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void * 743*06c3fb27SDimitry Andric __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, 744*06c3fb27SDimitry Andric void *OpaqueType) { 745*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 746*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 747*06c3fb27SDimitry Andric return VRef.getPtr(); 748*06c3fb27SDimitry Andric } 749*06c3fb27SDimitry Andric 750*06c3fb27SDimitry Andric // Pointers, lvalue struct that can take as a reference. 751*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void 752*06c3fb27SDimitry Andric __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 753*06c3fb27SDimitry Andric void *Val) { 754*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 755*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 756*06c3fb27SDimitry Andric VRef.setPtr(Val); 757*06c3fb27SDimitry Andric } 758*06c3fb27SDimitry Andric 759*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void 760*06c3fb27SDimitry Andric __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, 761*06c3fb27SDimitry Andric void *OpaqueType) { 762*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 763*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 764*06c3fb27SDimitry Andric } 765*06c3fb27SDimitry Andric 766*06c3fb27SDimitry Andric static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) { 767*06c3fb27SDimitry Andric QualType QT = V.getType(); 768*06c3fb27SDimitry Andric if (const auto *ET = QT->getAs<EnumType>()) 769*06c3fb27SDimitry Andric QT = ET->getDecl()->getIntegerType(); 770*06c3fb27SDimitry Andric 771*06c3fb27SDimitry Andric switch (QT->castAs<BuiltinType>()->getKind()) { 772*06c3fb27SDimitry Andric default: 773*06c3fb27SDimitry Andric llvm_unreachable("unknown type kind!"); 774*06c3fb27SDimitry Andric #define X(type, name) \ 775*06c3fb27SDimitry Andric case BuiltinType::name: \ 776*06c3fb27SDimitry Andric V.set##name(Data); \ 777*06c3fb27SDimitry Andric break; 778*06c3fb27SDimitry Andric REPL_BUILTIN_TYPES 779*06c3fb27SDimitry Andric #undef X 780*06c3fb27SDimitry Andric } 781*06c3fb27SDimitry Andric } 782*06c3fb27SDimitry Andric 783*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void 784*06c3fb27SDimitry Andric __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 785*06c3fb27SDimitry Andric unsigned long long Val) { 786*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 787*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 788*06c3fb27SDimitry Andric SetValueDataBasedOnQualType(VRef, Val); 789*06c3fb27SDimitry Andric } 790*06c3fb27SDimitry Andric 791*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void 792*06c3fb27SDimitry Andric __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 793*06c3fb27SDimitry Andric float Val) { 794*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 795*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 796*06c3fb27SDimitry Andric VRef.setFloat(Val); 797*06c3fb27SDimitry Andric } 798*06c3fb27SDimitry Andric 799*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void 800*06c3fb27SDimitry Andric __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 801*06c3fb27SDimitry Andric double Val) { 802*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 803*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 804*06c3fb27SDimitry Andric VRef.setDouble(Val); 805*06c3fb27SDimitry Andric } 806*06c3fb27SDimitry Andric 807*06c3fb27SDimitry Andric REPL_EXTERNAL_VISIBILITY void 808*06c3fb27SDimitry Andric __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, 809*06c3fb27SDimitry Andric long double Val) { 810*06c3fb27SDimitry Andric Value &VRef = *(Value *)OutVal; 811*06c3fb27SDimitry Andric VRef = Value(static_cast<Interpreter *>(This), OpaqueType); 812*06c3fb27SDimitry Andric VRef.setLongDouble(Val); 813*06c3fb27SDimitry Andric } 814