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 CompilerInstance
*Interpreter::getCompilerInstance() {
323 return IncrParser
->getCI();
326 llvm::Expected
<llvm::orc::LLJIT
&> Interpreter::getExecutionEngine() {
328 if (auto Err
= CreateExecutor())
329 return std::move(Err
);
332 return IncrExecutor
->GetExecutionEngine();
335 ASTContext
&Interpreter::getASTContext() {
336 return getCompilerInstance()->getASTContext();
339 const ASTContext
&Interpreter::getASTContext() const {
340 return getCompilerInstance()->getASTContext();
343 size_t Interpreter::getEffectivePTUSize() const {
344 std::list
<PartialTranslationUnit
> &PTUs
= IncrParser
->getPTUs();
345 assert(PTUs
.size() >= InitPTUSize
&& "empty PTU list?");
346 return PTUs
.size() - InitPTUSize
;
349 llvm::Expected
<PartialTranslationUnit
&>
350 Interpreter::Parse(llvm::StringRef Code
) {
351 // If we have a device parser, parse it first.
352 // The generated code will be included in the host compilation
354 auto DevicePTU
= DeviceParser
->Parse(Code
);
355 if (auto E
= DevicePTU
.takeError())
359 // Tell the interpreter sliently ignore unused expressions since value
360 // printing could cause it.
361 getCompilerInstance()->getDiagnostics().setSeverity(
362 clang::diag::warn_unused_expr
, diag::Severity::Ignored
, SourceLocation());
363 return IncrParser
->Parse(Code
);
366 llvm::Error
Interpreter::CreateExecutor() {
367 const clang::TargetInfo
&TI
=
368 getCompilerInstance()->getASTContext().getTargetInfo();
369 llvm::Error Err
= llvm::Error::success();
370 auto Executor
= std::make_unique
<IncrementalExecutor
>(*TSCtx
, Err
, TI
);
372 IncrExecutor
= std::move(Executor
);
377 llvm::Error
Interpreter::Execute(PartialTranslationUnit
&T
) {
380 auto Err
= CreateExecutor();
384 // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
385 if (auto Err
= IncrExecutor
->addModule(T
))
388 if (auto Err
= IncrExecutor
->runCtors())
391 return llvm::Error::success();
394 llvm::Error
Interpreter::ParseAndExecute(llvm::StringRef Code
, Value
*V
) {
396 auto PTU
= Parse(Code
);
398 return PTU
.takeError();
400 if (llvm::Error Err
= Execute(*PTU
))
403 if (LastValue
.isValid()) {
408 *V
= std::move(LastValue
);
410 return llvm::Error::success();
413 llvm::Expected
<llvm::orc::ExecutorAddr
>
414 Interpreter::getSymbolAddress(GlobalDecl GD
) const {
416 return llvm::make_error
<llvm::StringError
>("Operation failed. "
417 "No execution engine",
419 llvm::StringRef MangledName
= IncrParser
->GetMangledName(GD
);
420 return getSymbolAddress(MangledName
);
423 llvm::Expected
<llvm::orc::ExecutorAddr
>
424 Interpreter::getSymbolAddress(llvm::StringRef IRName
) const {
426 return llvm::make_error
<llvm::StringError
>("Operation failed. "
427 "No execution engine",
430 return IncrExecutor
->getSymbolAddress(IRName
, IncrementalExecutor::IRName
);
433 llvm::Expected
<llvm::orc::ExecutorAddr
>
434 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name
) const {
436 return llvm::make_error
<llvm::StringError
>("Operation failed. "
437 "No execution engine",
440 return IncrExecutor
->getSymbolAddress(Name
, IncrementalExecutor::LinkerName
);
443 llvm::Error
Interpreter::Undo(unsigned N
) {
445 std::list
<PartialTranslationUnit
> &PTUs
= IncrParser
->getPTUs();
446 if (N
> getEffectivePTUSize())
447 return llvm::make_error
<llvm::StringError
>("Operation failed. "
450 for (unsigned I
= 0; I
< N
; I
++) {
452 if (llvm::Error Err
= IncrExecutor
->removeModule(PTUs
.back()))
456 IncrParser
->CleanUpPTU(PTUs
.back());
459 return llvm::Error::success();
462 llvm::Error
Interpreter::LoadDynamicLibrary(const char *name
) {
463 auto EE
= getExecutionEngine();
465 return EE
.takeError();
467 auto &DL
= EE
->getDataLayout();
469 if (auto DLSG
= llvm::orc::DynamicLibrarySearchGenerator::Load(
470 name
, DL
.getGlobalPrefix()))
471 EE
->getMainJITDylib().addGenerator(std::move(*DLSG
));
473 return DLSG
.takeError();
475 return llvm::Error::success();
478 llvm::Expected
<llvm::orc::ExecutorAddr
>
479 Interpreter::CompileDtorCall(CXXRecordDecl
*CXXRD
) {
480 assert(CXXRD
&& "Cannot compile a destructor for a nullptr");
481 if (auto Dtor
= Dtors
.find(CXXRD
); Dtor
!= Dtors
.end())
482 return Dtor
->getSecond();
484 if (CXXRD
->hasIrrelevantDestructor())
485 return llvm::orc::ExecutorAddr
{};
487 CXXDestructorDecl
*DtorRD
=
488 getCompilerInstance()->getSema().LookupDestructor(CXXRD
);
490 llvm::StringRef Name
=
491 IncrParser
->GetMangledName(GlobalDecl(DtorRD
, Dtor_Base
));
492 auto AddrOrErr
= getSymbolAddress(Name
);
494 return AddrOrErr
.takeError();
496 Dtors
[CXXRD
] = *AddrOrErr
;
500 static constexpr llvm::StringRef MagicRuntimeInterface
[] = {
501 "__clang_Interpreter_SetValueNoAlloc",
502 "__clang_Interpreter_SetValueWithAlloc",
503 "__clang_Interpreter_SetValueCopyArr"};
505 bool Interpreter::FindRuntimeInterface() {
506 if (llvm::all_of(ValuePrintingInfo
, [](Expr
*E
) { return E
!= nullptr; }))
509 Sema
&S
= getCompilerInstance()->getSema();
510 ASTContext
&Ctx
= S
.getASTContext();
512 auto LookupInterface
= [&](Expr
*&Interface
, llvm::StringRef Name
) {
513 LookupResult
R(S
, &Ctx
.Idents
.get(Name
), SourceLocation(),
514 Sema::LookupOrdinaryName
, Sema::ForVisibleRedeclaration
);
515 S
.LookupQualifiedName(R
, Ctx
.getTranslationUnitDecl());
520 Interface
= S
.BuildDeclarationNameExpr(CSS
, R
, /*ADL=*/false).get();
524 if (!LookupInterface(ValuePrintingInfo
[NoAlloc
],
525 MagicRuntimeInterface
[NoAlloc
]))
527 if (!LookupInterface(ValuePrintingInfo
[WithAlloc
],
528 MagicRuntimeInterface
[WithAlloc
]))
530 if (!LookupInterface(ValuePrintingInfo
[CopyArray
],
531 MagicRuntimeInterface
[CopyArray
]))
538 class RuntimeInterfaceBuilder
539 : public TypeVisitor
<RuntimeInterfaceBuilder
, Interpreter::InterfaceKind
> {
540 clang::Interpreter
&Interp
;
544 llvm::SmallVector
<Expr
*, 3> Args
;
547 RuntimeInterfaceBuilder(clang::Interpreter
&In
, ASTContext
&C
, Sema
&SemaRef
,
548 Expr
*VE
, ArrayRef
<Expr
*> FixedArgs
)
549 : Interp(In
), Ctx(C
), S(SemaRef
), E(VE
) {
550 // The Interpreter* parameter and the out parameter `OutVal`.
551 for (Expr
*E
: FixedArgs
)
554 // Get rid of ExprWithCleanups.
555 if (auto *EWC
= llvm::dyn_cast_if_present
<ExprWithCleanups
>(E
))
556 E
= EWC
->getSubExpr();
559 ExprResult
getCall() {
560 QualType Ty
= E
->getType();
561 QualType DesugaredTy
= Ty
.getDesugaredType(Ctx
);
563 // For lvalue struct, we treat it as a reference.
564 if (DesugaredTy
->isRecordType() && E
->isLValue()) {
565 DesugaredTy
= Ctx
.getLValueReferenceType(DesugaredTy
);
566 Ty
= Ctx
.getLValueReferenceType(Ty
);
570 CStyleCastPtrExpr(S
, Ctx
.VoidPtrTy
, (uintptr_t)Ty
.getAsOpaquePtr());
571 // The QualType parameter `OpaqueType`, represented as `void*`.
572 Args
.push_back(TypeArg
);
574 // We push the last parameter based on the type of the Expr. Note we need
575 // special care for rvalue struct.
576 Interpreter::InterfaceKind Kind
= Visit(&*DesugaredTy
);
578 case Interpreter::InterfaceKind::WithAlloc
:
579 case Interpreter::InterfaceKind::CopyArray
: {
580 // __clang_Interpreter_SetValueWithAlloc.
581 ExprResult AllocCall
= S
.ActOnCallExpr(
583 Interp
.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc
],
584 E
->getBeginLoc(), Args
, E
->getEndLoc());
585 assert(!AllocCall
.isInvalid() && "Can't create runtime interface call!");
587 TypeSourceInfo
*TSI
= Ctx
.getTrivialTypeSourceInfo(Ty
, SourceLocation());
589 // Force CodeGen to emit destructor.
590 if (auto *RD
= Ty
->getAsCXXRecordDecl()) {
591 auto *Dtor
= S
.LookupDestructor(RD
);
592 Dtor
->addAttr(UsedAttr::CreateImplicit(Ctx
));
593 Interp
.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
597 // __clang_Interpreter_SetValueCopyArr.
598 if (Kind
== Interpreter::InterfaceKind::CopyArray
) {
599 const auto *ConstantArrTy
=
600 cast
<ConstantArrayType
>(DesugaredTy
.getTypePtr());
601 size_t ArrSize
= Ctx
.getConstantArrayElementCount(ConstantArrTy
);
602 Expr
*ArrSizeExpr
= IntegerLiteralExpr(Ctx
, ArrSize
);
603 Expr
*Args
[] = {E
, AllocCall
.get(), ArrSizeExpr
};
604 return S
.ActOnCallExpr(
607 .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray
],
608 SourceLocation(), Args
, SourceLocation());
610 Expr
*Args
[] = {AllocCall
.get()};
611 ExprResult CXXNewCall
= S
.BuildCXXNew(
613 /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args
,
614 /*PlacementRParen=*/SourceLocation(),
615 /*TypeIdParens=*/SourceRange(), TSI
->getType(), TSI
, std::nullopt
,
616 E
->getSourceRange(), E
);
618 assert(!CXXNewCall
.isInvalid() &&
619 "Can't create runtime placement new call!");
621 return S
.ActOnFinishFullExpr(CXXNewCall
.get(),
622 /*DiscardedValue=*/false);
624 // __clang_Interpreter_SetValueNoAlloc.
625 case Interpreter::InterfaceKind::NoAlloc
: {
626 return S
.ActOnCallExpr(
628 Interp
.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc
],
629 E
->getBeginLoc(), Args
, E
->getEndLoc());
632 llvm_unreachable("Unhandled Interpreter::InterfaceKind");
635 Interpreter::InterfaceKind
VisitRecordType(const RecordType
*Ty
) {
636 return Interpreter::InterfaceKind::WithAlloc
;
639 Interpreter::InterfaceKind
640 VisitMemberPointerType(const MemberPointerType
*Ty
) {
641 return Interpreter::InterfaceKind::WithAlloc
;
644 Interpreter::InterfaceKind
645 VisitConstantArrayType(const ConstantArrayType
*Ty
) {
646 return Interpreter::InterfaceKind::CopyArray
;
649 Interpreter::InterfaceKind
650 VisitFunctionProtoType(const FunctionProtoType
*Ty
) {
652 return Interpreter::InterfaceKind::NoAlloc
;
655 Interpreter::InterfaceKind
VisitPointerType(const PointerType
*Ty
) {
657 return Interpreter::InterfaceKind::NoAlloc
;
660 Interpreter::InterfaceKind
VisitReferenceType(const ReferenceType
*Ty
) {
661 ExprResult AddrOfE
= S
.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf
, E
);
662 assert(!AddrOfE
.isInvalid() && "Can not create unary expression");
663 Args
.push_back(AddrOfE
.get());
664 return Interpreter::InterfaceKind::NoAlloc
;
667 Interpreter::InterfaceKind
VisitBuiltinType(const BuiltinType
*Ty
) {
668 if (Ty
->isNullPtrType())
670 else if (Ty
->isFloatingType())
672 else if (Ty
->isIntegralOrEnumerationType())
673 HandleIntegralOrEnumType(Ty
);
674 else if (Ty
->isVoidType()) {
675 // Do we need to still run `E`?
678 return Interpreter::InterfaceKind::NoAlloc
;
681 Interpreter::InterfaceKind
VisitEnumType(const EnumType
*Ty
) {
682 HandleIntegralOrEnumType(Ty
);
683 return Interpreter::InterfaceKind::NoAlloc
;
687 // Force cast these types to uint64 to reduce the number of overloads of
688 // `__clang_Interpreter_SetValueNoAlloc`.
689 void HandleIntegralOrEnumType(const Type
*Ty
) {
690 TypeSourceInfo
*TSI
= Ctx
.getTrivialTypeSourceInfo(Ctx
.UnsignedLongLongTy
);
691 ExprResult CastedExpr
=
692 S
.BuildCStyleCastExpr(SourceLocation(), TSI
, SourceLocation(), E
);
693 assert(!CastedExpr
.isInvalid() && "Cannot create cstyle cast expr");
694 Args
.push_back(CastedExpr
.get());
697 void HandlePtrType(const Type
*Ty
) {
698 TypeSourceInfo
*TSI
= Ctx
.getTrivialTypeSourceInfo(Ctx
.VoidPtrTy
);
699 ExprResult CastedExpr
=
700 S
.BuildCStyleCastExpr(SourceLocation(), TSI
, SourceLocation(), E
);
701 assert(!CastedExpr
.isInvalid() && "Can not create cstyle cast expression");
702 Args
.push_back(CastedExpr
.get());
707 // This synthesizes a call expression to a speciall
708 // function that is responsible for generating the Value.
709 // In general, we transform:
712 // // 1. If x is a built-in type like int, float.
713 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
714 // // 2. If x is a struct, and a lvalue.
715 // __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
717 // // 3. If x is a struct, but a rvalue.
718 // new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
721 Expr
*Interpreter::SynthesizeExpr(Expr
*E
) {
722 Sema
&S
= getCompilerInstance()->getSema();
723 ASTContext
&Ctx
= S
.getASTContext();
725 if (!FindRuntimeInterface())
726 llvm_unreachable("We can't find the runtime iterface for pretty print!");
728 // Create parameter `ThisInterp`.
729 auto *ThisInterp
= CStyleCastPtrExpr(S
, Ctx
.VoidPtrTy
, (uintptr_t)this);
731 // Create parameter `OutVal`.
732 auto *OutValue
= CStyleCastPtrExpr(S
, Ctx
.VoidPtrTy
, (uintptr_t)&LastValue
);
734 // Build `__clang_Interpreter_SetValue*` call.
735 RuntimeInterfaceBuilder
Builder(*this, Ctx
, S
, E
, {ThisInterp
, OutValue
});
737 ExprResult Result
= Builder
.getCall();
738 // It could fail, like printing an array type in C. (not supported)
739 if (Result
.isInvalid())
744 // Temporary rvalue struct that need special care.
745 REPL_EXTERNAL_VISIBILITY
void *
746 __clang_Interpreter_SetValueWithAlloc(void *This
, void *OutVal
,
748 Value
&VRef
= *(Value
*)OutVal
;
749 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
750 return VRef
.getPtr();
753 // Pointers, lvalue struct that can take as a reference.
754 REPL_EXTERNAL_VISIBILITY
void
755 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
757 Value
&VRef
= *(Value
*)OutVal
;
758 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
762 REPL_EXTERNAL_VISIBILITY
void
763 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
,
765 Value
&VRef
= *(Value
*)OutVal
;
766 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
769 static void SetValueDataBasedOnQualType(Value
&V
, unsigned long long Data
) {
770 QualType QT
= V
.getType();
771 if (const auto *ET
= QT
->getAs
<EnumType
>())
772 QT
= ET
->getDecl()->getIntegerType();
774 switch (QT
->castAs
<BuiltinType
>()->getKind()) {
776 llvm_unreachable("unknown type kind!");
777 #define X(type, name) \
778 case BuiltinType::name: \
786 REPL_EXTERNAL_VISIBILITY
void
787 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
788 unsigned long long Val
) {
789 Value
&VRef
= *(Value
*)OutVal
;
790 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
791 SetValueDataBasedOnQualType(VRef
, Val
);
794 REPL_EXTERNAL_VISIBILITY
void
795 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
797 Value
&VRef
= *(Value
*)OutVal
;
798 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
802 REPL_EXTERNAL_VISIBILITY
void
803 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
805 Value
&VRef
= *(Value
*)OutVal
;
806 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
810 REPL_EXTERNAL_VISIBILITY
void
811 __clang_Interpreter_SetValueNoAlloc(void *This
, void *OutVal
, void *OpaqueType
,
813 Value
&VRef
= *(Value
*)OutVal
;
814 VRef
= Value(static_cast<Interpreter
*>(This
), OpaqueType
);
815 VRef
.setLongDouble(Val
);