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>(Val: *Jobs.begin())) |
65 | return llvm::createStringError(EC: llvm::errc::not_supported, |
66 | S: "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>(Val: &(*Jobs.begin())); |
71 | if (llvm::StringRef(Cmd->getCreator().getName()) != "clang" ) |
72 | return llvm::createStringError(EC: llvm::errc::not_supported, |
73 | S: "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(Writer: std::make_unique<ObjectFilePCHContainerWriter>()); |
87 | PCHOps->registerReader(Reader: 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 | Res&: Clang->getInvocation(), CommandLineArgs: 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(Argv0: Argv[0], MainAddr: nullptr); |
102 | |
103 | // Create the actual diagnostics engine. |
104 | Clang->createDiagnostics(); |
105 | if (!Clang->hasDiagnostics()) |
106 | return llvm::createStringError(EC: llvm::errc::not_supported, |
107 | S: "Initialization failed. " |
108 | "Unable to create diagnostics engine" ); |
109 | |
110 | DiagsBuffer->FlushDiagnostics(Diags&: Clang->getDiagnostics()); |
111 | if (!Success) |
112 | return llvm::createStringError(EC: llvm::errc::not_supported, |
113 | S: "Initialization failed. " |
114 | "Unable to flush diagnostics" ); |
115 | |
116 | // FIXME: Merge with CompilerInstance::ExecuteAction. |
117 | llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer(InputData: "" ).release(); |
118 | Clang->getPreprocessorOpts().addRemappedFile(From: "<<< inputs >>>" , To: MB); |
119 | |
120 | Clang->setTarget(TargetInfo::CreateTargetInfo( |
121 | Diags&: Clang->getDiagnostics(), Opts: Clang->getInvocation().TargetOpts)); |
122 | if (!Clang->hasTarget()) |
123 | return llvm::createStringError(EC: llvm::errc::not_supported, |
124 | S: "Initialization failed. " |
125 | "Target is missing" ); |
126 | |
127 | Clang->getTarget().adjust(Diags&: Clang->getDiagnostics(), Opts&: 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(argv0: nullptr, MainExecAddr: nullptr); |
148 | |
149 | ClangArgv.insert(position: ClangArgv.begin(), x: 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(position: ClangArgv.end(), x: "-Xclang" ); |
157 | ClangArgv.insert(position: ClangArgv.end(), x: "-fincremental-extensions" ); |
158 | ClangArgv.insert(position: ClangArgv.end(), x: "-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(x: "<<< 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(Argv: 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(Args: RF)); |
176 | |
177 | if (Compilation->getArgs().hasArg(Ids: driver::options::OPT_v)) |
178 | Compilation->getJobs().Print(OS&: llvm::errs(), Terminator: "\n" , /*Quote=*/false); |
179 | |
180 | auto ErrOrCC1Args = GetCC1Arguments(Diagnostics: &Diags, Compilation: Compilation.get()); |
181 | if (auto Err = ErrOrCC1Args.takeError()) |
182 | return std::move(Err); |
183 | |
184 | return CreateCI(Argv: **ErrOrCC1Args); |
185 | } |
186 | |
187 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
188 | IncrementalCompilerBuilder::CreateCpp() { |
189 | std::vector<const char *> Argv; |
190 | Argv.reserve(n: 5 + 1 + UserArgs.size()); |
191 | Argv.push_back(x: "-xc++" ); |
192 | #ifdef __EMSCRIPTEN__ |
193 | Argv.push_back("-target" ); |
194 | Argv.push_back("wasm32-unknown-emscripten" ); |
195 | Argv.push_back("-pie" ); |
196 | Argv.push_back("-shared" ); |
197 | #endif |
198 | Argv.insert(position: Argv.end(), first: UserArgs.begin(), last: UserArgs.end()); |
199 | |
200 | std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); |
201 | return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv); |
202 | } |
203 | |
204 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
205 | IncrementalCompilerBuilder::createCuda(bool device) { |
206 | std::vector<const char *> Argv; |
207 | Argv.reserve(n: 5 + 4 + UserArgs.size()); |
208 | |
209 | Argv.push_back(x: "-xcuda" ); |
210 | if (device) |
211 | Argv.push_back(x: "--cuda-device-only" ); |
212 | else |
213 | Argv.push_back(x: "--cuda-host-only" ); |
214 | |
215 | std::string SDKPathArg = "--cuda-path=" ; |
216 | if (!CudaSDKPath.empty()) { |
217 | SDKPathArg += CudaSDKPath; |
218 | Argv.push_back(x: SDKPathArg.c_str()); |
219 | } |
220 | |
221 | std::string ArchArg = "--offload-arch=" ; |
222 | if (!OffloadArch.empty()) { |
223 | ArchArg += OffloadArch; |
224 | Argv.push_back(x: ArchArg.c_str()); |
225 | } |
226 | |
227 | Argv.insert(position: Argv.end(), first: UserArgs.begin(), last: UserArgs.end()); |
228 | |
229 | std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); |
230 | return IncrementalCompilerBuilder::create(TT, ClangArgv&: Argv); |
231 | } |
232 | |
233 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
234 | IncrementalCompilerBuilder::CreateCudaDevice() { |
235 | return IncrementalCompilerBuilder::createCuda(device: true); |
236 | } |
237 | |
238 | llvm::Expected<std::unique_ptr<CompilerInstance>> |
239 | IncrementalCompilerBuilder::CreateCudaHost() { |
240 | return IncrementalCompilerBuilder::createCuda(device: 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>(args: std::move(LLVMCtx)); |
250 | IncrParser = std::make_unique<IncrementalParser>( |
251 | args&: *this, args: std::move(CI), args&: *TSCtx->getContext(), args&: 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(E1: std::move(ErrOut), E2: 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(T&: PTU)) { |
266 | ErrOut = joinErrors(E1: std::move(ErrOut), E2: 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 | reason: llvm::Twine("Failed to clean up IncrementalExecutor: " ) + |
277 | toString(E: 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(Code: Runtimes); |
318 | if (!PTU) |
319 | return PTU.takeError(); |
320 | Interp->markUserCodeStart(); |
321 | |
322 | Interp->ValuePrintingInfo.resize(N: 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 | args: llvm::vfs::getRealFileSystem()); |
335 | OverlayVFS->pushOverlay(FS: IMVFS); |
336 | CI->createFileManager(VFS: OverlayVFS); |
337 | |
338 | auto Interp = Interpreter::create(CI: 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 | args&: **Interp, args: std::move(DCI), args&: *(*Interp)->IncrParser.get(), |
345 | args&: *(*Interp)->TSCtx->getContext(), args&: IMVFS, args&: 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(Input: 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 | Diag: clang::diag::warn_unused_expr, Map: diag::Severity::Ignored, Loc: SourceLocation()); |
404 | return IncrParser->Parse(Input: 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>(Args: "Operation failed. " |
420 | "Execution engine exists" , |
421 | Args: std::error_code()); |
422 | if (!IncrParser->getCodeGen()) |
423 | return llvm::make_error<llvm::StringError>(Args: "Operation failed. " |
424 | "No code generator available" , |
425 | Args: 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(JTMB: 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>(args&: *TSCtx, args&: *JITBuilder, args&: 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(PTU&: 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(T&: *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>(Args: "Operation failed. " |
492 | "No execution engine" , |
493 | Args: std::error_code()); |
494 | llvm::StringRef MangledName = IncrParser->GetMangledName(GD); |
495 | return getSymbolAddress(IRName: 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>(Args: "Operation failed. " |
502 | "No execution engine" , |
503 | Args: std::error_code()); |
504 | |
505 | return IncrExecutor->getSymbolAddress(Name: IRName, NameKind: 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>(Args: "Operation failed. " |
512 | "No execution engine" , |
513 | Args: std::error_code()); |
514 | |
515 | return IncrExecutor->getSymbolAddress(Name, NameKind: 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>(Args: "Operation failed. " |
523 | "Too many undos" , |
524 | Args: std::error_code()); |
525 | for (unsigned I = 0; I < N; I++) { |
526 | if (IncrExecutor) { |
527 | if (llvm::Error Err = IncrExecutor->removeModule(PTU&: PTUs.back())) |
528 | return Err; |
529 | } |
530 | |
531 | IncrParser->CleanUpPTU(PTU&: 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 | FileName: name, GlobalPrefix: DL.getGlobalPrefix())) |
546 | EE->getMainJITDylib().addGenerator(DefGenerator: 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(Val: 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(Class: CXXRD); |
564 | |
565 | llvm::StringRef Name = |
566 | IncrParser->GetMangledName(GD: GlobalDecl(DtorRD, Dtor_Base)); |
567 | auto AddrOrErr = getSymbolAddress(IRName: 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(Range&: ValuePrintingInfo, P: [](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, LookupCtx: Ctx.getTranslationUnitDecl()); |
596 | if (R.empty()) |
597 | return false; |
598 | |
599 | CXXScopeSpec CSS; |
600 | Interface = S.BuildDeclarationNameExpr(SS: CSS, R, /*ADL=*/NeedsADL: 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(Interp&: *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(OpLoc: SourceLocation(), Opc: UO_AddrOf, InputExpr: E); |
664 | assert(!AddrOfE.isInvalid() && "Can not create unary expression" ); |
665 | Args.push_back(Elt: AddrOfE.get()); |
666 | return Interpreter::InterfaceKind::NoAlloc; |
667 | } |
668 | |
669 | Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) { |
670 | if (Ty->isNullPtrType()) |
671 | Args.push_back(Elt: E); |
672 | else if (Ty->isFloatingType()) |
673 | Args.push_back(Elt: 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(T: Ctx.VoidPtrTy); |
693 | QualType UIntTy = Ctx.getBitIntType(/*Unsigned=*/true, NumBits: PtrBits); |
694 | TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: UIntTy); |
695 | ExprResult CastedExpr = |
696 | S.BuildCStyleCastExpr(LParenLoc: SourceLocation(), Ty: TSI, RParenLoc: SourceLocation(), Op: E); |
697 | assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr" ); |
698 | Args.push_back(Elt: CastedExpr.get()); |
699 | } |
700 | |
701 | void HandlePtrType(const Type *Ty) { |
702 | TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(T: Ctx.VoidPtrTy); |
703 | ExprResult CastedExpr = |
704 | S.BuildCStyleCastExpr(LParenLoc: SourceLocation(), Ty: TSI, RParenLoc: SourceLocation(), Op: E); |
705 | assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression" ); |
706 | Args.push_back(Elt: 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>(Val: 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(Elt: E); |
738 | |
739 | QualType Ty = E->getType(); |
740 | QualType DesugaredTy = Ty.getDesugaredType(Context: B->Ctx); |
741 | |
742 | // For lvalue struct, we treat it as a reference. |
743 | if (DesugaredTy->isRecordType() && E->isLValue()) { |
744 | DesugaredTy = B->Ctx.getLValueReferenceType(T: DesugaredTy); |
745 | Ty = B->Ctx.getLValueReferenceType(T: Ty); |
746 | } |
747 | |
748 | Expr *TypeArg = CStyleCastPtrExpr(S&: B->S, Ty: B->Ctx.VoidPtrTy, |
749 | Ptr: (uintptr_t)Ty.getAsOpaquePtr()); |
750 | // The QualType parameter `OpaqueType`, represented as `void*`. |
751 | Visitor.Args.push_back(Elt: 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(T: &*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=*/S: nullptr, |
762 | Fn: B->Interp |
763 | .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], |
764 | LParenLoc: E->getBeginLoc(), ArgExprs: Visitor.Args, RParenLoc: E->getEndLoc()); |
765 | assert(!AllocCall.isInvalid() && "Can't create runtime interface call!" ); |
766 | |
767 | TypeSourceInfo *TSI = |
768 | B->Ctx.getTrivialTypeSourceInfo(T: Ty, Loc: SourceLocation()); |
769 | |
770 | // Force CodeGen to emit destructor. |
771 | if (auto *RD = Ty->getAsCXXRecordDecl()) { |
772 | auto *Dtor = B->S.LookupDestructor(Class: RD); |
773 | Dtor->addAttr(A: UsedAttr::CreateImplicit(Ctx&: B->Ctx)); |
774 | B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( |
775 | D: DeclGroupRef(Dtor)); |
776 | } |
777 | |
778 | // __clang_Interpreter_SetValueCopyArr. |
779 | if (Kind == Interpreter::InterfaceKind::CopyArray) { |
780 | const auto *ConstantArrTy = |
781 | cast<ConstantArrayType>(Val: DesugaredTy.getTypePtr()); |
782 | size_t ArrSize = B->Ctx.getConstantArrayElementCount(CA: ConstantArrTy); |
783 | Expr *ArrSizeExpr = IntegerLiteralExpr(C&: B->Ctx, Val: ArrSize); |
784 | Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; |
785 | return B->S.ActOnCallExpr( |
786 | /*Scope *=*/S: nullptr, |
787 | Fn: B->Interp |
788 | .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], |
789 | LParenLoc: SourceLocation(), ArgExprs: Args, RParenLoc: SourceLocation()); |
790 | } |
791 | Expr *Args[] = { |
792 | AllocCall.get(), |
793 | B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]}; |
794 | ExprResult CXXNewCall = B->S.BuildCXXNew( |
795 | Range: E->getSourceRange(), |
796 | /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), PlacementArgs: Args, |
797 | /*PlacementRParen=*/SourceLocation(), |
798 | /*TypeIdParens=*/SourceRange(), AllocType: TSI->getType(), AllocTypeInfo: TSI, ArraySize: std::nullopt, |
799 | DirectInitRange: E->getSourceRange(), Initializer: E); |
800 | |
801 | assert(!CXXNewCall.isInvalid() && |
802 | "Can't create runtime placement new call!" ); |
803 | |
804 | return B->S.ActOnFinishFullExpr(Expr: CXXNewCall.get(), |
805 | /*DiscardedValue=*/false); |
806 | } |
807 | // __clang_Interpreter_SetValueNoAlloc. |
808 | case Interpreter::InterfaceKind::NoAlloc: { |
809 | return B->S.ActOnCallExpr( |
810 | /*Scope=*/S: nullptr, |
811 | Fn: B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], |
812 | LParenLoc: E->getBeginLoc(), ArgExprs: Visitor.Args, RParenLoc: 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>(args&: Interp, args&: Ctx, args&: 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, Ty: Ctx.VoidPtrTy, Ptr: (uintptr_t)this); |
855 | |
856 | // Create parameter `OutVal`. |
857 | auto *OutValue = CStyleCastPtrExpr(S, Ty: Ctx.VoidPtrTy, Ptr: (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 | |