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::string TT,
136 std::vector<const char *> &ClangArgv) {
137
138 // If we don't know ClangArgv0 or the address of main() at this point, try
139 // to guess it anyway (it's possible on some platforms).
140 std::string MainExecutableName =
141 llvm::sys::fs::getMainExecutable(nullptr, nullptr);
142
143 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
144
145 // Prepending -c to force the driver to do something if no action was
146 // specified. By prepending we allow users to override the default
147 // action and use other actions in incremental mode.
148 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
149 // We do C++ by default; append right after argv[0] if no "-x" given
150 ClangArgv.insert(ClangArgv.end(), "-Xclang");
151 ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
152 ClangArgv.insert(ClangArgv.end(), "-c");
153
154 // Put a dummy C++ file on to ensure there's at least one compile job for the
155 // driver to construct.
156 ClangArgv.push_back("<<< inputs >>>");
157
158 // Buffer diagnostics from argument parsing so that we can output them using a
159 // well formed diagnostic object.
162 CreateAndPopulateDiagOpts(ClangArgv);
164 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
165
166 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
167 Driver.setCheckInputsExist(false); // the input comes from mem buffers
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 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
189 return IncrementalCompilerBuilder::create(TT, Argv);
190}
191
193IncrementalCompilerBuilder::createCuda(bool device) {
194 std::vector<const char *> Argv;
195 Argv.reserve(5 + 4 + UserArgs.size());
196
197 Argv.push_back("-xcuda");
198 if (device)
199 Argv.push_back("--cuda-device-only");
200 else
201 Argv.push_back("--cuda-host-only");
202
203 std::string SDKPathArg = "--cuda-path=";
204 if (!CudaSDKPath.empty()) {
205 SDKPathArg += CudaSDKPath;
206 Argv.push_back(SDKPathArg.c_str());
207 }
208
209 std::string ArchArg = "--offload-arch=";
210 if (!OffloadArch.empty()) {
211 ArchArg += OffloadArch;
212 Argv.push_back(ArchArg.c_str());
213 }
214
215 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
216
217 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
218 return IncrementalCompilerBuilder::create(TT, Argv);
219}
220
223 return IncrementalCompilerBuilder::createCuda(true);
224}
225
228 return IncrementalCompilerBuilder::createCuda(false);
229}
230
231Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
232 llvm::Error &Err) {
233 llvm::ErrorAsOutParameter EAO(&Err);
234 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
235 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
236 IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI),
237 *TSCtx->getContext(), Err);
238}
239
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)));
246 }
247}
248
249// These better to put in a runtime header but we can't. This is because we
250// can't find the precise resource directory in unittests so we have to hard
251// code them.
252const char *const Runtimes = R"(
253#ifdef __cplusplus
254 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
255 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
256 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
257 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
258 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
259 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
260 void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
261 struct __clang_Interpreter_NewTag{} __ci_newtag;
262 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
263 template <class T, class = T (*)() /*disable for arrays*/>
264 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
265 for (auto Idx = 0; Idx < Size; ++Idx)
266 new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
267 }
268 template <class T, unsigned long N>
269 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
270 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
271 }
272#endif // __cplusplus
273)";
274
276Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
277 llvm::Error Err = llvm::Error::success();
278 auto Interp =
279 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
280 if (Err)
281 return std::move(Err);
282
283 // Add runtime code and set a marker to hide it from user code. Undo will not
284 // go through that.
285 auto PTU = Interp->Parse(Runtimes);
286 if (!PTU)
287 return PTU.takeError();
288 Interp->markUserCodeStart();
289
290 Interp->ValuePrintingInfo.resize(4);
291 return std::move(Interp);
292}
293
295Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
296 std::unique_ptr<CompilerInstance> DCI) {
297 // avoid writing fat binary to disk using an in-memory virtual file system
299 std::make_unique<llvm::vfs::InMemoryFileSystem>();
301 std::make_unique<llvm::vfs::OverlayFileSystem>(
302 llvm::vfs::getRealFileSystem());
303 OverlayVFS->pushOverlay(IMVFS);
304 CI->createFileManager(OverlayVFS);
305
306 auto Interp = Interpreter::create(std::move(CI));
307 if (auto E = Interp.takeError())
308 return std::move(E);
309
310 llvm::Error Err = llvm::Error::success();
311 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
312 **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
313 *(*Interp)->TSCtx->getContext(), IMVFS, Err);
314 if (Err)
315 return std::move(Err);
316
317 (*Interp)->DeviceParser = std::move(DeviceParser);
318
319 return Interp;
320}
321
323 return IncrParser->getCI();
324}
325
327 return IncrParser->getCI();
328}
329
331 if (!IncrExecutor) {
332 if (auto Err = CreateExecutor())
333 return std::move(Err);
334 }
335
336 return IncrExecutor->GetExecutionEngine();
337}
338
341}
342
345}
346
347void Interpreter::markUserCodeStart() {
348 assert(!InitPTUSize && "We only do this once");
349 InitPTUSize = IncrParser->getPTUs().size();
350}
351
352size_t Interpreter::getEffectivePTUSize() const {
353 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
354 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
355 return PTUs.size() - InitPTUSize;
356}
357
359Interpreter::Parse(llvm::StringRef Code) {
360 // If we have a device parser, parse it first.
361 // The generated code will be included in the host compilation
362 if (DeviceParser) {
363 auto DevicePTU = DeviceParser->Parse(Code);
364 if (auto E = DevicePTU.takeError())
365 return std::move(E);
366 }
367
368 // Tell the interpreter sliently ignore unused expressions since value
369 // printing could cause it.
371 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
372 return IncrParser->Parse(Code);
373}
374
376createJITTargetMachineBuilder(const std::string &TT) {
377 if (TT == llvm::sys::getProcessTriple())
378 // This fails immediately if the target backend is not registered
379 return llvm::orc::JITTargetMachineBuilder::detectHost();
380
381 // If the target backend is not registered, LLJITBuilder::create() will fail
382 return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
383}
384
388 if (!JTMB)
389 return JTMB.takeError();
390 return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
391}
392
394 if (IncrExecutor)
395 return llvm::make_error<llvm::StringError>("Operation failed. "
396 "Execution engine exists",
397 std::error_code());
400 if (!JB)
401 return JB.takeError();
402 llvm::Error Err = llvm::Error::success();
403 auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err);
404 if (!Err)
405 IncrExecutor = std::move(Executor);
406
407 return Err;
408}
409
410void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
411
413 assert(T.TheModule);
414 if (!IncrExecutor) {
415 auto Err = CreateExecutor();
416 if (Err)
417 return Err;
418 }
419 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
420 if (auto Err = IncrExecutor->addModule(T))
421 return Err;
422
423 if (auto Err = IncrExecutor->runCtors())
424 return Err;
425
426 return llvm::Error::success();
427}
428
429llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
430
431 auto PTU = Parse(Code);
432 if (!PTU)
433 return PTU.takeError();
434 if (PTU->TheModule)
435 if (llvm::Error Err = Execute(*PTU))
436 return Err;
437
438 if (LastValue.isValid()) {
439 if (!V) {
440 LastValue.dump();
441 LastValue.clear();
442 } else
443 *V = std::move(LastValue);
444 }
445 return llvm::Error::success();
446}
447
450 if (!IncrExecutor)
451 return llvm::make_error<llvm::StringError>("Operation failed. "
452 "No execution engine",
453 std::error_code());
454 llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
455 return getSymbolAddress(MangledName);
456}
457
459Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
460 if (!IncrExecutor)
461 return llvm::make_error<llvm::StringError>("Operation failed. "
462 "No execution engine",
463 std::error_code());
464
465 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
466}
467
470 if (!IncrExecutor)
471 return llvm::make_error<llvm::StringError>("Operation failed. "
472 "No execution engine",
473 std::error_code());
474
475 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
476}
477
478llvm::Error Interpreter::Undo(unsigned N) {
479
480 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
481 if (N > getEffectivePTUSize())
482 return llvm::make_error<llvm::StringError>("Operation failed. "
483 "Too many undos",
484 std::error_code());
485 for (unsigned I = 0; I < N; I++) {
486 if (IncrExecutor) {
487 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
488 return Err;
489 }
490
491 IncrParser->CleanUpPTU(PTUs.back());
492 PTUs.pop_back();
493 }
494 return llvm::Error::success();
495}
496
497llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
498 auto EE = getExecutionEngine();
499 if (!EE)
500 return EE.takeError();
501
502 auto &DL = EE->getDataLayout();
503
504 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
505 name, DL.getGlobalPrefix()))
506 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
507 else
508 return DLSG.takeError();
509
510 return llvm::Error::success();
511}
512
515 assert(CXXRD && "Cannot compile a destructor for a nullptr");
516 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
517 return Dtor->getSecond();
518
519 if (CXXRD->hasIrrelevantDestructor())
520 return llvm::orc::ExecutorAddr{};
521
522 CXXDestructorDecl *DtorRD =
524
525 llvm::StringRef Name =
526 IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
527 auto AddrOrErr = getSymbolAddress(Name);
528 if (!AddrOrErr)
529 return AddrOrErr.takeError();
530
531 Dtors[CXXRD] = *AddrOrErr;
532 return AddrOrErr;
533}
534
535static constexpr llvm::StringRef MagicRuntimeInterface[] = {
536 "__clang_Interpreter_SetValueNoAlloc",
537 "__clang_Interpreter_SetValueWithAlloc",
538 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
539
540static std::unique_ptr<RuntimeInterfaceBuilder>
542 Sema &S);
543
544std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() {
545 if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
546 return nullptr;
547
549 ASTContext &Ctx = S.getASTContext();
550
551 auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
552 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
554 RedeclarationKind::ForVisibleRedeclaration);
556 if (R.empty())
557 return false;
558
559 CXXScopeSpec CSS;
560 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
561 return true;
562 };
563
564 if (!LookupInterface(ValuePrintingInfo[NoAlloc],
566 return nullptr;
567 if (!LookupInterface(ValuePrintingInfo[WithAlloc],
569 return nullptr;
570 if (!LookupInterface(ValuePrintingInfo[CopyArray],
572 return nullptr;
573 if (!LookupInterface(ValuePrintingInfo[NewTag],
575 return nullptr;
576
577 return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S);
578}
579
580namespace {
581
582class InterfaceKindVisitor
583 : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> {
584 friend class InProcessRuntimeInterfaceBuilder;
585
586 ASTContext &Ctx;
587 Sema &S;
588 Expr *E;
590
591public:
592 InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E)
593 : Ctx(Ctx), S(S), E(E) {}
594
595 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
596 return Interpreter::InterfaceKind::WithAlloc;
597 }
598
600 VisitMemberPointerType(const MemberPointerType *Ty) {
601 return Interpreter::InterfaceKind::WithAlloc;
602 }
603
605 VisitConstantArrayType(const ConstantArrayType *Ty) {
606 return Interpreter::InterfaceKind::CopyArray;
607 }
608
610 VisitFunctionProtoType(const FunctionProtoType *Ty) {
611 HandlePtrType(Ty);
612 return Interpreter::InterfaceKind::NoAlloc;
613 }
614
615 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
616 HandlePtrType(Ty);
617 return Interpreter::InterfaceKind::NoAlloc;
618 }
619
620 Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
621 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
622 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
623 Args.push_back(AddrOfE.get());
624 return Interpreter::InterfaceKind::NoAlloc;
625 }
626
627 Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
628 if (Ty->isNullPtrType())
629 Args.push_back(E);
630 else if (Ty->isFloatingType())
631 Args.push_back(E);
632 else if (Ty->isIntegralOrEnumerationType())
633 HandleIntegralOrEnumType(Ty);
634 else if (Ty->isVoidType()) {
635 // Do we need to still run `E`?
636 }
637
638 return Interpreter::InterfaceKind::NoAlloc;
639 }
640
641 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
642 HandleIntegralOrEnumType(Ty);
643 return Interpreter::InterfaceKind::NoAlloc;
644 }
645
646private:
647 // Force cast these types to uint64 to reduce the number of overloads of
648 // `__clang_Interpreter_SetValueNoAlloc`.
649 void HandleIntegralOrEnumType(const Type *Ty) {
651 ExprResult CastedExpr =
653 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
654 Args.push_back(CastedExpr.get());
655 }
656
657 void HandlePtrType(const Type *Ty) {
659 ExprResult CastedExpr =
661 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
662 Args.push_back(CastedExpr.get());
663 }
664};
665
666class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
667 Interpreter &Interp;
668 ASTContext &Ctx;
669 Sema &S;
670
671public:
672 InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S)
673 : Interp(Interp), Ctx(C), S(S) {}
674
675 TransformExprFunction *getPrintValueTransformer() override {
676 return &transformForValuePrinting;
677 }
678
679private:
680 static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder,
681 Expr *E,
682 ArrayRef<Expr *> FixedArgs) {
683 auto *B = static_cast<InProcessRuntimeInterfaceBuilder *>(Builder);
684
685 // Get rid of ExprWithCleanups.
686 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
687 E = EWC->getSubExpr();
688
689 InterfaceKindVisitor Visitor(B->Ctx, B->S, E);
690
691 // The Interpreter* parameter and the out parameter `OutVal`.
692 for (Expr *E : FixedArgs)
693 Visitor.Args.push_back(E);
694
695 QualType Ty = E->getType();
696 QualType DesugaredTy = Ty.getDesugaredType(B->Ctx);
697
698 // For lvalue struct, we treat it as a reference.
699 if (DesugaredTy->isRecordType() && E->isLValue()) {
700 DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy);
701 Ty = B->Ctx.getLValueReferenceType(Ty);
702 }
703
704 Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy,
706 // The QualType parameter `OpaqueType`, represented as `void*`.
707 Visitor.Args.push_back(TypeArg);
708
709 // We push the last parameter based on the type of the Expr. Note we need
710 // special care for rvalue struct.
711 Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy);
712 switch (Kind) {
713 case Interpreter::InterfaceKind::WithAlloc:
714 case Interpreter::InterfaceKind::CopyArray: {
715 // __clang_Interpreter_SetValueWithAlloc.
716 ExprResult AllocCall = B->S.ActOnCallExpr(
717 /*Scope=*/nullptr,
718 B->Interp
719 .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
720 E->getBeginLoc(), Visitor.Args, E->getEndLoc());
721 assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
722
723 TypeSourceInfo *TSI =
724 B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
725
726 // Force CodeGen to emit destructor.
727 if (auto *RD = Ty->getAsCXXRecordDecl()) {
728 auto *Dtor = B->S.LookupDestructor(RD);
729 Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx));
730 B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
731 DeclGroupRef(Dtor));
732 }
733
734 // __clang_Interpreter_SetValueCopyArr.
735 if (Kind == Interpreter::InterfaceKind::CopyArray) {
736 const auto *ConstantArrTy =
737 cast<ConstantArrayType>(DesugaredTy.getTypePtr());
738 size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy);
739 Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize);
740 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
741 return B->S.ActOnCallExpr(
742 /*Scope *=*/nullptr,
743 B->Interp
744 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
745 SourceLocation(), Args, SourceLocation());
746 }
747 Expr *Args[] = {
748 AllocCall.get(),
749 B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
750 ExprResult CXXNewCall = B->S.BuildCXXNew(
751 E->getSourceRange(),
752 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
753 /*PlacementRParen=*/SourceLocation(),
754 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
755 E->getSourceRange(), E);
756
757 assert(!CXXNewCall.isInvalid() &&
758 "Can't create runtime placement new call!");
759
760 return B->S.ActOnFinishFullExpr(CXXNewCall.get(),
761 /*DiscardedValue=*/false);
762 }
763 // __clang_Interpreter_SetValueNoAlloc.
764 case Interpreter::InterfaceKind::NoAlloc: {
765 return B->S.ActOnCallExpr(
766 /*Scope=*/nullptr,
767 B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
768 E->getBeginLoc(), Visitor.Args, E->getEndLoc());
769 }
770 default:
771 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
772 }
773 }
774};
775} // namespace
776
777static std::unique_ptr<RuntimeInterfaceBuilder>
779 Sema &S) {
780 return std::make_unique<InProcessRuntimeInterfaceBuilder>(Interp, Ctx, S);
781}
782
783// This synthesizes a call expression to a speciall
784// function that is responsible for generating the Value.
785// In general, we transform:
786// clang-repl> x
787// To:
788// // 1. If x is a built-in type like int, float.
789// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
790// // 2. If x is a struct, and a lvalue.
791// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
792// &x);
793// // 3. If x is a struct, but a rvalue.
794// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
795// xQualType)) (x);
796
799 ASTContext &Ctx = S.getASTContext();
800
801 if (!RuntimeIB) {
802 RuntimeIB = FindRuntimeInterface();
803 AddPrintValueCall = RuntimeIB->getPrintValueTransformer();
804 }
805
806 assert(AddPrintValueCall &&
807 "We don't have a runtime interface for pretty print!");
808
809 // Create parameter `ThisInterp`.
810 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
811
812 // Create parameter `OutVal`.
813 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
814
815 // Build `__clang_Interpreter_SetValue*` call.
817 AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue});
818
819 // It could fail, like printing an array type in C. (not supported)
820 if (Result.isInvalid())
821 return E;
822 return Result.get();
823}
824
825// Temporary rvalue struct that need special care.
828 void *OpaqueType) {
829 Value &VRef = *(Value *)OutVal;
830 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
831 return VRef.getPtr();
832}
833
834// Pointers, lvalue struct that can take as a reference.
836__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
837 void *Val) {
838 Value &VRef = *(Value *)OutVal;
839 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
840 VRef.setPtr(Val);
841}
842
844__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
845 void *OpaqueType) {
846 Value &VRef = *(Value *)OutVal;
847 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
848}
849
850static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) {
851 QualType QT = V.getType();
852 if (const auto *ET = QT->getAs<EnumType>())
853 QT = ET->getDecl()->getIntegerType();
854
855 switch (QT->castAs<BuiltinType>()->getKind()) {
856 default:
857 llvm_unreachable("unknown type kind!");
858#define X(type, name) \
859 case BuiltinType::name: \
860 V.set##name(Data); \
861 break;
863#undef X
864 }
865}
866
868__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
869 unsigned long long Val) {
870 Value &VRef = *(Value *)OutVal;
871 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
873}
874
876__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
877 float Val) {
878 Value &VRef = *(Value *)OutVal;
879 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
880 VRef.setFloat(Val);
881}
882
884__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
885 double Val) {
886 Value &VRef = *(Value *)OutVal;
887 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
888 VRef.setDouble(Val);
889}
890
892__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
893 long double Val) {
894 Value &VRef = *(Value *)OutVal;
895 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
896 VRef.setLongDouble(Val);
897}
898
899// A trampoline to work around the fact that operator placement new cannot
900// really be forward declared due to libc++ and libstdc++ declaration mismatch.
901// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
902// definition in the interpreter runtime. We should move it in a runtime header
903// which gets included by the interpreter and here.
906operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
907 // Just forward to the standard operator placement new.
908 return operator new(__sz, __p);
909}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3273
CompileCommand Cmd
#define REPL_EXTERNAL_VISIBILITY
Definition: Value.h:72
#define REPL_BUILTIN_TYPES
Definition: Value.h:75
static std::unique_ptr< RuntimeInterfaceBuilder > createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, Sema &S)
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 llvm::Expected< llvm::orc::JITTargetMachineBuilder > createJITTargetMachineBuilder(const std::string &TT)
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
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:1073
CanQualType VoidPtrTy
Definition: ASTContext.h:1118
IdentifierTable & Idents
Definition: ASTContext.h:644
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:1102
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:2771
Kind getKind() const
Definition: Type.h:2813
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2796
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
TargetOptions & getTargetOpts()
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:3346
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:5365
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:277
QualType getType() const
Definition: Expr.h:142
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4446
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()
static llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB)
Provides top-level interfaces for incremental compilation and execution.
Definition: Interpreter.h:91
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(GlobalDecl GD) const
llvm::Error Execute(PartialTranslationUnit &T)
llvm::Expected< llvm::orc::LLJIT & > getExecutionEngine()
virtual ~Interpreter()
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
virtual llvm::Expected< std::unique_ptr< llvm::orc::LLJITBuilder > > CreateJITBuilder(CompilerInstance &CI)
llvm::Expected< llvm::orc::ExecutorAddr > CompileDtorCall(CXXRecordDecl *CXXRD)
llvm::Error LoadDynamicLibrary(const char *name)
Link a dynamic library.
virtual std::unique_ptr< RuntimeInterfaceBuilder > FindRuntimeInterface()
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V=nullptr)
Interpreter(std::unique_ptr< CompilerInstance > CI, llvm::Error &Err)
Expr * SynthesizeExpr(Expr *E)
llvm::Error CreateExecutor()
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
bool empty() const
Return true if no decls were found.
Definition: Lookup.h:362
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: Type.h:3250
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2929
A (possibly-)qualified type.
Definition: Type.h:738
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition: Type.h:1089
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7149
void * getAsOpaquePtr() const
Definition: Type.h:785
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5339
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3170
Generate glue code between the Interpreter's built-in runtime and user code.
Definition: Interpreter.h:81
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:457
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15746
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:7376
ASTContext & getASTContext() const
Definition: Sema.h:527
CXXDestructorDecl * LookupDestructor(CXXRecordDecl *Class)
Look for the destructor of the given class.
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3340
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
Definition: SemaExpr.cpp:3432
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
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
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
Definition: Targets.cpp:761
std::string Triple
The name of the target triple to compile for.
Definition: TargetOptions.h:29
void FlushDiagnostics(DiagnosticsEngine &Diags) const
FlushDiagnostics - Flush the buffered diagnostics to an given diagnostic engine.
A container of type source information.
Definition: Type.h:7120
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:7131
An operation on a type.
Definition: TypeVisitor.h:64
The base class of the type hierarchy.
Definition: Type.h:1607
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1870
bool isVoidType() const
Definition: Type.h:7695
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:7980
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:7810
bool isFloatingType() const
Definition: Type.cpp:2237
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7913
bool isNullPtrType() const
Definition: Type.h:7728
bool isRecordType() const
Definition: Type.h:7496
void dump() const
Definition: Value.cpp:256
void clear()
Definition: Value.cpp:218
void * getPtr() const
Definition: Value.cpp:229
bool isValid() const
Definition: Value.h:132
void setPtr(void *Ptr)
Definition: Value.h:141
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
const FunctionProtoType * T
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.