[Flang] remove whole-archive option for AIX linker (#76039)
[llvm-project.git] / clang / lib / Interpreter / Interpreter.cpp
blobc9fcef5b5b5af1398e1290551ae4eb6afe07f64b
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 "DeviceOffload.h"
15 #include "IncrementalExecutor.h"
16 #include "IncrementalParser.h"
17 #include "InterpreterUtils.h"
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;
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");
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");
69 return &Cmd->getArguments();
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());
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>());
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);
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);
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");
104 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
105 if (!Success)
106 return llvm::createStringError(llvm::errc::not_supported,
107 "Initialization failed. "
108 "Unable to flush diagnostics");
110 // FIXME: Merge with CompilerInstance::ExecuteAction.
111 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
112 Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
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");
121 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
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;
127 Clang->getFrontendOpts().DisableFree = false;
128 Clang->getCodeGenOpts().DisableFree = false;
129 return std::move(Clang);
132 } // anonymous namespace
134 llvm::Expected<std::unique_ptr<CompilerInstance>>
135 IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
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);
142 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
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(), "-c");
153 // Put a dummy C++ file on to ensure there's at least one compile job for the
154 // driver to construct.
155 ClangArgv.push_back("<<< inputs >>>");
157 // Buffer diagnostics from argument parsing so that we can output them using a
158 // well formed diagnostic object.
159 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
160 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
161 CreateAndPopulateDiagOpts(ClangArgv);
162 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
163 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
165 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
166 llvm::sys::getProcessTriple(), 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(RF));
171 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
172 Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
174 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
175 if (auto Err = ErrOrCC1Args.takeError())
176 return std::move(Err);
178 return CreateCI(**ErrOrCC1Args);
181 llvm::Expected<std::unique_ptr<CompilerInstance>>
182 IncrementalCompilerBuilder::CreateCpp() {
183 std::vector<const char *> Argv;
184 Argv.reserve(5 + 1 + UserArgs.size());
185 Argv.push_back("-xc++");
186 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
188 return IncrementalCompilerBuilder::create(Argv);
191 llvm::Expected<std::unique_ptr<CompilerInstance>>
192 IncrementalCompilerBuilder::createCuda(bool device) {
193 std::vector<const char *> Argv;
194 Argv.reserve(5 + 4 + UserArgs.size());
196 Argv.push_back("-xcuda");
197 if (device)
198 Argv.push_back("--cuda-device-only");
199 else
200 Argv.push_back("--cuda-host-only");
202 std::string SDKPathArg = "--cuda-path=";
203 if (!CudaSDKPath.empty()) {
204 SDKPathArg += CudaSDKPath;
205 Argv.push_back(SDKPathArg.c_str());
208 std::string ArchArg = "--offload-arch=";
209 if (!OffloadArch.empty()) {
210 ArchArg += OffloadArch;
211 Argv.push_back(ArchArg.c_str());
214 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
216 return IncrementalCompilerBuilder::create(Argv);
219 llvm::Expected<std::unique_ptr<CompilerInstance>>
220 IncrementalCompilerBuilder::CreateCudaDevice() {
221 return IncrementalCompilerBuilder::createCuda(true);
224 llvm::Expected<std::unique_ptr<CompilerInstance>>
225 IncrementalCompilerBuilder::CreateCudaHost() {
226 return IncrementalCompilerBuilder::createCuda(false);
229 Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
230 llvm::Error &Err) {
231 llvm::ErrorAsOutParameter EAO(&Err);
232 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
233 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
234 IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI),
235 *TSCtx->getContext(), Err);
238 Interpreter::~Interpreter() {
239 if (IncrExecutor) {
240 if (llvm::Error Err = IncrExecutor->cleanUp())
241 llvm::report_fatal_error(
242 llvm::Twine("Failed to clean up IncrementalExecutor: ") +
243 toString(std::move(Err)));
247 // These better to put in a runtime header but we can't. This is because we
248 // can't find the precise resource directory in unittests so we have to hard
249 // code them.
250 const char *const Runtimes = R"(
251 void* operator new(__SIZE_TYPE__, void* __p) noexcept;
252 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
253 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
254 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
255 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
256 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
257 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
258 void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
259 template <class T, class = T (*)() /*disable for arrays*/>
260 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
261 for (auto Idx = 0; Idx < Size; ++Idx)
262 new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]);
264 template <class T, unsigned long N>
265 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
266 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
270 llvm::Expected<std::unique_ptr<Interpreter>>
271 Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
272 llvm::Error Err = llvm::Error::success();
273 auto Interp =
274 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
275 if (Err)
276 return std::move(Err);
278 auto PTU = Interp->Parse(Runtimes);
279 if (!PTU)
280 return PTU.takeError();
282 Interp->ValuePrintingInfo.resize(3);
283 // FIXME: This is a ugly hack. Undo command checks its availability by looking
284 // at the size of the PTU list. However we have parsed something in the
285 // beginning of the REPL so we have to mark them as 'Irrevocable'.
286 Interp->InitPTUSize = Interp->IncrParser->getPTUs().size();
287 return std::move(Interp);
290 llvm::Expected<std::unique_ptr<Interpreter>>
291 Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
292 std::unique_ptr<CompilerInstance> DCI) {
293 // avoid writing fat binary to disk using an in-memory virtual file system
294 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS =
295 std::make_unique<llvm::vfs::InMemoryFileSystem>();
296 llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
297 std::make_unique<llvm::vfs::OverlayFileSystem>(
298 llvm::vfs::getRealFileSystem());
299 OverlayVFS->pushOverlay(IMVFS);
300 CI->createFileManager(OverlayVFS);
302 auto Interp = Interpreter::create(std::move(CI));
303 if (auto E = Interp.takeError())
304 return std::move(E);
306 llvm::Error Err = llvm::Error::success();
307 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
308 **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
309 *(*Interp)->TSCtx->getContext(), IMVFS, Err);
310 if (Err)
311 return std::move(Err);
313 (*Interp)->DeviceParser = std::move(DeviceParser);
315 return Interp;
318 const CompilerInstance *Interpreter::getCompilerInstance() const {
319 return IncrParser->getCI();
322 CompilerInstance *Interpreter::getCompilerInstance() {
323 return IncrParser->getCI();
326 llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
327 if (!IncrExecutor) {
328 if (auto Err = CreateExecutor())
329 return std::move(Err);
332 return IncrExecutor->GetExecutionEngine();
335 ASTContext &Interpreter::getASTContext() {
336 return getCompilerInstance()->getASTContext();
339 const ASTContext &Interpreter::getASTContext() const {
340 return getCompilerInstance()->getASTContext();
343 size_t Interpreter::getEffectivePTUSize() const {
344 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
345 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
346 return PTUs.size() - InitPTUSize;
349 llvm::Expected<PartialTranslationUnit &>
350 Interpreter::Parse(llvm::StringRef Code) {
351 // If we have a device parser, parse it first.
352 // The generated code will be included in the host compilation
353 if (DeviceParser) {
354 auto DevicePTU = DeviceParser->Parse(Code);
355 if (auto E = DevicePTU.takeError())
356 return std::move(E);
359 // Tell the interpreter sliently ignore unused expressions since value
360 // printing could cause it.
361 getCompilerInstance()->getDiagnostics().setSeverity(
362 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
363 return IncrParser->Parse(Code);
366 llvm::Error Interpreter::CreateExecutor() {
367 const clang::TargetInfo &TI =
368 getCompilerInstance()->getASTContext().getTargetInfo();
369 llvm::Error Err = llvm::Error::success();
370 auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI);
371 if (!Err)
372 IncrExecutor = std::move(Executor);
374 return Err;
377 llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
378 assert(T.TheModule);
379 if (!IncrExecutor) {
380 auto Err = CreateExecutor();
381 if (Err)
382 return Err;
384 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
385 if (auto Err = IncrExecutor->addModule(T))
386 return Err;
388 if (auto Err = IncrExecutor->runCtors())
389 return Err;
391 return llvm::Error::success();
394 llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
396 auto PTU = Parse(Code);
397 if (!PTU)
398 return PTU.takeError();
399 if (PTU->TheModule)
400 if (llvm::Error Err = Execute(*PTU))
401 return Err;
403 if (LastValue.isValid()) {
404 if (!V) {
405 LastValue.dump();
406 LastValue.clear();
407 } else
408 *V = std::move(LastValue);
410 return llvm::Error::success();
413 llvm::Expected<llvm::orc::ExecutorAddr>
414 Interpreter::getSymbolAddress(GlobalDecl GD) const {
415 if (!IncrExecutor)
416 return llvm::make_error<llvm::StringError>("Operation failed. "
417 "No execution engine",
418 std::error_code());
419 llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
420 return getSymbolAddress(MangledName);
423 llvm::Expected<llvm::orc::ExecutorAddr>
424 Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
425 if (!IncrExecutor)
426 return llvm::make_error<llvm::StringError>("Operation failed. "
427 "No execution engine",
428 std::error_code());
430 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
433 llvm::Expected<llvm::orc::ExecutorAddr>
434 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
435 if (!IncrExecutor)
436 return llvm::make_error<llvm::StringError>("Operation failed. "
437 "No execution engine",
438 std::error_code());
440 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
443 llvm::Error Interpreter::Undo(unsigned N) {
445 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
446 if (N > getEffectivePTUSize())
447 return llvm::make_error<llvm::StringError>("Operation failed. "
448 "Too many undos",
449 std::error_code());
450 for (unsigned I = 0; I < N; I++) {
451 if (IncrExecutor) {
452 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
453 return Err;
456 IncrParser->CleanUpPTU(PTUs.back());
457 PTUs.pop_back();
459 return llvm::Error::success();
462 llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
463 auto EE = getExecutionEngine();
464 if (!EE)
465 return EE.takeError();
467 auto &DL = EE->getDataLayout();
469 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
470 name, DL.getGlobalPrefix()))
471 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
472 else
473 return DLSG.takeError();
475 return llvm::Error::success();
478 llvm::Expected<llvm::orc::ExecutorAddr>
479 Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
480 assert(CXXRD && "Cannot compile a destructor for a nullptr");
481 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
482 return Dtor->getSecond();
484 if (CXXRD->hasIrrelevantDestructor())
485 return llvm::orc::ExecutorAddr{};
487 CXXDestructorDecl *DtorRD =
488 getCompilerInstance()->getSema().LookupDestructor(CXXRD);
490 llvm::StringRef Name =
491 IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
492 auto AddrOrErr = getSymbolAddress(Name);
493 if (!AddrOrErr)
494 return AddrOrErr.takeError();
496 Dtors[CXXRD] = *AddrOrErr;
497 return AddrOrErr;
500 static constexpr llvm::StringRef MagicRuntimeInterface[] = {
501 "__clang_Interpreter_SetValueNoAlloc",
502 "__clang_Interpreter_SetValueWithAlloc",
503 "__clang_Interpreter_SetValueCopyArr"};
505 bool Interpreter::FindRuntimeInterface() {
506 if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
507 return true;
509 Sema &S = getCompilerInstance()->getSema();
510 ASTContext &Ctx = S.getASTContext();
512 auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
513 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
514 Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
515 S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl());
516 if (R.empty())
517 return false;
519 CXXScopeSpec CSS;
520 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
521 return true;
524 if (!LookupInterface(ValuePrintingInfo[NoAlloc],
525 MagicRuntimeInterface[NoAlloc]))
526 return false;
527 if (!LookupInterface(ValuePrintingInfo[WithAlloc],
528 MagicRuntimeInterface[WithAlloc]))
529 return false;
530 if (!LookupInterface(ValuePrintingInfo[CopyArray],
531 MagicRuntimeInterface[CopyArray]))
532 return false;
533 return true;
536 namespace {
538 class RuntimeInterfaceBuilder
539 : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> {
540 clang::Interpreter &Interp;
541 ASTContext &Ctx;
542 Sema &S;
543 Expr *E;
544 llvm::SmallVector<Expr *, 3> Args;
546 public:
547 RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef,
548 Expr *VE, ArrayRef<Expr *> FixedArgs)
549 : Interp(In), Ctx(C), S(SemaRef), E(VE) {
550 // The Interpreter* parameter and the out parameter `OutVal`.
551 for (Expr *E : FixedArgs)
552 Args.push_back(E);
554 // Get rid of ExprWithCleanups.
555 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
556 E = EWC->getSubExpr();
559 ExprResult getCall() {
560 QualType Ty = E->getType();
561 QualType DesugaredTy = Ty.getDesugaredType(Ctx);
563 // For lvalue struct, we treat it as a reference.
564 if (DesugaredTy->isRecordType() && E->isLValue()) {
565 DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
566 Ty = Ctx.getLValueReferenceType(Ty);
569 Expr *TypeArg =
570 CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr());
571 // The QualType parameter `OpaqueType`, represented as `void*`.
572 Args.push_back(TypeArg);
574 // We push the last parameter based on the type of the Expr. Note we need
575 // special care for rvalue struct.
576 Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy);
577 switch (Kind) {
578 case Interpreter::InterfaceKind::WithAlloc:
579 case Interpreter::InterfaceKind::CopyArray: {
580 // __clang_Interpreter_SetValueWithAlloc.
581 ExprResult AllocCall = S.ActOnCallExpr(
582 /*Scope=*/nullptr,
583 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
584 E->getBeginLoc(), Args, E->getEndLoc());
585 assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
587 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
589 // Force CodeGen to emit destructor.
590 if (auto *RD = Ty->getAsCXXRecordDecl()) {
591 auto *Dtor = S.LookupDestructor(RD);
592 Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
593 Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
594 DeclGroupRef(Dtor));
597 // __clang_Interpreter_SetValueCopyArr.
598 if (Kind == Interpreter::InterfaceKind::CopyArray) {
599 const auto *ConstantArrTy =
600 cast<ConstantArrayType>(DesugaredTy.getTypePtr());
601 size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy);
602 Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize);
603 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
604 return S.ActOnCallExpr(
605 /*Scope *=*/nullptr,
606 Interp
607 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
608 SourceLocation(), Args, SourceLocation());
610 Expr *Args[] = {AllocCall.get()};
611 ExprResult CXXNewCall = S.BuildCXXNew(
612 E->getSourceRange(),
613 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
614 /*PlacementRParen=*/SourceLocation(),
615 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
616 E->getSourceRange(), E);
618 assert(!CXXNewCall.isInvalid() &&
619 "Can't create runtime placement new call!");
621 return S.ActOnFinishFullExpr(CXXNewCall.get(),
622 /*DiscardedValue=*/false);
624 // __clang_Interpreter_SetValueNoAlloc.
625 case Interpreter::InterfaceKind::NoAlloc: {
626 return S.ActOnCallExpr(
627 /*Scope=*/nullptr,
628 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
629 E->getBeginLoc(), Args, E->getEndLoc());
632 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
635 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
636 return Interpreter::InterfaceKind::WithAlloc;
639 Interpreter::InterfaceKind
640 VisitMemberPointerType(const MemberPointerType *Ty) {
641 return Interpreter::InterfaceKind::WithAlloc;
644 Interpreter::InterfaceKind
645 VisitConstantArrayType(const ConstantArrayType *Ty) {
646 return Interpreter::InterfaceKind::CopyArray;
649 Interpreter::InterfaceKind
650 VisitFunctionProtoType(const FunctionProtoType *Ty) {
651 HandlePtrType(Ty);
652 return Interpreter::InterfaceKind::NoAlloc;
655 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
656 HandlePtrType(Ty);
657 return Interpreter::InterfaceKind::NoAlloc;
660 Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
661 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
662 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
663 Args.push_back(AddrOfE.get());
664 return Interpreter::InterfaceKind::NoAlloc;
667 Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
668 if (Ty->isNullPtrType())
669 Args.push_back(E);
670 else if (Ty->isFloatingType())
671 Args.push_back(E);
672 else if (Ty->isIntegralOrEnumerationType())
673 HandleIntegralOrEnumType(Ty);
674 else if (Ty->isVoidType()) {
675 // Do we need to still run `E`?
678 return Interpreter::InterfaceKind::NoAlloc;
681 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
682 HandleIntegralOrEnumType(Ty);
683 return Interpreter::InterfaceKind::NoAlloc;
686 private:
687 // Force cast these types to uint64 to reduce the number of overloads of
688 // `__clang_Interpreter_SetValueNoAlloc`.
689 void HandleIntegralOrEnumType(const Type *Ty) {
690 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.UnsignedLongLongTy);
691 ExprResult CastedExpr =
692 S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E);
693 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
694 Args.push_back(CastedExpr.get());
697 void HandlePtrType(const Type *Ty) {
698 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy);
699 ExprResult CastedExpr =
700 S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E);
701 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
702 Args.push_back(CastedExpr.get());
705 } // namespace
707 // This synthesizes a call expression to a speciall
708 // function that is responsible for generating the Value.
709 // In general, we transform:
710 // clang-repl> x
711 // To:
712 // // 1. If x is a built-in type like int, float.
713 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
714 // // 2. If x is a struct, and a lvalue.
715 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
716 // &x);
717 // // 3. If x is a struct, but a rvalue.
718 // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
719 // xQualType)) (x);
721 Expr *Interpreter::SynthesizeExpr(Expr *E) {
722 Sema &S = getCompilerInstance()->getSema();
723 ASTContext &Ctx = S.getASTContext();
725 if (!FindRuntimeInterface())
726 llvm_unreachable("We can't find the runtime iterface for pretty print!");
728 // Create parameter `ThisInterp`.
729 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
731 // Create parameter `OutVal`.
732 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
734 // Build `__clang_Interpreter_SetValue*` call.
735 RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});
737 ExprResult Result = Builder.getCall();
738 // It could fail, like printing an array type in C. (not supported)
739 if (Result.isInvalid())
740 return E;
741 return Result.get();
744 // Temporary rvalue struct that need special care.
745 REPL_EXTERNAL_VISIBILITY void *
746 __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
747 void *OpaqueType) {
748 Value &VRef = *(Value *)OutVal;
749 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
750 return VRef.getPtr();
753 // Pointers, lvalue struct that can take as a reference.
754 REPL_EXTERNAL_VISIBILITY void
755 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
756 void *Val) {
757 Value &VRef = *(Value *)OutVal;
758 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
759 VRef.setPtr(Val);
762 REPL_EXTERNAL_VISIBILITY void
763 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
764 void *OpaqueType) {
765 Value &VRef = *(Value *)OutVal;
766 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
769 static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) {
770 QualType QT = V.getType();
771 if (const auto *ET = QT->getAs<EnumType>())
772 QT = ET->getDecl()->getIntegerType();
774 switch (QT->castAs<BuiltinType>()->getKind()) {
775 default:
776 llvm_unreachable("unknown type kind!");
777 #define X(type, name) \
778 case BuiltinType::name: \
779 V.set##name(Data); \
780 break;
781 REPL_BUILTIN_TYPES
782 #undef X
786 REPL_EXTERNAL_VISIBILITY void
787 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
788 unsigned long long Val) {
789 Value &VRef = *(Value *)OutVal;
790 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
791 SetValueDataBasedOnQualType(VRef, Val);
794 REPL_EXTERNAL_VISIBILITY void
795 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
796 float Val) {
797 Value &VRef = *(Value *)OutVal;
798 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
799 VRef.setFloat(Val);
802 REPL_EXTERNAL_VISIBILITY void
803 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
804 double Val) {
805 Value &VRef = *(Value *)OutVal;
806 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
807 VRef.setDouble(Val);
810 REPL_EXTERNAL_VISIBILITY void
811 __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
812 long double Val) {
813 Value &VRef = *(Value *)OutVal;
814 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
815 VRef.setLongDouble(Val);