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