[lld][WebAssembly] Add `--table-base` setting
[llvm-project.git] / clang / lib / Interpreter / Interpreter.cpp
blob4e1045298537b1dc6a7106fce2ec9dbfdd5bb5d4
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.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Interpreter/Interpreter.h"
16 #include "DeviceOffload.h"
17 #include "IncrementalExecutor.h"
18 #include "IncrementalParser.h"
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;
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");
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");
70 return &Cmd->getArguments();
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());
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>());
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);
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);
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");
105 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
106 if (!Success)
107 return llvm::createStringError(llvm::errc::not_supported,
108 "Initialization failed. "
109 "Unable to flush diagnostics");
111 // FIXME: Merge with CompilerInstance::ExecuteAction.
112 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
113 Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
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");
122 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
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;
128 Clang->getFrontendOpts().DisableFree = false;
129 Clang->getCodeGenOpts().DisableFree = false;
131 return std::move(Clang);
134 } // anonymous namespace
136 llvm::Expected<std::unique_ptr<CompilerInstance>>
137 IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
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);
144 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
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");
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 >>>");
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);
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));
173 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
174 Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
176 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
177 if (auto Err = ErrOrCC1Args.takeError())
178 return std::move(Err);
180 return CreateCI(**ErrOrCC1Args);
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());
190 return IncrementalCompilerBuilder::create(Argv);
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());
198 Argv.push_back("-xcuda");
199 if (device)
200 Argv.push_back("--cuda-device-only");
201 else
202 Argv.push_back("--cuda-host-only");
204 std::string SDKPathArg = "--cuda-path=";
205 if (!CudaSDKPath.empty()) {
206 SDKPathArg += CudaSDKPath;
207 Argv.push_back(SDKPathArg.c_str());
210 std::string ArchArg = "--offload-arch=";
211 if (!OffloadArch.empty()) {
212 ArchArg += OffloadArch;
213 Argv.push_back(ArchArg.c_str());
216 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
218 return IncrementalCompilerBuilder::create(Argv);
221 llvm::Expected<std::unique_ptr<CompilerInstance>>
222 IncrementalCompilerBuilder::CreateCudaDevice() {
223 return IncrementalCompilerBuilder::createCuda(true);
226 llvm::Expected<std::unique_ptr<CompilerInstance>>
227 IncrementalCompilerBuilder::CreateCudaHost() {
228 return IncrementalCompilerBuilder::createCuda(false);
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);
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)));
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]);
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);
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();
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);
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);
303 auto Interp = Interpreter::create(std::move(CI));
304 if (auto E = Interp.takeError())
305 return std::move(E);
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);
314 (*Interp)->DeviceParser = std::move(DeviceParser);
316 return Interp;
319 const CompilerInstance *Interpreter::getCompilerInstance() const {
320 return IncrParser->getCI();
323 llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
324 if (!IncrExecutor) {
325 if (auto Err = CreateExecutor())
326 return std::move(Err);
329 return IncrExecutor->GetExecutionEngine();
332 ASTContext &Interpreter::getASTContext() {
333 return getCompilerInstance()->getASTContext();
336 const ASTContext &Interpreter::getASTContext() const {
337 return getCompilerInstance()->getASTContext();
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;
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);
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);
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);
371 return Err;
374 llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
375 assert(T.TheModule);
376 if (!IncrExecutor) {
377 auto Err = CreateExecutor();
378 if (Err)
379 return Err;
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;
385 if (auto Err = IncrExecutor->runCtors())
386 return Err;
388 return llvm::Error::success();
391 llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
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;
400 if (LastValue.isValid()) {
401 if (!V) {
402 LastValue.dump();
403 LastValue.clear();
404 } else
405 *V = std::move(LastValue);
407 return llvm::Error::success();
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);
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());
427 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
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());
437 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
440 llvm::Error Interpreter::Undo(unsigned N) {
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;
453 IncrParser->CleanUpPTU(PTUs.back());
454 PTUs.pop_back();
456 return llvm::Error::success();
459 llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
460 auto EE = getExecutionEngine();
461 if (!EE)
462 return EE.takeError();
464 auto &DL = EE->getDataLayout();
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();
472 return llvm::Error::success();
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();
481 if (CXXRD->hasIrrelevantDestructor())
482 return llvm::orc::ExecutorAddr{};
484 CXXDestructorDecl *DtorRD =
485 getCompilerInstance()->getSema().LookupDestructor(CXXRD);
487 llvm::StringRef Name =
488 IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
489 auto AddrOrErr = getSymbolAddress(Name);
490 if (!AddrOrErr)
491 return AddrOrErr.takeError();
493 Dtors[CXXRD] = *AddrOrErr;
494 return AddrOrErr;
497 static constexpr llvm::StringRef MagicRuntimeInterface[] = {
498 "__clang_Interpreter_SetValueNoAlloc",
499 "__clang_Interpreter_SetValueWithAlloc",
500 "__clang_Interpreter_SetValueCopyArr"};
502 bool Interpreter::FindRuntimeInterface() {
503 if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
504 return true;
506 Sema &S = getCompilerInstance()->getSema();
507 ASTContext &Ctx = S.getASTContext();
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;
516 CXXScopeSpec CSS;
517 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
518 return true;
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;
533 namespace {
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;
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);
551 // Get rid of ExprWithCleanups.
552 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
553 E = EWC->getSubExpr();
556 ExprResult getCall() {
557 QualType Ty = E->getType();
558 QualType DesugaredTy = Ty.getDesugaredType(Ctx);
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);
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);
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!");
584 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
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));
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());
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);
615 assert(!CXXNewCall.isInvalid() &&
616 "Can't create runtime placement new call!");
618 return S.ActOnFinishFullExpr(CXXNewCall.get(),
619 /*DiscardedValue=*/false);
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());
629 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
632 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
633 return Interpreter::InterfaceKind::WithAlloc;
636 Interpreter::InterfaceKind
637 VisitMemberPointerType(const MemberPointerType *Ty) {
638 return Interpreter::InterfaceKind::WithAlloc;
641 Interpreter::InterfaceKind
642 VisitConstantArrayType(const ConstantArrayType *Ty) {
643 return Interpreter::InterfaceKind::CopyArray;
646 Interpreter::InterfaceKind
647 VisitFunctionProtoType(const FunctionProtoType *Ty) {
648 HandlePtrType(Ty);
649 return Interpreter::InterfaceKind::NoAlloc;
652 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
653 HandlePtrType(Ty);
654 return Interpreter::InterfaceKind::NoAlloc;
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;
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`?
675 return Interpreter::InterfaceKind::NoAlloc;
678 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
679 HandleIntegralOrEnumType(Ty);
680 return Interpreter::InterfaceKind::NoAlloc;
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());
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());
702 } // namespace
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);
718 Expr *Interpreter::SynthesizeExpr(Expr *E) {
719 Sema &S = getCompilerInstance()->getSema();
720 ASTContext &Ctx = S.getASTContext();
722 if (!FindRuntimeInterface())
723 llvm_unreachable("We can't find the runtime iterface for pretty print!");
725 // Create parameter `ThisInterp`.
726 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
728 // Create parameter `OutVal`.
729 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
731 // Build `__clang_Interpreter_SetValue*` call.
732 RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});
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();
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();
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);
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);
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();
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
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);
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);
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);
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);