1 //===------ Interpreter.cpp - Incremental Compilation and Execution -------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the component which performs incremental code
10 // compilation and execution.
12 //===----------------------------------------------------------------------===//
14 #include "DeviceOffload.h"
15 #include "IncrementalExecutor.h"
16 #include "IncrementalParser.h"
17 #include "InterpreterUtils.h"
19 #include "clang/AST/ASTContext.h"
20 #include "clang/AST/Mangle.h"
21 #include "clang/AST/TypeVisitor.h"
22 #include "clang/Basic/DiagnosticSema.h"
23 #include "clang/Basic/TargetInfo.h"
24 #include "clang/CodeGen/CodeGenAction.h"
25 #include "clang/CodeGen/ModuleBuilder.h"
26 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
27 #include "clang/Driver/Compilation.h"
28 #include "clang/Driver/Driver.h"
29 #include "clang/Driver/Job.h"
30 #include "clang/Driver/Options.h"
31 #include "clang/Driver/Tool.h"
32 #include "clang/Frontend/CompilerInstance.h"
33 #include "clang/Frontend/TextDiagnosticBuffer.h"
34 #include "clang/Interpreter/Interpreter.h"
35 #include "clang/Interpreter/Value.h"
36 #include "clang/Lex/PreprocessorOptions.h"
37 #include "clang/Sema/Lookup.h"
38 #include "llvm/ExecutionEngine/JITSymbol.h"
39 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
40 #include "llvm/IR/Module.h"
41 #include "llvm/Support/Errc.h"
42 #include "llvm/Support/ErrorHandling.h"
43 #include "llvm/Support/raw_ostream.h"
44 #include "llvm/TargetParser/Host.h"
45 using namespace clang
;
47 // FIXME: Figure out how to unify with namespace init_convenience from
48 // tools/clang-import-test/clang-import-test.cpp
50 /// Retrieves the clang CC1 specific flags out of the compilation's jobs.
51 /// \returns NULL on error.
52 static llvm::Expected
<const llvm::opt::ArgStringList
*>
53 GetCC1Arguments(DiagnosticsEngine
*Diagnostics
,
54 driver::Compilation
*Compilation
) {
55 // We expect to get back exactly one Command job, if we didn't something
56 // failed. Extract that job from the Compilation.
57 const driver::JobList
&Jobs
= Compilation
->getJobs();
58 if (!Jobs
.size() || !isa
<driver::Command
>(*Jobs
.begin()))
59 return llvm::createStringError(llvm::errc::not_supported
,
60 "Driver initialization failed. "
61 "Unable to create a driver job");
63 // The one job we find should be to invoke clang again.
64 const driver::Command
*Cmd
= cast
<driver::Command
>(&(*Jobs
.begin()));
65 if (llvm::StringRef(Cmd
->getCreator().getName()) != "clang")
66 return llvm::createStringError(llvm::errc::not_supported
,
67 "Driver initialization failed");
69 return &Cmd
->getArguments();
72 static llvm::Expected
<std::unique_ptr
<CompilerInstance
>>
73 CreateCI(const llvm::opt::ArgStringList
&Argv
) {
74 std::unique_ptr
<CompilerInstance
> Clang(new CompilerInstance());
75 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
77 // Register the support for object-file-wrapped Clang modules.
78 // FIXME: Clang should register these container operations automatically.
79 auto PCHOps
= Clang
->getPCHContainerOperations();
80 PCHOps
->registerWriter(std::make_unique
<ObjectFilePCHContainerWriter
>());
81 PCHOps
->registerReader(std::make_unique
<ObjectFilePCHContainerReader
>());
83 // Buffer diagnostics from argument parsing so that we can output them using
84 // a well formed diagnostic object.
85 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
86 TextDiagnosticBuffer
*DiagsBuffer
= new TextDiagnosticBuffer
;
87 DiagnosticsEngine
Diags(DiagID
, &*DiagOpts
, DiagsBuffer
);
88 bool Success
= CompilerInvocation::CreateFromArgs(
89 Clang
->getInvocation(), llvm::ArrayRef(Argv
.begin(), Argv
.size()), Diags
);
91 // Infer the builtin include path if unspecified.
92 if (Clang
->getHeaderSearchOpts().UseBuiltinIncludes
&&
93 Clang
->getHeaderSearchOpts().ResourceDir
.empty())
94 Clang
->getHeaderSearchOpts().ResourceDir
=
95 CompilerInvocation::GetResourcesPath(Argv
[0], nullptr);
97 // Create the actual diagnostics engine.
98 Clang
->createDiagnostics();
99 if (!Clang
->hasDiagnostics())
100 return llvm::createStringError(llvm::errc::not_supported
,
101 "Initialization failed. "
102 "Unable to create diagnostics engine");
104 DiagsBuffer
->FlushDiagnostics(Clang
->getDiagnostics());
106 return llvm::createStringError(llvm::errc::not_supported
,
107 "Initialization failed. "
108 "Unable to flush diagnostics");
110 // FIXME: Merge with CompilerInstance::ExecuteAction.
111 llvm::MemoryBuffer
*MB
= llvm::MemoryBuffer::getMemBuffer("").release();
112 Clang
->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB
);
114 Clang
->setTarget(TargetInfo::CreateTargetInfo(
115 Clang
->getDiagnostics(), Clang
->getInvocation().TargetOpts
));
116 if (!Clang
->hasTarget())
117 return llvm::createStringError(llvm::errc::not_supported
,
118 "Initialization failed. "
119 "Target is missing");
121 Clang
->getTarget().adjust(Clang
->getDiagnostics(), Clang
->getLangOpts());
123 // Don't clear the AST before backend codegen since we do codegen multiple
124 // times, reusing the same AST.
125 Clang
->getCodeGenOpts().ClearASTBeforeBackend
= false;
127 Clang
->getFrontendOpts().DisableFree
= false;
128 Clang
->getCodeGenOpts().DisableFree
= false;
129 return std::move(Clang
);
132 } // anonymous namespace
134 llvm::Expected
<std::unique_ptr
<CompilerInstance
>>
135 IncrementalCompilerBuilder::create(std::vector
<const char *> &ClangArgv
) {
137 // If we don't know ClangArgv0 or the address of main() at this point, try
138 // to guess it anyway (it's possible on some platforms).
139 std::string MainExecutableName
=
140 llvm::sys::fs::getMainExecutable(nullptr, nullptr);
142 ClangArgv
.insert(ClangArgv
.begin(), MainExecutableName
.c_str());
144 // Prepending -c to force the driver to do something if no action was
145 // specified. By prepending we allow users to override the default
146 // action and use other actions in incremental mode.
147 // FIXME: Print proper driver diagnostics if the driver flags are wrong.
148 // We do C++ by default; append right after argv[0] if no "-x" given
149 ClangArgv
.insert(ClangArgv
.end(), "-Xclang");
150 ClangArgv
.insert(ClangArgv
.end(), "-fincremental-extensions");
151 ClangArgv
.insert(ClangArgv
.end(), "-c");
153 // Put a dummy C++ file on to ensure there's at least one compile job for the
154 // driver to construct.
155 ClangArgv
.push_back("<<< inputs >>>");
157 // Buffer diagnostics from argument parsing so that we can output them using a
158 // well formed diagnostic object.
159 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
160 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
=
161 CreateAndPopulateDiagOpts(ClangArgv
);
162 TextDiagnosticBuffer
*DiagsBuffer
= new TextDiagnosticBuffer
;
163 DiagnosticsEngine
Diags(DiagID
, &*DiagOpts
, DiagsBuffer
);
165 driver::Driver
Driver(/*MainBinaryName=*/ClangArgv
[0],
166 llvm::sys::getProcessTriple(), Diags
);
167 Driver
.setCheckInputsExist(false); // the input comes from mem buffers
168 llvm::ArrayRef
<const char *> RF
= llvm::ArrayRef(ClangArgv
);
169 std::unique_ptr
<driver::Compilation
> Compilation(Driver
.BuildCompilation(RF
));
171 if (Compilation
->getArgs().hasArg(driver::options::OPT_v
))
172 Compilation
->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
174 auto ErrOrCC1Args
= GetCC1Arguments(&Diags
, Compilation
.get());
175 if (auto Err
= ErrOrCC1Args
.takeError())
176 return std::move(Err
);
178 return CreateCI(**ErrOrCC1Args
);
181 llvm::Expected
<std::unique_ptr
<CompilerInstance
>>
182 IncrementalCompilerBuilder::CreateCpp() {
183 std::vector
<const char *> Argv
;
184 Argv
.reserve(5 + 1 + UserArgs
.size());
185 Argv
.push_back("-xc++");
186 Argv
.insert(Argv
.end(), UserArgs
.begin(), UserArgs
.end());
188 return IncrementalCompilerBuilder::create(Argv
);
191 llvm::Expected
<std::unique_ptr
<CompilerInstance
>>
192 IncrementalCompilerBuilder::createCuda(bool device
) {
193 std::vector
<const char *> Argv
;
194 Argv
.reserve(5 + 4 + UserArgs
.size());
196 Argv
.push_back("-xcuda");
198 Argv
.push_back("--cuda-device-only");
200 Argv
.push_back("--cuda-host-only");
202 std::string SDKPathArg
= "--cuda-path=";
203 if (!CudaSDKPath
.empty()) {
204 SDKPathArg
+= CudaSDKPath
;
205 Argv
.push_back(SDKPathArg
.c_str());
208 std::string ArchArg
= "--offload-arch=";
209 if (!OffloadArch
.empty()) {
210 ArchArg
+= OffloadArch
;
211 Argv
.push_back(ArchArg
.c_str());
214 Argv
.insert(Argv
.end(), UserArgs
.begin(), UserArgs
.end());
216 return IncrementalCompilerBuilder::create(Argv
);
219 llvm::Expected
<std::unique_ptr
<CompilerInstance
>>
220 IncrementalCompilerBuilder::CreateCudaDevice() {
221 return IncrementalCompilerBuilder::createCuda(true);
224 llvm::Expected
<std::unique_ptr
<CompilerInstance
>>
225 IncrementalCompilerBuilder::CreateCudaHost() {
226 return IncrementalCompilerBuilder::createCuda(false);
229 Interpreter::Interpreter(std::unique_ptr
<CompilerInstance
> CI
,
231 llvm::ErrorAsOutParameter
EAO(&Err
);
232 auto LLVMCtx
= std::make_unique
<llvm::LLVMContext
>();
233 TSCtx
= std::make_unique
<llvm::orc::ThreadSafeContext
>(std::move(LLVMCtx
));
234 IncrParser
= std::make_unique
<IncrementalParser
>(*this, std::move(CI
),
235 *TSCtx
->getContext(), Err
);
238 Interpreter::~Interpreter() {
240 if (llvm::Error Err
= IncrExecutor
->cleanUp())
241 llvm::report_fatal_error(
242 llvm::Twine("Failed to clean up IncrementalExecutor: ") +
243 toString(std::move(Err
)));
247 // These better to put in a runtime header but we can't. This is because we
248 // can't find the precise resource directory in unittests so we have to hard
250 const char *const Runtimes
= R
"(
251 void* operator new(__SIZE_TYPE__, void* __p) noexcept;
252 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
253 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
254 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
255 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
256 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
257 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
258 void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
259 template <class T, class = T (*)() /*disable for arrays*/>
260 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
261 for (auto Idx = 0; Idx < Size; ++Idx)
262 new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]);
264 template <class T, unsigned long N>
265 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
266 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
270 llvm::Expected
<std::unique_ptr
<Interpreter
>>
271 Interpreter::create(std::unique_ptr
<CompilerInstance
> CI
) {
272 llvm::Error Err
= llvm::Error::success();
274 std::unique_ptr
<Interpreter
>(new Interpreter(std::move(CI
), Err
));
276 return std::move(Err
);
278 auto PTU
= Interp
->Parse(Runtimes
);
280 return PTU
.takeError();
282 Interp
->ValuePrintingInfo
.resize(3);
283 // FIXME: This is a ugly hack. Undo command checks its availability by looking
284 // at the size of the PTU list. However we have parsed something in the
285 // beginning of the REPL so we have to mark them as 'Irrevocable'.
286 Interp
->InitPTUSize
= Interp
->IncrParser
->getPTUs().size();
287 return std::move(Interp
);
290 llvm::Expected
<std::unique_ptr
<Interpreter
>>
291 Interpreter::createWithCUDA(std::unique_ptr
<CompilerInstance
> CI
,
292 std::unique_ptr
<CompilerInstance
> DCI
) {
293 // avoid writing fat binary to disk using an in-memory virtual file system
294 llvm::IntrusiveRefCntPtr
<llvm::vfs::InMemoryFileSystem
> IMVFS
=
295 std::make_unique
<llvm::vfs::InMemoryFileSystem
>();
296 llvm::IntrusiveRefCntPtr
<llvm::vfs::OverlayFileSystem
> OverlayVFS
=
297 std::make_unique
<llvm::vfs::OverlayFileSystem
>(
298 llvm::vfs::getRealFileSystem());
299 OverlayVFS
->pushOverlay(IMVFS
);
300 CI
->createFileManager(OverlayVFS
);
302 auto Interp
= Interpreter::create(std::move(CI
));
303 if (auto E
= Interp
.takeError())
306 llvm::Error Err
= llvm::Error::success();
307 auto DeviceParser
= std::make_unique
<IncrementalCUDADeviceParser
>(
308 **Interp
, std::move(DCI
), *(*Interp
)->IncrParser
.get(),
309 *(*Interp
)->TSCtx
->getContext(), IMVFS
, Err
);
311 return std::move(Err
);
313 (*Interp
)->DeviceParser
= std::move(DeviceParser
);
318 const CompilerInstance
*Interpreter::getCompilerInstance() const {
319 return IncrParser
->getCI();
322 llvm::Expected
<llvm::orc::LLJIT
&> Interpreter::getExecutionEngine() {
324 if (auto Err
= CreateExecutor())
325 return std::move(Err
);
328 return IncrExecutor
->GetExecutionEngine();
331 ASTContext
&Interpreter::getASTContext() {
332 return getCompilerInstance()->getASTContext();
335 const ASTContext
&Interpreter::getASTContext() const {
336 return getCompilerInstance()->getASTContext();
339 size_t Interpreter::getEffectivePTUSize() const {
340 std::list
<PartialTranslationUnit
> &PTUs
= IncrParser
->getPTUs();
341 assert(PTUs
.size() >= InitPTUSize
&& "empty PTU list?");
342 return PTUs
.size() - InitPTUSize
;
345 llvm::Expected
<PartialTranslationUnit
&>
346 Interpreter::Parse(llvm::StringRef Code
) {
347 // If we have a device parser, parse it first.
348 // The generated code will be included in the host compilation
350 auto DevicePTU
= DeviceParser
->Parse(Code
);
351 if (auto E
= DevicePTU
.takeError())
355 // Tell the interpreter sliently ignore unused expressions since value
356 // printing could cause it.
357 getCompilerInstance()->getDiagnostics().setSeverity(
358 clang::diag::warn_unused_expr
, diag::Severity::Ignored
, SourceLocation());
359 return IncrParser
->Parse(Code
);
362 llvm::Error
Interpreter::CreateExecutor() {
363 const clang::TargetInfo
&TI
=
364 getCompilerInstance()->getASTContext().getTargetInfo();
365 llvm::Error Err
= llvm::Error::success();
366 auto Executor
= std::make_unique
<IncrementalExecutor
>(*TSCtx
, Err
, TI
);
368 IncrExecutor
= std::move(Executor
);
373 llvm::Error
Interpreter::Execute(PartialTranslationUnit
&T
) {
376 auto Err
= CreateExecutor();
380 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
381 if (auto Err
= IncrExecutor
->addModule(T
))
384 if (auto Err
= IncrExecutor
->runCtors())
387 return llvm::Error::success();
390 llvm::Error
Interpreter::ParseAndExecute(llvm::StringRef Code
, Value
*V
) {
392 auto PTU
= Parse(Code
);
394 return PTU
.takeError();
396 if (llvm::Error Err
= Execute(*PTU
))
399 if (LastValue
.isValid()) {
404 *V
= std::move(LastValue
);
406 return llvm::Error::success();
409 llvm::Expected
<llvm::orc::ExecutorAddr
>
410 Interpreter::getSymbolAddress(GlobalDecl GD
) const {
412 return llvm::make_error
<llvm::StringError
>("Operation failed. "
413 "No execution engine",
415 llvm::StringRef MangledName
= IncrParser
->GetMangledName(GD
);
416 return getSymbolAddress(MangledName
);
419 llvm::Expected
<llvm::orc::ExecutorAddr
>
420 Interpreter::getSymbolAddress(llvm::StringRef IRName
) const {
422 return llvm::make_error
<llvm::StringError
>("Operation failed. "
423 "No execution engine",
426 return IncrExecutor
->getSymbolAddress(IRName
, IncrementalExecutor::IRName
);
429 llvm::Expected
<llvm::orc::ExecutorAddr
>
430 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name
) const {
432 return llvm::make_error
<llvm::StringError
>("Operation failed. "
433 "No execution engine",
436 return IncrExecutor
->getSymbolAddress(Name
, IncrementalExecutor::LinkerName
);
439 llvm::Error
Interpreter::Undo(unsigned N
) {
441 std::list
<PartialTranslationUnit
> &PTUs
= IncrParser
->getPTUs();
442 if (N
> getEffectivePTUSize())
443 return llvm::make_error
<llvm::StringError
>("Operation failed. "
446 for (unsigned I
= 0; I
< N
; I
++) {
448 if (llvm::Error Err
= IncrExecutor
->removeModule(PTUs
.back()))
452 IncrParser
->CleanUpPTU(PTUs
.back());
455 return llvm::Error::success();
458 llvm::Error
Interpreter::LoadDynamicLibrary(const char *name
) {
459 auto EE
= getExecutionEngine();
461 return EE
.takeError();
463 auto &DL
= EE
->getDataLayout();
465 if (auto DLSG
= llvm::orc::DynamicLibrarySearchGenerator::Load(
466 name
, DL
.getGlobalPrefix()))
467 EE
->getMainJITDylib().addGenerator(std::move(*DLSG
));
469 return DLSG
.takeError();
471 return llvm::Error::success();
474 llvm::Expected
<llvm::orc::ExecutorAddr
>
475 Interpreter::CompileDtorCall(CXXRecordDecl
*CXXRD
) {
476 assert(CXXRD
&& "Cannot compile a destructor for a nullptr");
477 if (auto Dtor
= Dtors
.find(CXXRD
); Dtor
!= Dtors
.end())
478 return Dtor
->getSecond();
480 if (CXXRD
->hasIrrelevantDestructor())
481 return llvm::orc::ExecutorAddr
{};
483 CXXDestructorDecl
*DtorRD
=
484 getCompilerInstance()->getSema().LookupDestructor(CXXRD
);
486 llvm::StringRef Name
=
487 IncrParser
->GetMangledName(GlobalDecl(DtorRD
, Dtor_Base
));
488 auto AddrOrErr
= getSymbolAddress(Name
);
490 return AddrOrErr
.takeError();
492 Dtors
[CXXRD
] = *AddrOrErr
;
496 static constexpr llvm::StringRef MagicRuntimeInterface
[] = {
497 "__clang_Interpreter_SetValueNoAlloc",
498 "__clang_Interpreter_SetValueWithAlloc",
499 "__clang_Interpreter_SetValueCopyArr"};
501 bool Interpreter::FindRuntimeInterface() {
502 if (llvm::all_of(ValuePrintingInfo
, [](Expr
*E
) { return E
!= nullptr; }))
505 Sema
&S
= getCompilerInstance()->getSema();
506 ASTContext
&Ctx
= S
.getASTContext();
508 auto LookupInterface
= [&](Expr
*&Interface
, llvm::StringRef Name
) {
509 LookupResult
R(S
, &Ctx
.Idents
.get(Name
), SourceLocation(),
510 Sema::LookupOrdinaryName
, Sema::ForVisibleRedeclaration
);
511 S
.LookupQualifiedName(R
, Ctx
.getTranslationUnitDecl());
516 Interface
= S
.BuildDeclarationNameExpr(CSS
, R
, /*ADL=*/false).get();
520 if (!LookupInterface(ValuePrintingInfo
[NoAlloc
],
521 MagicRuntimeInterface
[NoAlloc
]))
523 if (!LookupInterface(ValuePrintingInfo
[WithAlloc
],
524 MagicRuntimeInterface
[WithAlloc
]))
526 if (!LookupInterface(ValuePrintingInfo
[CopyArray
],
527 MagicRuntimeInterface
[CopyArray
]))
534 class RuntimeInterfaceBuilder
535 : public TypeVisitor
<RuntimeInterfaceBuilder
, Interpreter::InterfaceKind
> {
536 clang::Interpreter
&Interp
;
540 llvm::SmallVector
<Expr
*, 3> Args
;
543 RuntimeInterfaceBuilder(clang::Interpreter
&In
, ASTContext
&C
, Sema
&SemaRef
,
544 Expr
*VE
, ArrayRef
<Expr
*> FixedArgs
)
545 : Interp(In
), Ctx(C
), S(SemaRef
), E(VE
) {
546 // The Interpreter* parameter and the out parameter `OutVal`.
547 for (Expr
*E
: FixedArgs
)
550 // Get rid of ExprWithCleanups.
551 if (auto *EWC
= llvm::dyn_cast_if_present
<ExprWithCleanups
>(E
))
552 E
= EWC
->getSubExpr();
555 ExprResult
getCall() {
556 QualType Ty
= E
->getType();
557 QualType DesugaredTy
= Ty
.getDesugaredType(Ctx
);
559 // For lvalue struct, we treat it as a reference.
560 if (DesugaredTy
->isRecordType() && E
->isLValue()) {
561 DesugaredTy
= Ctx
.getLValueReferenceType(DesugaredTy
);
562 Ty
= Ctx
.getLValueReferenceType(Ty
);
566 CStyleCastPtrExpr(S
, Ctx
.VoidPtrTy
, (uintptr_t)Ty
.getAsOpaquePtr());
567 // The QualType parameter `OpaqueType`, represented as `void*`.
568 Args
.push_back(TypeArg
);
570 // We push the last parameter based on the type of the Expr. Note we need
571 // special care for rvalue struct.
572 Interpreter::InterfaceKind Kind
= Visit(&*DesugaredTy
);
574 case Interpreter::InterfaceKind::WithAlloc
:
575 case Interpreter::InterfaceKind::CopyArray
: {
576 // __clang_Interpreter_SetValueWithAlloc.
577 ExprResult AllocCall
= S
.ActOnCallExpr(
579 Interp
.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc
],
580 E
->getBeginLoc(), Args
, E
->getEndLoc());
581 assert(!AllocCall
.isInvalid() && "Can't create runtime interface call!");
583 TypeSourceInfo
*TSI
= Ctx
.getTrivialTypeSourceInfo(Ty
, SourceLocation());
585 // Force CodeGen to emit destructor.
586 if (auto *RD
= Ty
->getAsCXXRecordDecl()) {
587 auto *Dtor
= S
.LookupDestructor(RD
);
588 Dtor
->addAttr(UsedAttr::CreateImplicit(Ctx
));
589 Interp
.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
593 // __clang_Interpreter_SetValueCopyArr.
594 if (Kind
== Interpreter::InterfaceKind::CopyArray
) {
595 const auto *ConstantArrTy
=
596 cast
<ConstantArrayType
>(DesugaredTy
.getTypePtr());
597 size_t ArrSize
= Ctx
.getConstantArrayElementCount(ConstantArrTy
);
598 Expr
*ArrSizeExpr
= IntegerLiteralExpr(Ctx
, ArrSize
);
599 Expr
*Args
[] = {E
, AllocCall
.get(), ArrSizeExpr
};
600 return S
.ActOnCallExpr(
603 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray
],
604 SourceLocation(), Args
, SourceLocation());
606 Expr
*Args
[] = {AllocCall
.get()};
607 ExprResult CXXNewCall
= S
.BuildCXXNew(
609 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args
,
610 /*PlacementRParen=*/SourceLocation(),
611 /*TypeIdParens=*/SourceRange(), TSI
->getType(), TSI
, std::nullopt
,
612 E
->getSourceRange(), E
);
614 assert(!CXXNewCall
.isInvalid() &&
615 "Can't create runtime placement new call!");
617 return S
.ActOnFinishFullExpr(CXXNewCall
.get(),
618 /*DiscardedValue=*/false);
620 // __clang_Interpreter_SetValueNoAlloc.
621 case Interpreter::InterfaceKind::NoAlloc
: {
622 return S
.ActOnCallExpr(
624 Interp
.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc
],
625 E
->getBeginLoc(), Args
, E
->getEndLoc());
628 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
631 Interpreter::InterfaceKind
VisitRecordType(const RecordType
*Ty
) {
632 return Interpreter::InterfaceKind::WithAlloc
;
635 Interpreter::InterfaceKind
636 VisitMemberPointerType(const MemberPointerType
*Ty
) {
637 return Interpreter::InterfaceKind::WithAlloc
;
640 Interpreter::InterfaceKind
641 VisitConstantArrayType(const ConstantArrayType
*Ty
) {
642 return Interpreter::InterfaceKind::CopyArray
;
645 Interpreter::InterfaceKind
646 VisitFunctionProtoType(const FunctionProtoType
*Ty
) {
648 return Interpreter::InterfaceKind::NoAlloc
;
651 Interpreter::InterfaceKind
VisitPointerType(const PointerType
*Ty
) {
653 return Interpreter::InterfaceKind::NoAlloc
;
656 Interpreter::InterfaceKind
VisitReferenceType(const ReferenceType
*Ty
) {
657 ExprResult AddrOfE
= S
.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf
, E
);
658 assert(!AddrOfE
.isInvalid() && "Can not create unary expression");
659 Args
.push_back(AddrOfE
.get());
660 return Interpreter::InterfaceKind::NoAlloc
;
663 Interpreter::InterfaceKind
VisitBuiltinType(const BuiltinType
*Ty
) {
664 if (Ty
->isNullPtrType())
666 else if (Ty
->isFloatingType())
668 else if (Ty
->isIntegralOrEnumerationType())
669 HandleIntegralOrEnumType(Ty
);
670 else if (Ty
->isVoidType()) {
671 // Do we need to still run `E`?
674 return Interpreter::InterfaceKind::NoAlloc
;
677 Interpreter::InterfaceKind
VisitEnumType(const EnumType
*Ty
) {
678 HandleIntegralOrEnumType(Ty
);
679 return Interpreter::InterfaceKind::NoAlloc
;
683 // Force cast these types to uint64 to reduce the number of overloads of
684 // `__clang_Interpreter_SetValueNoAlloc`.
685 void HandleIntegralOrEnumType(const Type
*Ty
) {
686 TypeSourceInfo
*TSI
= Ctx
.getTrivialTypeSourceInfo(Ctx
.UnsignedLongLongTy
);
687 ExprResult CastedExpr
=
688 S
.BuildCStyleCastExpr(SourceLocation(), TSI
, SourceLocation(), E
);
689 assert(!CastedExpr
.isInvalid() && "Cannot create cstyle cast expr");
690 Args
.push_back(CastedExpr
.get());
693 void HandlePtrType(const Type
*Ty
) {
694 TypeSourceInfo
*TSI
= Ctx
.getTrivialTypeSourceInfo(Ctx
.VoidPtrTy
);
695 ExprResult CastedExpr
=
696 S
.BuildCStyleCastExpr(SourceLocation(), TSI
, SourceLocation(), E
);
697 assert(!CastedExpr
.isInvalid() && "Can not create cstyle cast expression");
698 Args
.push_back(CastedExpr
.get());
703 // This synthesizes a call expression to a speciall
704 // function that is responsible for generating the Value.
705 // In general, we transform:
708 // // 1. If x is a built-in type like int, float.
709 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
710 // // 2. If x is a struct, and a lvalue.
711 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
713 // // 3. If x is a struct, but a rvalue.
714 // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
717 Expr
*Interpreter::SynthesizeExpr(Expr
*E
) {
718 Sema
&S
= getCompilerInstance()->getSema();
719 ASTContext
&Ctx
= S
.getASTContext();
721 if (!FindRuntimeInterface())
722 llvm_unreachable("We can't find the runtime iterface for pretty print!");
724 // Create parameter `ThisInterp`.
725 auto *ThisInterp
= CStyleCastPtrExpr(S
, Ctx
.VoidPtrTy
, (uintptr_t)this);
727 // Create parameter `OutVal`.
728 auto *OutValue
= CStyleCastPtrExpr(S
, Ctx
.VoidPtrTy
, (uintptr_t)&LastValue
);
730 // Build `__clang_Interpreter_SetValue*` call.
731 RuntimeInterfaceBuilder
Builder(*this, Ctx
, S
, E
, {ThisInterp
, OutValue
});
733 ExprResult Result
= Builder
.getCall();
734 // It could fail, like printing an array type in C. (not supported)
735 if (Result
.isInvalid())
740 // Temporary rvalue struct that need special care.
741 REPL_EXTERNAL_VISIBILITY
void *
742 __clang_Interpreter_SetValueWithAlloc(void *This
, void *OutVal
,
744 Value
&VRef
= *(Value
*)OutVal
;
745 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
746 return VRef
.getPtr();
749 // Pointers, lvalue struct that can take as a reference.
750 REPL_EXTERNAL_VISIBILITY
void
751 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
753 Value
&VRef
= *(Value
*)OutVal
;
754 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
758 REPL_EXTERNAL_VISIBILITY
void
759 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
,
761 Value
&VRef
= *(Value
*)OutVal
;
762 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
765 static void SetValueDataBasedOnQualType(Value
&V
, unsigned long long Data
) {
766 QualType QT
= V
.getType();
767 if (const auto *ET
= QT
->getAs
<EnumType
>())
768 QT
= ET
->getDecl()->getIntegerType();
770 switch (QT
->castAs
<BuiltinType
>()->getKind()) {
772 llvm_unreachable("unknown type kind!");
773 #define X(type, name) \
774 case BuiltinType::name: \
782 REPL_EXTERNAL_VISIBILITY
void
783 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
784 unsigned long long Val
) {
785 Value
&VRef
= *(Value
*)OutVal
;
786 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
787 SetValueDataBasedOnQualType(VRef
, Val
);
790 REPL_EXTERNAL_VISIBILITY
void
791 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
793 Value
&VRef
= *(Value
*)OutVal
;
794 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
798 REPL_EXTERNAL_VISIBILITY
void
799 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
801 Value
&VRef
= *(Value
*)OutVal
;
802 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
806 REPL_EXTERNAL_VISIBILITY
void
807 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
809 Value
&VRef
= *(Value
*)OutVal
;
810 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
811 VRef
.setLongDouble(Val
);