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