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