xref: /freebsd-src/contrib/llvm-project/clang/lib/Interpreter/Interpreter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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