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