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#ifdef __EMSCRIPTEN__
19#include "Wasm.h"
20#endif // __EMSCRIPTEN__
21
23#include "clang/AST/Mangle.h"
31#include "clang/Driver/Driver.h"
32#include "clang/Driver/Job.h"
34#include "clang/Driver/Tool.h"
40#include "clang/Sema/Lookup.h"
41#include "llvm/ExecutionEngine/JITSymbol.h"
42#include "llvm/ExecutionEngine/Orc/LLJIT.h"
43#include "llvm/IR/Module.h"
44#include "llvm/Support/Errc.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/raw_ostream.h"
47#include "llvm/TargetParser/Host.h"
48
49#include <cstdarg>
50
51using namespace clang;
52
53// FIXME: Figure out how to unify with namespace init_convenience from
54// tools/clang-import-test/clang-import-test.cpp
55namespace {
56/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
57/// \returns NULL on error.
59GetCC1Arguments(DiagnosticsEngine *Diagnostics,
60 driver::Compilation *Compilation) {
61 // We expect to get back exactly one Command job, if we didn't something
62 // failed. Extract that job from the Compilation.
63 const driver::JobList &Jobs = Compilation->getJobs();
64 if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))
65 return llvm::createStringError(llvm::errc::not_supported,
66 "Driver initialization failed. "
67 "Unable to create a driver job");
68
69 // The one job we find should be to invoke clang again.
70 const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
71 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
72 return llvm::createStringError(llvm::errc::not_supported,
73 "Driver initialization failed");
74
75 return &Cmd->getArguments();
76}
77
79CreateCI(const llvm::opt::ArgStringList &Argv) {
80 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
82
83 // Register the support for object-file-wrapped Clang modules.
84 // FIXME: Clang should register these container operations automatically.
85 auto PCHOps = Clang->getPCHContainerOperations();
86 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
87 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
88
89 // Buffer diagnostics from argument parsing so that we can output them using
90 // a well formed diagnostic object.
93 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
95 Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);
96
97 // Infer the builtin include path if unspecified.
98 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
99 Clang->getHeaderSearchOpts().ResourceDir.empty())
100 Clang->getHeaderSearchOpts().ResourceDir =
101 CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
102
103 // Create the actual diagnostics engine.
104 Clang->createDiagnostics();
105 if (!Clang->hasDiagnostics())
106 return llvm::createStringError(llvm::errc::not_supported,
107 "Initialization failed. "
108 "Unable to create diagnostics engine");
109
110 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
111 if (!Success)
112 return llvm::createStringError(llvm::errc::not_supported,
113 "Initialization failed. "
114 "Unable to flush diagnostics");
115
116 // FIXME: Merge with CompilerInstance::ExecuteAction.
117 llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
118 Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
119
120 Clang->setTarget(TargetInfo::CreateTargetInfo(
121 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
122 if (!Clang->hasTarget())
123 return llvm::createStringError(llvm::errc::not_supported,
124 "Initialization failed. "
125 "Target is missing");
126
127 Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
128
129 // Don't clear the AST before backend codegen since we do codegen multiple
130 // times, reusing the same AST.
131 Clang->getCodeGenOpts().ClearASTBeforeBackend = false;
132
133 Clang->getFrontendOpts().DisableFree = false;
134 Clang->getCodeGenOpts().DisableFree = false;
135 return std::move(Clang);
136}
137
138} // anonymous namespace
139
141IncrementalCompilerBuilder::create(std::string TT,
142 std::vector<const char *> &ClangArgv) {
143
144 // If we don't know ClangArgv0 or the address of main() at this point, try
145 // to guess it anyway (it's possible on some platforms).
146 std::string MainExecutableName =
147 llvm::sys::fs::getMainExecutable(nullptr, nullptr);
148
149 ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
150
151 // Prepending -c to force the driver to do something if no action was
152 // specified. By prepending we allow users to override the default
153 // action and use other actions in incremental mode.
154 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
155 // We do C++ by default; append right after argv[0] if no "-x" given
156 ClangArgv.insert(ClangArgv.end(), "-Xclang");
157 ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
158 ClangArgv.insert(ClangArgv.end(), "-c");
159
160 // Put a dummy C++ file on to ensure there's at least one compile job for the
161 // driver to construct.
162 ClangArgv.push_back("<<< inputs >>>");
163
164 // Buffer diagnostics from argument parsing so that we can output them using a
165 // well formed diagnostic object.
168 CreateAndPopulateDiagOpts(ClangArgv);
170 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
171
172 driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
173 Driver.setCheckInputsExist(false); // the input comes from mem buffers
175 std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
176
177 if (Compilation->getArgs().hasArg(driver::options::OPT_v))
178 Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
179
180 auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
181 if (auto Err = ErrOrCC1Args.takeError())
182 return std::move(Err);
183
184 return CreateCI(**ErrOrCC1Args);
185}
186
189 std::vector<const char *> Argv;
190 Argv.reserve(5 + 1 + UserArgs.size());
191 Argv.push_back("-xc++");
192#ifdef __EMSCRIPTEN__
193 Argv.push_back("-target");
194 Argv.push_back("wasm32-unknown-emscripten");
195 Argv.push_back("-pie");
196 Argv.push_back("-shared");
197#endif
198 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
199
200 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
201 return IncrementalCompilerBuilder::create(TT, Argv);
202}
203
205IncrementalCompilerBuilder::createCuda(bool device) {
206 std::vector<const char *> Argv;
207 Argv.reserve(5 + 4 + UserArgs.size());
208
209 Argv.push_back("-xcuda");
210 if (device)
211 Argv.push_back("--cuda-device-only");
212 else
213 Argv.push_back("--cuda-host-only");
214
215 std::string SDKPathArg = "--cuda-path=";
216 if (!CudaSDKPath.empty()) {
217 SDKPathArg += CudaSDKPath;
218 Argv.push_back(SDKPathArg.c_str());
219 }
220
221 std::string ArchArg = "--offload-arch=";
222 if (!OffloadArch.empty()) {
223 ArchArg += OffloadArch;
224 Argv.push_back(ArchArg.c_str());
225 }
226
227 Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
228
229 std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
230 return IncrementalCompilerBuilder::create(TT, Argv);
231}
232
235 return IncrementalCompilerBuilder::createCuda(true);
236}
237
240 return IncrementalCompilerBuilder::createCuda(false);
241}
242
243Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
244 llvm::Error &ErrOut,
245 std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder)
246 : JITBuilder(std::move(JITBuilder)) {
247 llvm::ErrorAsOutParameter EAO(&ErrOut);
248 auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
249 TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
250 IncrParser = std::make_unique<IncrementalParser>(
251 *this, std::move(CI), *TSCtx->getContext(), ErrOut);
252 if (ErrOut)
253 return;
254
255 // Not all frontends support code-generation, e.g. ast-dump actions don't
256 if (IncrParser->getCodeGen()) {
257 if (llvm::Error Err = CreateExecutor()) {
258 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
259 return;
260 }
261
262 // Process the PTUs that came from initialization. For example -include will
263 // give us a header that's processed at initialization of the preprocessor.
264 for (PartialTranslationUnit &PTU : IncrParser->getPTUs())
265 if (llvm::Error Err = Execute(PTU)) {
266 ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
267 return;
268 }
269 }
270}
271
273 if (IncrExecutor) {
274 if (llvm::Error Err = IncrExecutor->cleanUp())
275 llvm::report_fatal_error(
276 llvm::Twine("Failed to clean up IncrementalExecutor: ") +
277 toString(std::move(Err)));
278 }
279}
280
281// These better to put in a runtime header but we can't. This is because we
282// can't find the precise resource directory in unittests so we have to hard
283// code them.
284const char *const Runtimes = R"(
285 #define __CLANG_REPL__ 1
286#ifdef __cplusplus
287 #define EXTERN_C extern "C"
288 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
289 struct __clang_Interpreter_NewTag{} __ci_newtag;
290 void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
291 template <class T, class = T (*)() /*disable for arrays*/>
292 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
293 for (auto Idx = 0; Idx < Size; ++Idx)
294 new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
295 }
296 template <class T, unsigned long N>
297 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
298 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
299 }
300#else
301 #define EXTERN_C extern
302#endif // __cplusplus
303
304 EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...);
305)";
306
308Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
309 llvm::Error Err = llvm::Error::success();
310 auto Interp =
311 std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
312 if (Err)
313 return std::move(Err);
314
315 // Add runtime code and set a marker to hide it from user code. Undo will not
316 // go through that.
317 auto PTU = Interp->Parse(Runtimes);
318 if (!PTU)
319 return PTU.takeError();
320 Interp->markUserCodeStart();
321
322 Interp->ValuePrintingInfo.resize(4);
323 return std::move(Interp);
324}
325
327Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
328 std::unique_ptr<CompilerInstance> DCI) {
329 // avoid writing fat binary to disk using an in-memory virtual file system
331 std::make_unique<llvm::vfs::InMemoryFileSystem>();
333 std::make_unique<llvm::vfs::OverlayFileSystem>(
334 llvm::vfs::getRealFileSystem());
335 OverlayVFS->pushOverlay(IMVFS);
336 CI->createFileManager(OverlayVFS);
337
338 auto Interp = Interpreter::create(std::move(CI));
339 if (auto E = Interp.takeError())
340 return std::move(E);
341
342 llvm::Error Err = llvm::Error::success();
343 auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
344 **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
345 *(*Interp)->TSCtx->getContext(), IMVFS, Err);
346 if (Err)
347 return std::move(Err);
348
349 (*Interp)->DeviceParser = std::move(DeviceParser);
350
351 return Interp;
352}
353
355 return IncrParser->getCI();
356}
357
359 return IncrParser->getCI();
360}
361
363 if (!IncrExecutor) {
364 if (auto Err = CreateExecutor())
365 return std::move(Err);
366 }
367
368 return IncrExecutor->GetExecutionEngine();
369}
370
373}
374
377}
378
379void Interpreter::markUserCodeStart() {
380 assert(!InitPTUSize && "We only do this once");
381 InitPTUSize = IncrParser->getPTUs().size();
382}
383
384size_t Interpreter::getEffectivePTUSize() const {
385 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
386 assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
387 return PTUs.size() - InitPTUSize;
388}
389
391Interpreter::Parse(llvm::StringRef Code) {
392 // If we have a device parser, parse it first.
393 // The generated code will be included in the host compilation
394 if (DeviceParser) {
395 auto DevicePTU = DeviceParser->Parse(Code);
396 if (auto E = DevicePTU.takeError())
397 return std::move(E);
398 }
399
400 // Tell the interpreter sliently ignore unused expressions since value
401 // printing could cause it.
403 clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
404 return IncrParser->Parse(Code);
405}
406
408createJITTargetMachineBuilder(const std::string &TT) {
409 if (TT == llvm::sys::getProcessTriple())
410 // This fails immediately if the target backend is not registered
411 return llvm::orc::JITTargetMachineBuilder::detectHost();
412
413 // If the target backend is not registered, LLJITBuilder::create() will fail
414 return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
415}
416
418 if (IncrExecutor)
419 return llvm::make_error<llvm::StringError>("Operation failed. "
420 "Execution engine exists",
421 std::error_code());
422 if (!IncrParser->getCodeGen())
423 return llvm::make_error<llvm::StringError>("Operation failed. "
424 "No code generator available",
425 std::error_code());
426 if (!JITBuilder) {
427 const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
428 auto JTMB = createJITTargetMachineBuilder(TT);
429 if (!JTMB)
430 return JTMB.takeError();
431 auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
432 if (!JB)
433 return JB.takeError();
434 JITBuilder = std::move(*JB);
435 }
436
437 llvm::Error Err = llvm::Error::success();
438#ifdef __EMSCRIPTEN__
439 auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
440#else
441 auto Executor =
442 std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
443#endif
444 if (!Err)
445 IncrExecutor = std::move(Executor);
446
447 return Err;
448}
449
450void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
451
453 assert(T.TheModule);
454 if (!IncrExecutor) {
455 auto Err = CreateExecutor();
456 if (Err)
457 return Err;
458 }
459 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
460 if (auto Err = IncrExecutor->addModule(T))
461 return Err;
462
463 if (auto Err = IncrExecutor->runCtors())
464 return Err;
465
466 return llvm::Error::success();
467}
468
469llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
470
471 auto PTU = Parse(Code);
472 if (!PTU)
473 return PTU.takeError();
474 if (PTU->TheModule)
475 if (llvm::Error Err = Execute(*PTU))
476 return Err;
477
478 if (LastValue.isValid()) {
479 if (!V) {
480 LastValue.dump();
481 LastValue.clear();
482 } else
483 *V = std::move(LastValue);
484 }
485 return llvm::Error::success();
486}
487
490 if (!IncrExecutor)
491 return llvm::make_error<llvm::StringError>("Operation failed. "
492 "No execution engine",
493 std::error_code());
494 llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
495 return getSymbolAddress(MangledName);
496}
497
499Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
500 if (!IncrExecutor)
501 return llvm::make_error<llvm::StringError>("Operation failed. "
502 "No execution engine",
503 std::error_code());
504
505 return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
506}
507
510 if (!IncrExecutor)
511 return llvm::make_error<llvm::StringError>("Operation failed. "
512 "No execution engine",
513 std::error_code());
514
515 return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
516}
517
518llvm::Error Interpreter::Undo(unsigned N) {
519
520 std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
521 if (N > getEffectivePTUSize())
522 return llvm::make_error<llvm::StringError>("Operation failed. "
523 "Too many undos",
524 std::error_code());
525 for (unsigned I = 0; I < N; I++) {
526 if (IncrExecutor) {
527 if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
528 return Err;
529 }
530
531 IncrParser->CleanUpPTU(PTUs.back());
532 PTUs.pop_back();
533 }
534 return llvm::Error::success();
535}
536
537llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
538 auto EE = getExecutionEngine();
539 if (!EE)
540 return EE.takeError();
541
542 auto &DL = EE->getDataLayout();
543
544 if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
545 name, DL.getGlobalPrefix()))
546 EE->getMainJITDylib().addGenerator(std::move(*DLSG));
547 else
548 return DLSG.takeError();
549
550 return llvm::Error::success();
551}
552
555 assert(CXXRD && "Cannot compile a destructor for a nullptr");
556 if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
557 return Dtor->getSecond();
558
559 if (CXXRD->hasIrrelevantDestructor())
560 return llvm::orc::ExecutorAddr{};
561
562 CXXDestructorDecl *DtorRD =
564
565 llvm::StringRef Name =
566 IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
567 auto AddrOrErr = getSymbolAddress(Name);
568 if (!AddrOrErr)
569 return AddrOrErr.takeError();
570
571 Dtors[CXXRD] = *AddrOrErr;
572 return AddrOrErr;
573}
574
575static constexpr llvm::StringRef MagicRuntimeInterface[] = {
576 "__clang_Interpreter_SetValueNoAlloc",
577 "__clang_Interpreter_SetValueWithAlloc",
578 "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
579
580static std::unique_ptr<RuntimeInterfaceBuilder>
582 Sema &S);
583
584std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() {
585 if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
586 return nullptr;
587
589 ASTContext &Ctx = S.getASTContext();
590
591 auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
592 LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
594 RedeclarationKind::ForVisibleRedeclaration);
596 if (R.empty())
597 return false;
598
599 CXXScopeSpec CSS;
600 Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
601 return true;
602 };
603
604 if (!LookupInterface(ValuePrintingInfo[NoAlloc],
606 return nullptr;
607 if (Ctx.getLangOpts().CPlusPlus) {
608 if (!LookupInterface(ValuePrintingInfo[WithAlloc],
610 return nullptr;
611 if (!LookupInterface(ValuePrintingInfo[CopyArray],
613 return nullptr;
614 if (!LookupInterface(ValuePrintingInfo[NewTag],
616 return nullptr;
617 }
618
619 return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S);
620}
621
622namespace {
623
624class InterfaceKindVisitor
625 : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> {
626 friend class InProcessRuntimeInterfaceBuilder;
627
628 ASTContext &Ctx;
629 Sema &S;
630 Expr *E;
632
633public:
634 InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E)
635 : Ctx(Ctx), S(S), E(E) {}
636
637 Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
638 return Interpreter::InterfaceKind::WithAlloc;
639 }
640
642 VisitMemberPointerType(const MemberPointerType *Ty) {
643 return Interpreter::InterfaceKind::WithAlloc;
644 }
645
647 VisitConstantArrayType(const ConstantArrayType *Ty) {
648 return Interpreter::InterfaceKind::CopyArray;
649 }
650
652 VisitFunctionProtoType(const FunctionProtoType *Ty) {
653 HandlePtrType(Ty);
654 return Interpreter::InterfaceKind::NoAlloc;
655 }
656
657 Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
658 HandlePtrType(Ty);
659 return Interpreter::InterfaceKind::NoAlloc;
660 }
661
662 Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
663 ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
664 assert(!AddrOfE.isInvalid() && "Can not create unary expression");
665 Args.push_back(AddrOfE.get());
666 return Interpreter::InterfaceKind::NoAlloc;
667 }
668
669 Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
670 if (Ty->isNullPtrType())
671 Args.push_back(E);
672 else if (Ty->isFloatingType())
673 Args.push_back(E);
674 else if (Ty->isIntegralOrEnumerationType())
675 HandleIntegralOrEnumType(Ty);
676 else if (Ty->isVoidType()) {
677 // Do we need to still run `E`?
678 }
679
680 return Interpreter::InterfaceKind::NoAlloc;
681 }
682
683 Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
684 HandleIntegralOrEnumType(Ty);
685 return Interpreter::InterfaceKind::NoAlloc;
686 }
687
688private:
689 // Force cast these types to the uint that fits the register size. That way we
690 // reduce the number of overloads of `__clang_Interpreter_SetValueNoAlloc`.
691 void HandleIntegralOrEnumType(const Type *Ty) {
692 uint64_t PtrBits = Ctx.getTypeSize(Ctx.VoidPtrTy);
693 QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, PtrBits);
694 TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(UIntTy);
695 ExprResult CastedExpr =
697 assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
698 Args.push_back(CastedExpr.get());
699 }
700
701 void HandlePtrType(const Type *Ty) {
703 ExprResult CastedExpr =
705 assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
706 Args.push_back(CastedExpr.get());
707 }
708};
709
710class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
711 Interpreter &Interp;
712 ASTContext &Ctx;
713 Sema &S;
714
715public:
716 InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S)
717 : Interp(Interp), Ctx(C), S(S) {}
718
719 TransformExprFunction *getPrintValueTransformer() override {
720 return &transformForValuePrinting;
721 }
722
723private:
724 static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder,
725 Expr *E,
726 ArrayRef<Expr *> FixedArgs) {
727 auto *B = static_cast<InProcessRuntimeInterfaceBuilder *>(Builder);
728
729 // Get rid of ExprWithCleanups.
730 if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
731 E = EWC->getSubExpr();
732
733 InterfaceKindVisitor Visitor(B->Ctx, B->S, E);
734
735 // The Interpreter* parameter and the out parameter `OutVal`.
736 for (Expr *E : FixedArgs)
737 Visitor.Args.push_back(E);
738
739 QualType Ty = E->getType();
740 QualType DesugaredTy = Ty.getDesugaredType(B->Ctx);
741
742 // For lvalue struct, we treat it as a reference.
743 if (DesugaredTy->isRecordType() && E->isLValue()) {
744 DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy);
745 Ty = B->Ctx.getLValueReferenceType(Ty);
746 }
747
748 Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy,
750 // The QualType parameter `OpaqueType`, represented as `void*`.
751 Visitor.Args.push_back(TypeArg);
752
753 // We push the last parameter based on the type of the Expr. Note we need
754 // special care for rvalue struct.
755 Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy);
756 switch (Kind) {
757 case Interpreter::InterfaceKind::WithAlloc:
758 case Interpreter::InterfaceKind::CopyArray: {
759 // __clang_Interpreter_SetValueWithAlloc.
760 ExprResult AllocCall = B->S.ActOnCallExpr(
761 /*Scope=*/nullptr,
762 B->Interp
763 .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
764 E->getBeginLoc(), Visitor.Args, E->getEndLoc());
765 assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
766
767 TypeSourceInfo *TSI =
768 B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
769
770 // Force CodeGen to emit destructor.
771 if (auto *RD = Ty->getAsCXXRecordDecl()) {
772 auto *Dtor = B->S.LookupDestructor(RD);
773 Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx));
774 B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
775 DeclGroupRef(Dtor));
776 }
777
778 // __clang_Interpreter_SetValueCopyArr.
779 if (Kind == Interpreter::InterfaceKind::CopyArray) {
780 const auto *ConstantArrTy =
781 cast<ConstantArrayType>(DesugaredTy.getTypePtr());
782 size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy);
783 Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize);
784 Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
785 return B->S.ActOnCallExpr(
786 /*Scope *=*/nullptr,
787 B->Interp
788 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
789 SourceLocation(), Args, SourceLocation());
790 }
791 Expr *Args[] = {
792 AllocCall.get(),
793 B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
794 ExprResult CXXNewCall = B->S.BuildCXXNew(
795 E->getSourceRange(),
796 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
797 /*PlacementRParen=*/SourceLocation(),
798 /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
799 E->getSourceRange(), E);
800
801 assert(!CXXNewCall.isInvalid() &&
802 "Can't create runtime placement new call!");
803
804 return B->S.ActOnFinishFullExpr(CXXNewCall.get(),
805 /*DiscardedValue=*/false);
806 }
807 // __clang_Interpreter_SetValueNoAlloc.
808 case Interpreter::InterfaceKind::NoAlloc: {
809 return B->S.ActOnCallExpr(
810 /*Scope=*/nullptr,
811 B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
812 E->getBeginLoc(), Visitor.Args, E->getEndLoc());
813 }
814 default:
815 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
816 }
817 }
818};
819} // namespace
820
821static std::unique_ptr<RuntimeInterfaceBuilder>
823 Sema &S) {
824 return std::make_unique<InProcessRuntimeInterfaceBuilder>(Interp, Ctx, S);
825}
826
827// This synthesizes a call expression to a speciall
828// function that is responsible for generating the Value.
829// In general, we transform:
830// clang-repl> x
831// To:
832// // 1. If x is a built-in type like int, float.
833// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
834// // 2. If x is a struct, and a lvalue.
835// __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
836// &x);
837// // 3. If x is a struct, but a rvalue.
838// new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
839// xQualType)) (x);
840
843 ASTContext &Ctx = S.getASTContext();
844
845 if (!RuntimeIB) {
846 RuntimeIB = FindRuntimeInterface();
847 AddPrintValueCall = RuntimeIB->getPrintValueTransformer();
848 }
849
850 assert(AddPrintValueCall &&
851 "We don't have a runtime interface for pretty print!");
852
853 // Create parameter `ThisInterp`.
854 auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
855
856 // Create parameter `OutVal`.
857 auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
858
859 // Build `__clang_Interpreter_SetValue*` call.
861 AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue});
862
863 // It could fail, like printing an array type in C. (not supported)
864 if (Result.isInvalid())
865 return E;
866 return Result.get();
867}
868
869// Temporary rvalue struct that need special care.
872 void *OpaqueType) {
873 Value &VRef = *(Value *)OutVal;
874 VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
875 return VRef.getPtr();
876}
877
879 void *This, void *OutVal, void *OpaqueType, ...) {
880 Value &VRef = *(Value *)OutVal;
881 Interpreter *I = static_cast<Interpreter *>(This);
882 VRef = Value(I, OpaqueType);
883 if (VRef.isVoid())
884 return;
885
886 va_list args;
887 va_start(args, /*last named param*/ OpaqueType);
888
889 QualType QT = VRef.getType();
890 if (VRef.getKind() == Value::K_PtrOrObj) {
891 VRef.setPtr(va_arg(args, void *));
892 } else {
893 if (const auto *ET = QT->getAs<EnumType>())
894 QT = ET->getDecl()->getIntegerType();
895 switch (QT->castAs<BuiltinType>()->getKind()) {
896 default:
897 llvm_unreachable("unknown type kind!");
898 break;
899 // Types shorter than int are resolved as int, else va_arg has UB.
900 case BuiltinType::Bool:
901 VRef.setBool(va_arg(args, int));
902 break;
903 case BuiltinType::Char_S:
904 VRef.setChar_S(va_arg(args, int));
905 break;
906 case BuiltinType::SChar:
907 VRef.setSChar(va_arg(args, int));
908 break;
909 case BuiltinType::Char_U:
910 VRef.setChar_U(va_arg(args, unsigned));
911 break;
912 case BuiltinType::UChar:
913 VRef.setUChar(va_arg(args, unsigned));
914 break;
915 case BuiltinType::Short:
916 VRef.setShort(va_arg(args, int));
917 break;
918 case BuiltinType::UShort:
919 VRef.setUShort(va_arg(args, unsigned));
920 break;
921 case BuiltinType::Int:
922 VRef.setInt(va_arg(args, int));
923 break;
924 case BuiltinType::UInt:
925 VRef.setUInt(va_arg(args, unsigned));
926 break;
927 case BuiltinType::Long:
928 VRef.setLong(va_arg(args, long));
929 break;
930 case BuiltinType::ULong:
931 VRef.setULong(va_arg(args, unsigned long));
932 break;
933 case BuiltinType::LongLong:
934 VRef.setLongLong(va_arg(args, long long));
935 break;
936 case BuiltinType::ULongLong:
937 VRef.setULongLong(va_arg(args, unsigned long long));
938 break;
939 // Types shorter than double are resolved as double, else va_arg has UB.
940 case BuiltinType::Float:
941 VRef.setFloat(va_arg(args, double));
942 break;
943 case BuiltinType::Double:
944 VRef.setDouble(va_arg(args, double));
945 break;
946 case BuiltinType::LongDouble:
947 VRef.setLongDouble(va_arg(args, long double));
948 break;
949 // See REPL_BUILTIN_TYPES.
950 }
951 }
952 va_end(args);
953}
954
955// A trampoline to work around the fact that operator placement new cannot
956// really be forward declared due to libc++ and libstdc++ declaration mismatch.
957// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
958// definition in the interpreter runtime. We should move it in a runtime header
959// which gets included by the interpreter and here.
962operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
963 // Just forward to the standard operator placement new.
964 return operator new(__sz, __p);
965}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3323
enum clang::sema::@1650::IndirectLocalPathEntry::EntryKind Kind
Expr * E
CompileCommand Cmd
#define REPL_EXTERNAL_VISIBILITY
Definition: Value.h:72
static std::unique_ptr< RuntimeInterfaceBuilder > createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, Sema &S)
const char *const Runtimes
REPL_EXTERNAL_VISIBILITY void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc(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.
#define va_arg(ap, type)
#define va_start(ap, param)
#define va_end(ap)
__builtin_va_list va_list
static __inline__ uint32_t volatile uint32_t * __p
Definition: arm_acle.h:88
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:186
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1091
CanQualType VoidPtrTy
Definition: ASTContext.h:1136
IdentifierTable & Idents
Definition: ASTContext.h:656
const LangOptions & getLangOpts() const
Definition: ASTContext.h:787
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2382
QualType getBitIntType(bool Unsigned, unsigned NumBits) const
Return a bit-precise integer type with the specified signedness and bit count.
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:2997
Kind getKind() const
Definition: Type.h:3042
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2799
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:1403
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
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:3575
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:5963
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:4971
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
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)
Expr * SynthesizeExpr(Expr *E)
llvm::Error CreateExecutor()
Interpreter(std::unique_ptr< CompilerInstance > CI, llvm::Error &Err, std::unique_ptr< llvm::orc::LLJITBuilder > JITBuilder=nullptr)
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:3479
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3158
A (possibly-)qualified type.
Definition: Type.h:942
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition: Type.h:1304
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7744
void * getAsOpaquePtr() const
Definition: Type.h:989
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5937
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3399
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:535
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15227
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:8997
ASTContext & getASTContext() const
Definition: Sema.h:600
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:3341
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)
Definition: SemaExpr.cpp:3155
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:764
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:7715
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:7726
An operation on a type.
Definition: TypeVisitor.h:64
The base class of the type hierarchy.
Definition: Type.h:1826
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1881
bool isVoidType() const
Definition: Type.h:8296
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8584
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8411
bool isFloatingType() const
Definition: Type.cpp:2248
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8517
bool isNullPtrType() const
Definition: Type.h:8329
bool isRecordType() const
Definition: Type.h:8093
QualType getType() const
Definition: Value.cpp:234
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
@ K_PtrOrObj
Definition: Value.h:108
Kind getKind() const
Definition: Value.h:136
bool isVoid() const
Definition: Value.h:133
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)
OffloadArch
Definition: Cuda.h:55
@ 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.
unsigned long uint64_t
__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.