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"
45using namespace clang;
46
47// FIXME: Figure out how to unify with namespace init_convenience from
48// tools/clang-import-test/clang-import-test.cpp
49namespace {
50/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
51/// \returns NULL on error.
52static llvm::Expected<const llvm::opt::ArgStringList *>
53GetCC1Arguments(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>(Val: *Jobs.begin()))
59 return llvm::createStringError(EC: llvm::errc::not_supported,
60 Msg: "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>(Val: &(*Jobs.begin()));
65 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
66 return llvm::createStringError(EC: llvm::errc::not_supported,
67 Msg: "Driver initialization failed");
68
69 return &Cmd->getArguments();
70}
71
72static llvm::Expected<std::unique_ptr<CompilerInstance>>
73CreateCI(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(Writer: std::make_unique<ObjectFilePCHContainerWriter>());
81 PCHOps->registerReader(Reader: 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 Res&: Clang->getInvocation(), CommandLineArgs: 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(Argv0: Argv[0], MainAddr: nullptr);
96
97 // Create the actual diagnostics engine.
98 Clang->createDiagnostics();
99 if (!Clang->hasDiagnostics())
100 return llvm::createStringError(EC: llvm::errc::not_supported,
101 Msg: "Initialization failed. "
102 "Unable to create diagnostics engine");
103
104 DiagsBuffer->FlushDiagnostics(Diags&: Clang->getDiagnostics());
105 if (!Success)
106 return llvm::createStringError(EC: llvm::errc::not_supported,
107 Msg: "Initialization failed. "
108 "Unable to flush diagnostics");
109
110 // FIXME: Merge with CompilerInstance::ExecuteAction.
111 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(InputData: "").release();
112 Clang->getPreprocessorOpts().addRemappedFile(From: "<<< inputs >>>", To: MB);
113
114 Clang->setTarget(TargetInfo::CreateTargetInfo(
115 Diags&: Clang->getDiagnostics(), Opts: Clang->getInvocation().TargetOpts));
116 if (!Clang->hasTarget())
117 return llvm::createStringError(EC: llvm::errc::not_supported,
118 Msg: "Initialization failed. "
119 "Target is missing");
120
121 Clang->getTarget().adjust(Diags&: Clang->getDiagnostics(), Opts&: 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
134llvm::Expected<std::unique_ptr<CompilerInstance>>
135IncrementalCompilerBuilder::create(std::string TT,
136 std::vector<const char *> &ClangArgv) {
137
138 // If we don't know ClangArgv0 or the address of main() at this point, try
139 // to guess it anyway (it's possible on some platforms).
140 std::string MainExecutableName =
141 llvm::sys::fs::getMainExecutable(argv0: nullptr, MainExecAddr: nullptr);
142
143 ClangArgv.insert(position: ClangArgv.begin(), x: MainExecutableName.c_str());
144
145 // Prepending -c to force the driver to do something if no action was
146 // specified. By prepending we allow users to override the default
147 // action and use other actions in incremental mode.
148 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
149 // We do C++ by default; append right after argv[0] if no "-x" given
150 ClangArgv.insert(position: ClangArgv.end(), x: "-Xclang");
151 ClangArgv.insert(position: ClangArgv.end(), x: "-fincremental-extensions");
152 ClangArgv.insert(position: ClangArgv.end(), x: "-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(x: "<<< 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(Argv: ClangArgv);
163 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
164 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
165
166 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
167 Driver.setCheckInputsExist(false); // the input comes from mem buffers
168 llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv);
169 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(Args: RF));
170
171 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
172 Compilation->getJobs().Print(OS&: llvm::errs(), Terminator: "\n", /*Quote=*/false);
173
174 auto ErrOrCC1Args = GetCC1Arguments(Diagnostics: &Diags, Compilation: Compilation.get());
175 if (auto Err = ErrOrCC1Args.takeError())
176 return std::move(Err);
177
178 return CreateCI(Argv: **ErrOrCC1Args);
179}
180
181llvm::Expected<std::unique_ptr<CompilerInstance>>
182IncrementalCompilerBuilder::CreateCpp() {
183 std::vector<const char *> Argv;
184 Argv.reserve(n: 5 + 1 + UserArgs.size());
185 Argv.push_back(x: "-xc++");
186 Argv.insert(position: Argv.end(), first: UserArgs.begin(), last: UserArgs.end());
187
188 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
189 return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv);
190}
191
192llvm::Expected<std::unique_ptr<CompilerInstance>>
193IncrementalCompilerBuilder::createCuda(bool device) {
194 std::vector<const char *> Argv;
195 Argv.reserve(n: 5 + 4 + UserArgs.size());
196
197 Argv.push_back(x: "-xcuda");
198 if (device)
199 Argv.push_back(x: "--cuda-device-only");
200 else
201 Argv.push_back(x: "--cuda-host-only");
202
203 std::string SDKPathArg = "--cuda-path=";
204 if (!CudaSDKPath.empty()) {
205 SDKPathArg += CudaSDKPath;
206 Argv.push_back(x: SDKPathArg.c_str());
207 }
208
209 std::string ArchArg = "--offload-arch=";
210 if (!OffloadArch.empty()) {
211 ArchArg += OffloadArch;
212 Argv.push_back(x: ArchArg.c_str());
213 }
214
215 Argv.insert(position: Argv.end(), first: UserArgs.begin(), last: UserArgs.end());
216
217 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
218 return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv);
219}
220
221llvm::Expected<std::unique_ptr<CompilerInstance>>
222IncrementalCompilerBuilder::CreateCudaDevice() {
223 return IncrementalCompilerBuilder::createCuda(device: true);
224}
225
226llvm::Expected<std::unique_ptr<CompilerInstance>>
227IncrementalCompilerBuilder::CreateCudaHost() {
228 return IncrementalCompilerBuilder::createCuda(device: false);
229}
230
231Interpreter::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>(args: std::move(LLVMCtx));
236 IncrParser = std::make_unique<IncrementalParser>(args&: *this, args: std::move(CI),
237 args&: *TSCtx->getContext(), args&: Err);
238}
239
240Interpreter::~Interpreter() {
241 if (IncrExecutor) {
242 if (llvm::Error Err = IncrExecutor->cleanUp())
243 llvm::report_fatal_error(
244 reason: llvm::Twine("Failed to clean up IncrementalExecutor: ") +
245 toString(E: 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.
252const char *const Runtimes = R"(
253#ifdef __cplusplus
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 struct __clang_Interpreter_NewTag{} __ci_newtag;
262 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
263 template <class T, class = T (*)() /*disable for arrays*/>
264 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
265 for (auto Idx = 0; Idx < Size; ++Idx)
266 new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
267 }
268 template <class T, unsigned long N>
269 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
270 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
271 }
272#endif // __cplusplus
273)";
274
275llvm::Expected<std::unique_ptr<Interpreter>>
276Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
277 llvm::Error Err = llvm::Error::success();
278 auto Interp =
279 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
280 if (Err)
281 return std::move(Err);
282
283 // Add runtime code and set a marker to hide it from user code. Undo will not
284 // go through that.
285 auto PTU = Interp->Parse(Code: Runtimes);
286 if (!PTU)
287 return PTU.takeError();
288 Interp->markUserCodeStart();
289
290 Interp->ValuePrintingInfo.resize(N: 4);
291 return std::move(Interp);
292}
293
294llvm::Expected<std::unique_ptr<Interpreter>>
295Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
296 std::unique_ptr<CompilerInstance> DCI) {
297 // avoid writing fat binary to disk using an in-memory virtual file system
298 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS =
299 std::make_unique<llvm::vfs::InMemoryFileSystem>();
300 llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
301 std::make_unique<llvm::vfs::OverlayFileSystem>(
302 args: llvm::vfs::getRealFileSystem());
303 OverlayVFS->pushOverlay(FS: IMVFS);
304 CI->createFileManager(VFS: OverlayVFS);
305
306 auto Interp = Interpreter::create(CI: std::move(CI));
307 if (auto E = Interp.takeError())
308 return std::move(E);
309
310 llvm::Error Err = llvm::Error::success();
311 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
312 args&: **Interp, args: std::move(DCI), args&: *(*Interp)->IncrParser.get(),
313 args&: *(*Interp)->TSCtx->getContext(), args&: IMVFS, args&: Err);
314 if (Err)
315 return std::move(Err);
316
317 (*Interp)->DeviceParser = std::move(DeviceParser);
318
319 return Interp;
320}
321
322const CompilerInstance *Interpreter::getCompilerInstance() const {
323 return IncrParser->getCI();
324}
325
326CompilerInstance *Interpreter::getCompilerInstance() {
327 return IncrParser->getCI();
328}
329
330llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
331 if (!IncrExecutor) {
332 if (auto Err = CreateExecutor())
333 return std::move(Err);
334 }
335
336 return IncrExecutor->GetExecutionEngine();
337}
338
339ASTContext &Interpreter::getASTContext() {
340 return getCompilerInstance()->getASTContext();
341}
342
343const ASTContext &Interpreter::getASTContext() const {
344 return getCompilerInstance()->getASTContext();
345}
346
347void Interpreter::markUserCodeStart() {
348 assert(!InitPTUSize && "We only do this once");
349 InitPTUSize = IncrParser->getPTUs().size();
350}
351
352size_t Interpreter::getEffectivePTUSize() const {
353 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
354 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
355 return PTUs.size() - InitPTUSize;
356}
357
358llvm::Expected<PartialTranslationUnit &>
359Interpreter::Parse(llvm::StringRef Code) {
360 // If we have a device parser, parse it first.
361 // The generated code will be included in the host compilation
362 if (DeviceParser) {
363 auto DevicePTU = DeviceParser->Parse(Input: Code);
364 if (auto E = DevicePTU.takeError())
365 return std::move(E);
366 }
367
368 // Tell the interpreter sliently ignore unused expressions since value
369 // printing could cause it.
370 getCompilerInstance()->getDiagnostics().setSeverity(
371 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
372 return IncrParser->Parse(Input: Code);
373}
374
375static llvm::Expected<llvm::orc::JITTargetMachineBuilder>
376createJITTargetMachineBuilder(const std::string &TT) {
377 if (TT == llvm::sys::getProcessTriple())
378 // This fails immediately if the target backend is not registered
379 return llvm::orc::JITTargetMachineBuilder::detectHost();
380
381 // If the target backend is not registered, LLJITBuilder::create() will fail
382 return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
383}
384
385llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
386Interpreter::CreateJITBuilder(CompilerInstance &CI) {
387 auto JTMB = createJITTargetMachineBuilder(TT: CI.getTargetOpts().Triple);
388 if (!JTMB)
389 return JTMB.takeError();
390 return IncrementalExecutor::createDefaultJITBuilder(JTMB: std::move(*JTMB));
391}
392
393llvm::Error Interpreter::CreateExecutor() {
394 if (IncrExecutor)
395 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
396 "Execution engine exists",
397 Args: std::error_code());
398 llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> JB =
399 CreateJITBuilder(CI&: *getCompilerInstance());
400 if (!JB)
401 return JB.takeError();
402 llvm::Error Err = llvm::Error::success();
403 auto Executor = std::make_unique<IncrementalExecutor>(args&: *TSCtx, args&: **JB, args&: Err);
404 if (!Err)
405 IncrExecutor = std::move(Executor);
406
407 return Err;
408}
409
410void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
411
412llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
413 assert(T.TheModule);
414 if (!IncrExecutor) {
415 auto Err = CreateExecutor();
416 if (Err)
417 return Err;
418 }
419 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
420 if (auto Err = IncrExecutor->addModule(PTU&: T))
421 return Err;
422
423 if (auto Err = IncrExecutor->runCtors())
424 return Err;
425
426 return llvm::Error::success();
427}
428
429llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
430
431 auto PTU = Parse(Code);
432 if (!PTU)
433 return PTU.takeError();
434 if (PTU->TheModule)
435 if (llvm::Error Err = Execute(T&: *PTU))
436 return Err;
437
438 if (LastValue.isValid()) {
439 if (!V) {
440 LastValue.dump();
441 LastValue.clear();
442 } else
443 *V = std::move(LastValue);
444 }
445 return llvm::Error::success();
446}
447
448llvm::Expected<llvm::orc::ExecutorAddr>
449Interpreter::getSymbolAddress(GlobalDecl GD) const {
450 if (!IncrExecutor)
451 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
452 "No execution engine",
453 Args: std::error_code());
454 llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
455 return getSymbolAddress(IRName: MangledName);
456}
457
458llvm::Expected<llvm::orc::ExecutorAddr>
459Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
460 if (!IncrExecutor)
461 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
462 "No execution engine",
463 Args: std::error_code());
464
465 return IncrExecutor->getSymbolAddress(Name: IRName, NameKind: IncrementalExecutor::IRName);
466}
467
468llvm::Expected<llvm::orc::ExecutorAddr>
469Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
470 if (!IncrExecutor)
471 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
472 "No execution engine",
473 Args: std::error_code());
474
475 return IncrExecutor->getSymbolAddress(Name, NameKind: IncrementalExecutor::LinkerName);
476}
477
478llvm::Error Interpreter::Undo(unsigned N) {
479
480 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
481 if (N > getEffectivePTUSize())
482 return llvm::make_error<llvm::StringError>(Args: "Operation failed. "
483 "Too many undos",
484 Args: std::error_code());
485 for (unsigned I = 0; I < N; I++) {
486 if (IncrExecutor) {
487 if (llvm::Error Err = IncrExecutor->removeModule(PTU&: PTUs.back()))
488 return Err;
489 }
490
491 IncrParser->CleanUpPTU(PTU&: PTUs.back());
492 PTUs.pop_back();
493 }
494 return llvm::Error::success();
495}
496
497llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
498 auto EE = getExecutionEngine();
499 if (!EE)
500 return EE.takeError();
501
502 auto &DL = EE->getDataLayout();
503
504 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
505 FileName: name, GlobalPrefix: DL.getGlobalPrefix()))
506 EE->getMainJITDylib().addGenerator(DefGenerator: std::move(*DLSG));
507 else
508 return DLSG.takeError();
509
510 return llvm::Error::success();
511}
512
513llvm::Expected<llvm::orc::ExecutorAddr>
514Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
515 assert(CXXRD && "Cannot compile a destructor for a nullptr");
516 if (auto Dtor = Dtors.find(Val: CXXRD); Dtor != Dtors.end())
517 return Dtor->getSecond();
518
519 if (CXXRD->hasIrrelevantDestructor())
520 return llvm::orc::ExecutorAddr{};
521
522 CXXDestructorDecl *DtorRD =
523 getCompilerInstance()->getSema().LookupDestructor(Class: CXXRD);
524
525 llvm::StringRef Name =
526 IncrParser->GetMangledName(GD: GlobalDecl(DtorRD, Dtor_Base));
527 auto AddrOrErr = getSymbolAddress(IRName: Name);
528 if (!AddrOrErr)
529 return AddrOrErr.takeError();
530
531 Dtors[CXXRD] = *AddrOrErr;
532 return AddrOrErr;
533}
534
535static constexpr llvm::StringRef MagicRuntimeInterface[] = {
536 "__clang_Interpreter_SetValueNoAlloc",
537 "__clang_Interpreter_SetValueWithAlloc",
538 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
539
540static std::unique_ptr<RuntimeInterfaceBuilder>
541createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx,
542 Sema &S);
543
544std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() {
545 if (llvm::all_of(Range&: ValuePrintingInfo, P: [](Expr *E) { return E != nullptr; }))
546 return nullptr;
547
548 Sema &S = getCompilerInstance()->getSema();
549 ASTContext &Ctx = S.getASTContext();
550
551 auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
552 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
553 Sema::LookupOrdinaryName,
554 RedeclarationKind::ForVisibleRedeclaration);
555 S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl());
556 if (R.empty())
557 return false;
558
559 CXXScopeSpec CSS;
560 Interface = S.BuildDeclarationNameExpr(SS: CSS, R, /*ADL=*/NeedsADL: false).get();
561 return true;
562 };
563
564 if (!LookupInterface(ValuePrintingInfo[NoAlloc],
565 MagicRuntimeInterface[NoAlloc]))
566 return nullptr;
567 if (!LookupInterface(ValuePrintingInfo[WithAlloc],
568 MagicRuntimeInterface[WithAlloc]))
569 return nullptr;
570 if (!LookupInterface(ValuePrintingInfo[CopyArray],
571 MagicRuntimeInterface[CopyArray]))
572 return nullptr;
573 if (!LookupInterface(ValuePrintingInfo[NewTag],
574 MagicRuntimeInterface[NewTag]))
575 return nullptr;
576
577 return createInProcessRuntimeInterfaceBuilder(Interp&: *this, Ctx, S);
578}
579
580namespace {
581
582class InterfaceKindVisitor
583 : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> {
584 friend class InProcessRuntimeInterfaceBuilder;
585
586 ASTContext &Ctx;
587 Sema &S;
588 Expr *E;
589 llvm::SmallVector<Expr *, 3> Args;
590
591public:
592 InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E)
593 : Ctx(Ctx), S(S), E(E) {}
594
595 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
596 return Interpreter::InterfaceKind::WithAlloc;
597 }
598
599 Interpreter::InterfaceKind
600 VisitMemberPointerType(const MemberPointerType *Ty) {
601 return Interpreter::InterfaceKind::WithAlloc;
602 }
603
604 Interpreter::InterfaceKind
605 VisitConstantArrayType(const ConstantArrayType *Ty) {
606 return Interpreter::InterfaceKind::CopyArray;
607 }
608
609 Interpreter::InterfaceKind
610 VisitFunctionProtoType(const FunctionProtoType *Ty) {
611 HandlePtrType(Ty);
612 return Interpreter::InterfaceKind::NoAlloc;
613 }
614
615 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
616 HandlePtrType(Ty);
617 return Interpreter::InterfaceKind::NoAlloc;
618 }
619
620 Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
621 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(OpLoc: SourceLocation(), Opc: UO_AddrOf, InputExpr: E);
622 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
623 Args.push_back(Elt: AddrOfE.get());
624 return Interpreter::InterfaceKind::NoAlloc;
625 }
626
627 Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
628 if (Ty->isNullPtrType())
629 Args.push_back(Elt: E);
630 else if (Ty->isFloatingType())
631 Args.push_back(Elt: E);
632 else if (Ty->isIntegralOrEnumerationType())
633 HandleIntegralOrEnumType(Ty);
634 else if (Ty->isVoidType()) {
635 // Do we need to still run `E`?
636 }
637
638 return Interpreter::InterfaceKind::NoAlloc;
639 }
640
641 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
642 HandleIntegralOrEnumType(Ty);
643 return Interpreter::InterfaceKind::NoAlloc;
644 }
645
646private:
647 // Force cast these types to uint64 to reduce the number of overloads of
648 // `__clang_Interpreter_SetValueNoAlloc`.
649 void HandleIntegralOrEnumType(const Type *Ty) {
650 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: Ctx.UnsignedLongLongTy);
651 ExprResult CastedExpr =
652 S.BuildCStyleCastExpr(LParenLoc: SourceLocation(), Ty: TSI, RParenLoc: SourceLocation(), Op: E);
653 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
654 Args.push_back(Elt: CastedExpr.get());
655 }
656
657 void HandlePtrType(const Type *Ty) {
658 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: Ctx.VoidPtrTy);
659 ExprResult CastedExpr =
660 S.BuildCStyleCastExpr(LParenLoc: SourceLocation(), Ty: TSI, RParenLoc: SourceLocation(), Op: E);
661 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
662 Args.push_back(Elt: CastedExpr.get());
663 }
664};
665
666class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
667 Interpreter &Interp;
668 ASTContext &Ctx;
669 Sema &S;
670
671public:
672 InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S)
673 : Interp(Interp), Ctx(C), S(S) {}
674
675 TransformExprFunction *getPrintValueTransformer() override {
676 return &transformForValuePrinting;
677 }
678
679private:
680 static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder,
681 Expr *E,
682 ArrayRef<Expr *> FixedArgs) {
683 auto *B = static_cast<InProcessRuntimeInterfaceBuilder *>(Builder);
684
685 // Get rid of ExprWithCleanups.
686 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(Val: E))
687 E = EWC->getSubExpr();
688
689 InterfaceKindVisitor Visitor(B->Ctx, B->S, E);
690
691 // The Interpreter* parameter and the out parameter `OutVal`.
692 for (Expr *E : FixedArgs)
693 Visitor.Args.push_back(Elt: E);
694
695 QualType Ty = E->getType();
696 QualType DesugaredTy = Ty.getDesugaredType(Context: B->Ctx);
697
698 // For lvalue struct, we treat it as a reference.
699 if (DesugaredTy->isRecordType() && E->isLValue()) {
700 DesugaredTy = B->Ctx.getLValueReferenceType(T: DesugaredTy);
701 Ty = B->Ctx.getLValueReferenceType(T: Ty);
702 }
703
704 Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy,
705 (uintptr_t)Ty.getAsOpaquePtr());
706 // The QualType parameter `OpaqueType`, represented as `void*`.
707 Visitor.Args.push_back(Elt: TypeArg);
708
709 // We push the last parameter based on the type of the Expr. Note we need
710 // special care for rvalue struct.
711 Interpreter::InterfaceKind Kind = Visitor.Visit(T: &*DesugaredTy);
712 switch (Kind) {
713 case Interpreter::InterfaceKind::WithAlloc:
714 case Interpreter::InterfaceKind::CopyArray: {
715 // __clang_Interpreter_SetValueWithAlloc.
716 ExprResult AllocCall = B->S.ActOnCallExpr(
717 /*Scope=*/S: nullptr,
718 Fn: B->Interp
719 .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
720 LParenLoc: E->getBeginLoc(), ArgExprs: Visitor.Args, RParenLoc: E->getEndLoc());
721 assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
722
723 TypeSourceInfo *TSI =
724 B->Ctx.getTrivialTypeSourceInfo(T: Ty, Loc: SourceLocation());
725
726 // Force CodeGen to emit destructor.
727 if (auto *RD = Ty->getAsCXXRecordDecl()) {
728 auto *Dtor = B->S.LookupDestructor(Class: RD);
729 Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx));
730 B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
731 D: DeclGroupRef(Dtor));
732 }
733
734 // __clang_Interpreter_SetValueCopyArr.
735 if (Kind == Interpreter::InterfaceKind::CopyArray) {
736 const auto *ConstantArrTy =
737 cast<ConstantArrayType>(Val: DesugaredTy.getTypePtr());
738 size_t ArrSize = B->Ctx.getConstantArrayElementCount(CA: ConstantArrTy);
739 Expr *ArrSizeExpr = IntegerLiteralExpr(C&: B->Ctx, Val: ArrSize);
740 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
741 return B->S.ActOnCallExpr(
742 /*Scope *=*/S: nullptr,
743 Fn: B->Interp
744 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
745 LParenLoc: SourceLocation(), ArgExprs: Args, RParenLoc: SourceLocation());
746 }
747 Expr *Args[] = {
748 AllocCall.get(),
749 B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
750 ExprResult CXXNewCall = B->S.BuildCXXNew(
751 Range: E->getSourceRange(),
752 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), PlacementArgs: Args,
753 /*PlacementRParen=*/SourceLocation(),
754 /*TypeIdParens=*/SourceRange(), AllocType: TSI->getType(), AllocTypeInfo: TSI, ArraySize: std::nullopt,
755 DirectInitRange: E->getSourceRange(), Initializer: E);
756
757 assert(!CXXNewCall.isInvalid() &&
758 "Can't create runtime placement new call!");
759
760 return B->S.ActOnFinishFullExpr(Expr: CXXNewCall.get(),
761 /*DiscardedValue=*/false);
762 }
763 // __clang_Interpreter_SetValueNoAlloc.
764 case Interpreter::InterfaceKind::NoAlloc: {
765 return B->S.ActOnCallExpr(
766 /*Scope=*/S: nullptr,
767 Fn: B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
768 LParenLoc: E->getBeginLoc(), ArgExprs: Visitor.Args, RParenLoc: E->getEndLoc());
769 }
770 default:
771 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
772 }
773 }
774};
775} // namespace
776
777static std::unique_ptr<RuntimeInterfaceBuilder>
778createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx,
779 Sema &S) {
780 return std::make_unique<InProcessRuntimeInterfaceBuilder>(args&: Interp, args&: Ctx, args&: S);
781}
782
783// This synthesizes a call expression to a speciall
784// function that is responsible for generating the Value.
785// In general, we transform:
786// clang-repl> x
787// To:
788// // 1. If x is a built-in type like int, float.
789// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
790// // 2. If x is a struct, and a lvalue.
791// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
792// &x);
793// // 3. If x is a struct, but a rvalue.
794// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
795// xQualType)) (x);
796
797Expr *Interpreter::SynthesizeExpr(Expr *E) {
798 Sema &S = getCompilerInstance()->getSema();
799 ASTContext &Ctx = S.getASTContext();
800
801 if (!RuntimeIB) {
802 RuntimeIB = FindRuntimeInterface();
803 AddPrintValueCall = RuntimeIB->getPrintValueTransformer();
804 }
805
806 assert(AddPrintValueCall &&
807 "We don't have a runtime interface for pretty print!");
808
809 // Create parameter `ThisInterp`.
810 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
811
812 // Create parameter `OutVal`.
813 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
814
815 // Build `__clang_Interpreter_SetValue*` call.
816 ExprResult Result =
817 AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue});
818
819 // It could fail, like printing an array type in C. (not supported)
820 if (Result.isInvalid())
821 return E;
822 return Result.get();
823}
824
825// Temporary rvalue struct that need special care.
826REPL_EXTERNAL_VISIBILITY void *
827__clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
828 void *OpaqueType) {
829 Value &VRef = *(Value *)OutVal;
830 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
831 return VRef.getPtr();
832}
833
834// Pointers, lvalue struct that can take as a reference.
835REPL_EXTERNAL_VISIBILITY void
836__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
837 void *Val) {
838 Value &VRef = *(Value *)OutVal;
839 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
840 VRef.setPtr(Val);
841}
842
843REPL_EXTERNAL_VISIBILITY void
844__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
845 void *OpaqueType) {
846 Value &VRef = *(Value *)OutVal;
847 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
848}
849
850static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) {
851 QualType QT = V.getType();
852 if (const auto *ET = QT->getAs<EnumType>())
853 QT = ET->getDecl()->getIntegerType();
854
855 switch (QT->castAs<BuiltinType>()->getKind()) {
856 default:
857 llvm_unreachable("unknown type kind!");
858#define X(type, name) \
859 case BuiltinType::name: \
860 V.set##name(Data); \
861 break;
862 REPL_BUILTIN_TYPES
863#undef X
864 }
865}
866
867REPL_EXTERNAL_VISIBILITY void
868__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
869 unsigned long long Val) {
870 Value &VRef = *(Value *)OutVal;
871 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
872 SetValueDataBasedOnQualType(V&: VRef, Data: Val);
873}
874
875REPL_EXTERNAL_VISIBILITY void
876__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
877 float Val) {
878 Value &VRef = *(Value *)OutVal;
879 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
880 VRef.setFloat(Val);
881}
882
883REPL_EXTERNAL_VISIBILITY void
884__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
885 double Val) {
886 Value &VRef = *(Value *)OutVal;
887 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
888 VRef.setDouble(Val);
889}
890
891REPL_EXTERNAL_VISIBILITY void
892__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
893 long double Val) {
894 Value &VRef = *(Value *)OutVal;
895 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
896 VRef.setLongDouble(Val);
897}
898
899// A trampoline to work around the fact that operator placement new cannot
900// really be forward declared due to libc++ and libstdc++ declaration mismatch.
901// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
902// definition in the interpreter runtime. We should move it in a runtime header
903// which gets included by the interpreter and here.
904struct __clang_Interpreter_NewTag {};
905REPL_EXTERNAL_VISIBILITY void *
906operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
907 // Just forward to the standard operator placement new.
908 return operator new(__sz, __p);
909}
910

source code of clang/lib/Interpreter/Interpreter.cpp