clang 19.0.0git
Interpreter.cpp
Go to the documentation of this file.
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
20#include "clang/AST/Mangle.h"
28#include "clang/Driver/Driver.h"
29#include "clang/Driver/Job.h"
31#include "clang/Driver/Tool.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.
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>(*Jobs.begin()))
59 return llvm::createStringError(llvm::errc::not_supported,
60 "Driver initialization failed. "
61 "Unable to create a driver job");
62
63 // The one job we find should be to invoke clang again.
64 const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
65 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
66 return llvm::createStringError(llvm::errc::not_supported,
67 "Driver initialization failed");
68
69 return &Cmd->getArguments();
70}
71
73CreateCI(const llvm::opt::ArgStringList &Argv) {
74 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
76
77 // Register the support for object-file-wrapped Clang modules.
78 // FIXME: Clang should register these container operations automatically.
79 auto PCHOps = Clang->getPCHContainerOperations();
80 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
81 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
82
83 // Buffer diagnostics from argument parsing so that we can output them using
84 // a well formed diagnostic object.
87 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
89 Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
90
91 // Infer the builtin include path if unspecified.
92 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
93 Clang->getHeaderSearchOpts().ResourceDir.empty())
94 Clang->getHeaderSearchOpts().ResourceDir =
96
97 // Create the actual diagnostics engine.
98 Clang->createDiagnostics();
99 if (!Clang->hasDiagnostics())
100 return llvm::createStringError(llvm::errc::not_supported,
101 "Initialization failed. "
102 "Unable to create diagnostics engine");
103
104 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
105 if (!Success)
106 return llvm::createStringError(llvm::errc::not_supported,
107 "Initialization failed. "
108 "Unable to flush diagnostics");
109
110 // FIXME: Merge with CompilerInstance::ExecuteAction.
111 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
112 Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
113
114 Clang->setTarget(TargetInfo::CreateTargetInfo(
115 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
116 if (!Clang->hasTarget())
117 return llvm::createStringError(llvm::errc::not_supported,
118 "Initialization failed. "
119 "Target is missing");
120
121 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
122
123 // Don't clear the AST before backend codegen since we do codegen multiple
124 // times, reusing the same AST.
125 Clang->getCodeGenOpts().ClearASTBeforeBackend = false;
126
127 Clang->getFrontendOpts().DisableFree = false;
128 Clang->getCodeGenOpts().DisableFree = false;
129 return std::move(Clang);
130}
131
132} // anonymous namespace
133
135IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
136
137 // If we don't know ClangArgv0 or the address of main() at this point, try
138 // to guess it anyway (it's possible on some platforms).
139 std::string MainExecutableName =
140 llvm::sys::fs::getMainExecutable(nullptr, nullptr);
141
142 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
143
144 // Prepending -c to force the driver to do something if no action was
145 // specified. By prepending we allow users to override the default
146 // action and use other actions in incremental mode.
147 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
148 // We do C++ by default; append right after argv[0] if no "-x" given
149 ClangArgv.insert(ClangArgv.end(), "-Xclang");
150 ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
151 ClangArgv.insert(ClangArgv.end(), "-c");
152
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 >>>");
156
157 // Buffer diagnostics from argument parsing so that we can output them using a
158 // well formed diagnostic object.
161 CreateAndPopulateDiagOpts(ClangArgv);
163 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
164
165 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
166 llvm::sys::getProcessTriple(), Diags);
167 Driver.setCheckInputsExist(false); // the input comes from mem buffers
169 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
170
171 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
172 Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
173
174 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
175 if (auto Err = ErrOrCC1Args.takeError())
176 return std::move(Err);
177
178 return CreateCI(**ErrOrCC1Args);
179}
180
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());
187
188 return IncrementalCompilerBuilder::create(Argv);
189}
190
192IncrementalCompilerBuilder::createCuda(bool device) {
193 std::vector<const char *> Argv;
194 Argv.reserve(5 + 4 + UserArgs.size());
195
196 Argv.push_back("-xcuda");
197 if (device)
198 Argv.push_back("--cuda-device-only");
199 else
200 Argv.push_back("--cuda-host-only");
201
202 std::string SDKPathArg = "--cuda-path=";
203 if (!CudaSDKPath.empty()) {
204 SDKPathArg += CudaSDKPath;
205 Argv.push_back(SDKPathArg.c_str());
206 }
207
208 std::string ArchArg = "--offload-arch=";
209 if (!OffloadArch.empty()) {
210 ArchArg += OffloadArch;
211 Argv.push_back(ArchArg.c_str());
212 }
213
214 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
215
216 return IncrementalCompilerBuilder::create(Argv);
217}
218
221 return IncrementalCompilerBuilder::createCuda(true);
222}
223
226 return IncrementalCompilerBuilder::createCuda(false);
227}
228
229Interpreter::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);
236}
237
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)));
244 }
245}
246
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.
250const char *const Runtimes = R"(
251#ifdef __cplusplus
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 struct __clang_Interpreter_NewTag{} __ci_newtag;
260 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
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), __ci_newtag) T(Src[Idx]);
265 }
266 template <class T, unsigned long N>
267 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
268 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
269 }
270#endif // __cplusplus
271)";
272
274Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
275 llvm::Error Err = llvm::Error::success();
276 auto Interp =
277 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
278 if (Err)
279 return std::move(Err);
280
281 auto PTU = Interp->Parse(Runtimes);
282 if (!PTU)
283 return PTU.takeError();
284
285 Interp->ValuePrintingInfo.resize(4);
286 // FIXME: This is a ugly hack. Undo command checks its availability by looking
287 // at the size of the PTU list. However we have parsed something in the
288 // beginning of the REPL so we have to mark them as 'Irrevocable'.
289 Interp->InitPTUSize = Interp->IncrParser->getPTUs().size();
290 return std::move(Interp);
291}
292
294Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
295 std::unique_ptr<CompilerInstance> DCI) {
296 // avoid writing fat binary to disk using an in-memory virtual file system
298 std::make_unique<llvm::vfs::InMemoryFileSystem>();
300 std::make_unique<llvm::vfs::OverlayFileSystem>(
301 llvm::vfs::getRealFileSystem());
302 OverlayVFS->pushOverlay(IMVFS);
303 CI->createFileManager(OverlayVFS);
304
305 auto Interp = Interpreter::create(std::move(CI));
306 if (auto E = Interp.takeError())
307 return std::move(E);
308
309 llvm::Error Err = llvm::Error::success();
310 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
311 **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
312 *(*Interp)->TSCtx->getContext(), IMVFS, Err);
313 if (Err)
314 return std::move(Err);
315
316 (*Interp)->DeviceParser = std::move(DeviceParser);
317
318 return Interp;
319}
320
322 return IncrParser->getCI();
323}
324
326 return IncrParser->getCI();
327}
328
330 if (!IncrExecutor) {
331 if (auto Err = CreateExecutor())
332 return std::move(Err);
333 }
334
335 return IncrExecutor->GetExecutionEngine();
336}
337
340}
341
344}
345
346size_t Interpreter::getEffectivePTUSize() const {
347 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
348 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
349 return PTUs.size() - InitPTUSize;
350}
351
353Interpreter::Parse(llvm::StringRef Code) {
354 // If we have a device parser, parse it first.
355 // The generated code will be included in the host compilation
356 if (DeviceParser) {
357 auto DevicePTU = DeviceParser->Parse(Code);
358 if (auto E = DevicePTU.takeError())
359 return std::move(E);
360 }
361
362 // Tell the interpreter sliently ignore unused expressions since value
363 // printing could cause it.
365 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
366 return IncrParser->Parse(Code);
367}
368
369llvm::Error Interpreter::CreateExecutor() {
370 const clang::TargetInfo &TI =
372 llvm::Error Err = llvm::Error::success();
373 auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI);
374 if (!Err)
375 IncrExecutor = std::move(Executor);
376
377 return Err;
378}
379
381 assert(T.TheModule);
382 if (!IncrExecutor) {
383 auto Err = CreateExecutor();
384 if (Err)
385 return Err;
386 }
387 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
388 if (auto Err = IncrExecutor->addModule(T))
389 return Err;
390
391 if (auto Err = IncrExecutor->runCtors())
392 return Err;
393
394 return llvm::Error::success();
395}
396
397llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
398
399 auto PTU = Parse(Code);
400 if (!PTU)
401 return PTU.takeError();
402 if (PTU->TheModule)
403 if (llvm::Error Err = Execute(*PTU))
404 return Err;
405
406 if (LastValue.isValid()) {
407 if (!V) {
408 LastValue.dump();
409 LastValue.clear();
410 } else
411 *V = std::move(LastValue);
412 }
413 return llvm::Error::success();
414}
415
418 if (!IncrExecutor)
419 return llvm::make_error<llvm::StringError>("Operation failed. "
420 "No execution engine",
421 std::error_code());
422 llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
423 return getSymbolAddress(MangledName);
424}
425
427Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
428 if (!IncrExecutor)
429 return llvm::make_error<llvm::StringError>("Operation failed. "
430 "No execution engine",
431 std::error_code());
432
433 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
434}
435
438 if (!IncrExecutor)
439 return llvm::make_error<llvm::StringError>("Operation failed. "
440 "No execution engine",
441 std::error_code());
442
443 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
444}
445
446llvm::Error Interpreter::Undo(unsigned N) {
447
448 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
449 if (N > getEffectivePTUSize())
450 return llvm::make_error<llvm::StringError>("Operation failed. "
451 "Too many undos",
452 std::error_code());
453 for (unsigned I = 0; I < N; I++) {
454 if (IncrExecutor) {
455 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
456 return Err;
457 }
458
459 IncrParser->CleanUpPTU(PTUs.back());
460 PTUs.pop_back();
461 }
462 return llvm::Error::success();
463}
464
465llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
466 auto EE = getExecutionEngine();
467 if (!EE)
468 return EE.takeError();
469
470 auto &DL = EE->getDataLayout();
471
472 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
473 name, DL.getGlobalPrefix()))
474 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
475 else
476 return DLSG.takeError();
477
478 return llvm::Error::success();
479}
480
483 assert(CXXRD && "Cannot compile a destructor for a nullptr");
484 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
485 return Dtor->getSecond();
486
487 if (CXXRD->hasIrrelevantDestructor())
488 return llvm::orc::ExecutorAddr{};
489
490 CXXDestructorDecl *DtorRD =
492
493 llvm::StringRef Name =
494 IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
495 auto AddrOrErr = getSymbolAddress(Name);
496 if (!AddrOrErr)
497 return AddrOrErr.takeError();
498
499 Dtors[CXXRD] = *AddrOrErr;
500 return AddrOrErr;
501}
502
503static constexpr llvm::StringRef MagicRuntimeInterface[] = {
504 "__clang_Interpreter_SetValueNoAlloc",
505 "__clang_Interpreter_SetValueWithAlloc",
506 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
507
508bool Interpreter::FindRuntimeInterface() {
509 if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
510 return true;
511
513 ASTContext &Ctx = S.getASTContext();
514
515 auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
516 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
519 if (R.empty())
520 return false;
521
522 CXXScopeSpec CSS;
523 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
524 return true;
525 };
526
527 if (!LookupInterface(ValuePrintingInfo[NoAlloc],
529 return false;
530 if (!LookupInterface(ValuePrintingInfo[WithAlloc],
532 return false;
533 if (!LookupInterface(ValuePrintingInfo[CopyArray],
535 return false;
536 if (!LookupInterface(ValuePrintingInfo[NewTag],
538 return false;
539 return true;
540}
541
542namespace {
543
544class RuntimeInterfaceBuilder
545 : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> {
546 clang::Interpreter &Interp;
547 ASTContext &Ctx;
548 Sema &S;
549 Expr *E;
551
552public:
553 RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef,
554 Expr *VE, ArrayRef<Expr *> FixedArgs)
555 : Interp(In), Ctx(C), S(SemaRef), E(VE) {
556 // The Interpreter* parameter and the out parameter `OutVal`.
557 for (Expr *E : FixedArgs)
558 Args.push_back(E);
559
560 // Get rid of ExprWithCleanups.
561 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
562 E = EWC->getSubExpr();
563 }
564
565 ExprResult getCall() {
566 QualType Ty = E->getType();
567 QualType DesugaredTy = Ty.getDesugaredType(Ctx);
568
569 // For lvalue struct, we treat it as a reference.
570 if (DesugaredTy->isRecordType() && E->isLValue()) {
571 DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
572 Ty = Ctx.getLValueReferenceType(Ty);
573 }
574
575 Expr *TypeArg =
577 // The QualType parameter `OpaqueType`, represented as `void*`.
578 Args.push_back(TypeArg);
579
580 // We push the last parameter based on the type of the Expr. Note we need
581 // special care for rvalue struct.
582 Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy);
583 switch (Kind) {
584 case Interpreter::InterfaceKind::WithAlloc:
585 case Interpreter::InterfaceKind::CopyArray: {
586 // __clang_Interpreter_SetValueWithAlloc.
587 ExprResult AllocCall = S.ActOnCallExpr(
588 /*Scope=*/nullptr,
589 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
590 E->getBeginLoc(), Args, E->getEndLoc());
591 assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
592
594
595 // Force CodeGen to emit destructor.
596 if (auto *RD = Ty->getAsCXXRecordDecl()) {
597 auto *Dtor = S.LookupDestructor(RD);
598 Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
600 DeclGroupRef(Dtor));
601 }
602
603 // __clang_Interpreter_SetValueCopyArr.
604 if (Kind == Interpreter::InterfaceKind::CopyArray) {
605 const auto *ConstantArrTy =
606 cast<ConstantArrayType>(DesugaredTy.getTypePtr());
607 size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy);
608 Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize);
609 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
610 return S.ActOnCallExpr(
611 /*Scope *=*/nullptr,
612 Interp
613 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
614 SourceLocation(), Args, SourceLocation());
615 }
616 Expr *Args[] = {
617 AllocCall.get(),
618 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
619 ExprResult CXXNewCall = S.BuildCXXNew(
620 E->getSourceRange(),
621 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
622 /*PlacementRParen=*/SourceLocation(),
623 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
624 E->getSourceRange(), E);
625
626 assert(!CXXNewCall.isInvalid() &&
627 "Can't create runtime placement new call!");
628
629 return S.ActOnFinishFullExpr(CXXNewCall.get(),
630 /*DiscardedValue=*/false);
631 }
632 // __clang_Interpreter_SetValueNoAlloc.
633 case Interpreter::InterfaceKind::NoAlloc: {
634 return S.ActOnCallExpr(
635 /*Scope=*/nullptr,
636 Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
637 E->getBeginLoc(), Args, E->getEndLoc());
638 }
639 default:
640 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
641 }
642 }
643
644 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
645 return Interpreter::InterfaceKind::WithAlloc;
646 }
647
649 VisitMemberPointerType(const MemberPointerType *Ty) {
650 return Interpreter::InterfaceKind::WithAlloc;
651 }
652
654 VisitConstantArrayType(const ConstantArrayType *Ty) {
655 return Interpreter::InterfaceKind::CopyArray;
656 }
657
659 VisitFunctionProtoType(const FunctionProtoType *Ty) {
660 HandlePtrType(Ty);
661 return Interpreter::InterfaceKind::NoAlloc;
662 }
663
664 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
665 HandlePtrType(Ty);
666 return Interpreter::InterfaceKind::NoAlloc;
667 }
668
669 Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
670 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
671 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
672 Args.push_back(AddrOfE.get());
673 return Interpreter::InterfaceKind::NoAlloc;
674 }
675
676 Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
677 if (Ty->isNullPtrType())
678 Args.push_back(E);
679 else if (Ty->isFloatingType())
680 Args.push_back(E);
681 else if (Ty->isIntegralOrEnumerationType())
682 HandleIntegralOrEnumType(Ty);
683 else if (Ty->isVoidType()) {
684 // Do we need to still run `E`?
685 }
686
687 return Interpreter::InterfaceKind::NoAlloc;
688 }
689
690 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
691 HandleIntegralOrEnumType(Ty);
692 return Interpreter::InterfaceKind::NoAlloc;
693 }
694
695private:
696 // Force cast these types to uint64 to reduce the number of overloads of
697 // `__clang_Interpreter_SetValueNoAlloc`.
698 void HandleIntegralOrEnumType(const Type *Ty) {
700 ExprResult CastedExpr =
702 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
703 Args.push_back(CastedExpr.get());
704 }
705
706 void HandlePtrType(const Type *Ty) {
708 ExprResult CastedExpr =
710 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
711 Args.push_back(CastedExpr.get());
712 }
713};
714} // namespace
715
716// This synthesizes a call expression to a speciall
717// function that is responsible for generating the Value.
718// In general, we transform:
719// clang-repl> x
720// To:
721// // 1. If x is a built-in type like int, float.
722// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
723// // 2. If x is a struct, and a lvalue.
724// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
725// &x);
726// // 3. If x is a struct, but a rvalue.
727// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
728// xQualType)) (x);
729
732 ASTContext &Ctx = S.getASTContext();
733
734 if (!FindRuntimeInterface())
735 llvm_unreachable("We can't find the runtime iterface for pretty print!");
736
737 // Create parameter `ThisInterp`.
738 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
739
740 // Create parameter `OutVal`.
741 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
742
743 // Build `__clang_Interpreter_SetValue*` call.
744 RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});
745
746 ExprResult Result = Builder.getCall();
747 // It could fail, like printing an array type in C. (not supported)
748 if (Result.isInvalid())
749 return E;
750 return Result.get();
751}
752
753// Temporary rvalue struct that need special care.
756 void *OpaqueType) {
757 Value &VRef = *(Value *)OutVal;
758 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
759 return VRef.getPtr();
760}
761
762// Pointers, lvalue struct that can take as a reference.
764__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
765 void *Val) {
766 Value &VRef = *(Value *)OutVal;
767 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
768 VRef.setPtr(Val);
769}
770
772__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
773 void *OpaqueType) {
774 Value &VRef = *(Value *)OutVal;
775 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
776}
777
778static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) {
779 QualType QT = V.getType();
780 if (const auto *ET = QT->getAs<EnumType>())
781 QT = ET->getDecl()->getIntegerType();
782
783 switch (QT->castAs<BuiltinType>()->getKind()) {
784 default:
785 llvm_unreachable("unknown type kind!");
786#define X(type, name) \
787 case BuiltinType::name: \
788 V.set##name(Data); \
789 break;
791#undef X
792 }
793}
794
796__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
797 unsigned long long Val) {
798 Value &VRef = *(Value *)OutVal;
799 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
801}
802
804__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
805 float Val) {
806 Value &VRef = *(Value *)OutVal;
807 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
808 VRef.setFloat(Val);
809}
810
812__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
813 double Val) {
814 Value &VRef = *(Value *)OutVal;
815 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
816 VRef.setDouble(Val);
817}
818
820__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
821 long double Val) {
822 Value &VRef = *(Value *)OutVal;
823 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
824 VRef.setLongDouble(Val);
825}
826
827// A trampoline to work around the fact that operator placement new cannot
828// really be forward declared due to libc++ and libstdc++ declaration mismatch.
829// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
830// definition in the interpreter runtime. We should move it in a runtime header
831// which gets included by the interpreter and here.
834operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
835 // Just forward to the standard operator placement new.
836 return operator new(__sz, __p);
837}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3255
CompileCommand Cmd
#define REPL_EXTERNAL_VISIBILITY
Definition: Value.h:72
#define REPL_BUILTIN_TYPES
Definition: Value.h:75
static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data)
const char *const Runtimes
REPL_EXTERNAL_VISIBILITY void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, void *Val)
REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
static constexpr llvm::StringRef MagicRuntimeInterface[]
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static __inline__ uint32_t volatile uint32_t * __p
Definition: arm_acle.h:80
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Definition: ASTConsumer.cpp:18
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1068
CanQualType VoidPtrTy
Definition: ASTContext.h:1113
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition: ASTContext.h:639
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1097
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:752
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
This class is used for builtin types like 'int'.
Definition: Type.h:2739
Kind getKind() const
Definition: Type.h:2781
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2792
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasIrrelevantDestructor() const
Determine whether this class has a destructor which has no semantic effect.
Definition: DeclCXX.h:1402
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:73
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
ASTContext & getASTContext() const
ASTConsumer & getASTConsumer() const
static std::string GetResourcesPath(const char *Argv0, void *MainAddr)
Get the directory where the compiler headers reside, relative to the compiler binary (found by the pa...
static bool CreateFromArgs(CompilerInvocation &Res, ArrayRef< const char * > CommandLineArgs, DiagnosticsEngine &Diags, const char *Argv0=nullptr)
Create a compiler invocation from a list of input options.
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3185
void addAttr(Attr *A)
Definition: DeclBase.cpp:975
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
Definition: Diagnostic.cpp:354
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:5117
This represents one expression.
Definition: Expr.h:110
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:271
QualType getType() const
Definition: Expr.h:142
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4198
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:56
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaHost()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCpp()
llvm::Expected< std::unique_ptr< CompilerInstance > > CreateCudaDevice()
Provides top-level interfaces for incremental compilation and execution.
Definition: Interpreter.h:76
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
llvm::Error Execute(PartialTranslationUnit &T)
llvm::Expected< llvm::orc::LLJIT & > getExecutionEngine()
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const
static llvm::Expected< std::unique_ptr< Interpreter > > createWithCUDA(std::unique_ptr< CompilerInstance > CI, std::unique_ptr< CompilerInstance > DCI)
const CompilerInstance * getCompilerInstance() const
llvm::Expected< llvm::orc::ExecutorAddr > CompileDtorCall(CXXRecordDecl *CXXRD)
llvm::Error LoadDynamicLibrary(const char *name)
Link a dynamic library.
const llvm::SmallVectorImpl< Expr * > & getValuePrintingInfo() const
Definition: Interpreter.h:134
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V=nullptr)
Expr * SynthesizeExpr(Expr *E)
static llvm::Expected< std::unique_ptr< Interpreter > > create(std::unique_ptr< CompilerInstance > CI)
llvm::Expected< PartialTranslationUnit & > Parse(llvm::StringRef Code)
llvm::Error Undo(unsigned N=1)
Undo N previous incremental inputs.
const ASTContext & getASTContext() const
Represents the results of name lookup.
Definition: Lookup.h:46
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: Type.h:3088
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2897
A (possibly-)qualified type.
Definition: Type.h:737
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition: Type.h:1088
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6901
void * getAsOpaquePtr() const
Definition: Type.h:784
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5091
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3008
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:425
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:16298
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:4490
ASTContext & getASTContext() const
Definition: Sema.h:1801
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, QualType AllocType, TypeSourceInfo *AllocTypeInfo, std::optional< Expr * > ArraySize, SourceRange DirectInitRange, Expr *Initializer)
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3331
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
Definition: SemaExpr.cpp:3423
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
Definition: Sema.h:4546
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
Definition: SemaExpr.cpp:7168
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:7143
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:350
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
Exposes information about the current target.
Definition: TargetInfo.h:212
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
Definition: Targets.cpp:761
void FlushDiagnostics(DiagnosticsEngine &Diags) const
FlushDiagnostics - Flush the buffered diagnostics to an given diagnostic engine.
A container of type source information.
Definition: Type.h:6872
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:6883
An operation on a type.
Definition: TypeVisitor.h:64
The base class of the type hierarchy.
Definition: Type.h:1606
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1819
bool isVoidType() const
Definition: Type.h:7442
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:7719
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:7549
bool isFloatingType() const
Definition: Type.cpp:2186
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7652
bool isNullPtrType() const
Definition: Type.h:7467
bool isRecordType() const
Definition: Type.h:7243
void * getPtr() const
Definition: Value.cpp:229
void dump() const
Definition: Value.cpp:256
void clear()
Definition: Value.cpp:218
bool isValid() const
Definition: Value.h:131
void setPtr(void *Ptr)
Definition: Value.h:140
Command - An executable path/name and argument vector to execute.
Definition: Job.h:106
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
const llvm::opt::DerivedArgList & getArgs() const
Definition: Compilation.h:201
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:77
JobList - A sequence of jobs to perform.
Definition: Job.h:262
size_type size() const
Definition: Job.h:285
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo=nullptr) const
Definition: Job.cpp:453
iterator begin()
Definition: Job.h:286
Defines the clang::TargetInfo interface.
@ Ignored
Do not present this diagnostic, ignore it.
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
@ Result
The result type of a method or function.
IntegerLiteral * IntegerLiteralExpr(ASTContext &C, uint64_t Val)
@ Dtor_Base
Base object dtor.
Definition: ABI.h:36
Expr * CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E)
@ Success
Template argument deduction was successful.
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
The class keeps track of various objects created as part of processing incremental inputs.
std::unique_ptr< llvm::Module > TheModule
The llvm IR produced for the input.