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