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