CppInterOp
C++ Language Interoperability Layer
Loading...
Searching...
No Matches
CppInterOpInterpreter.h
Go to the documentation of this file.
1//--------------------------------------------------------------------*- C++ -*-
2// CppInterOp Interpreter (clang-repl)
3// author: Alexander Penev <alexander_penev@yahoo.com>
4//------------------------------------------------------------------------------
5
6#ifndef CPPINTEROP_INTERPRETER_H
7#define CPPINTEROP_INTERPRETER_H
8
9#include "Compatibility.h"
11#include "Paths.h"
12
13#include "clang/Interpreter/Interpreter.h"
14#include "clang/Interpreter/PartialTranslationUnit.h"
15
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclarationName.h"
18#include "clang/AST/GlobalDecl.h"
19#include "clang/Basic/LangOptions.h"
20#include "clang/Basic/TargetOptions.h"
21#include "clang/Frontend/CompilerInstance.h"
22#include "clang/Frontend/FrontendOptions.h"
23#include "clang/Lex/Preprocessor.h"
24#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Redeclaration.h"
26#include "clang/Sema/Sema.h"
27#include "clang/Serialization/ModuleFileExtension.h"
28
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/ExecutionEngine/Orc/LLJIT.h"
34#include "llvm/Support/Compiler.h"
35#include "llvm/Support/Error.h"
36#include "llvm/Support/TargetSelect.h"
37#include "llvm/Support/raw_ostream.h"
38#include "llvm/TargetParser/Triple.h"
39
40#ifndef _WIN32
41#include <sched.h>
42#include <unistd.h>
43#endif
44#if defined(_WIN32) && (defined(_M_IX86) || defined(__i386__))
45#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
46#include "llvm/Support/DynamicLibrary.h"
47#include <deque>
48#endif
49#include <algorithm>
50#include <cstdio>
51#include <memory>
52#include <mutex>
53#include <tuple>
54#include <utility>
55#include <vector>
56
57namespace clang {
58class CompilerInstance;
59}
60
61namespace {
62template <typename D> static D* LookupResult2Decl(clang::LookupResult& R) {
63 if (R.empty())
64 return nullptr;
65
66 R.resolveKind();
67
68 if (R.isSingleResult())
69 return llvm::dyn_cast<D>(R.getFoundDecl());
70 return (D*)-1;
71}
72} // namespace
73
74namespace CppInternal {
75namespace utils {
76namespace Lookup {
77
78inline clang::NamespaceDecl* Namespace(clang::Sema* S, const char* Name,
79 const clang::DeclContext* Within) {
80 clang::DeclarationName DName = &(S->Context.Idents.get(Name));
81 clang::LookupResult R(*S, DName, clang::SourceLocation(),
82 clang::Sema::LookupNestedNameSpecifierName);
83 R.suppressDiagnostics();
84 if (!Within)
85 S->LookupName(R, S->TUScope);
86 else {
87 if (const clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(Within)) {
88 if (!TD->getDefinition()) {
89 // No definition, no lookup result.
90 return nullptr;
91 }
92 }
93 S->LookupQualifiedName(R, const_cast<clang::DeclContext*>(Within));
94 }
95
96 if (R.empty())
97 return nullptr;
98
99 R.resolveKind();
100
101 return llvm::dyn_cast<clang::NamespaceDecl>(R.getFoundDecl());
102}
103
104inline void Named(clang::Sema* S, clang::LookupResult& R,
105 const clang::DeclContext* Within = nullptr) {
106 R.suppressDiagnostics();
107 if (!Within)
108 S->LookupName(R, S->TUScope);
109 else {
110 const clang::DeclContext* primaryWithin = nullptr;
111 if (const clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(Within)) {
112 primaryWithin =
113 llvm::dyn_cast_or_null<clang::DeclContext>(TD->getDefinition());
114 } else {
115 primaryWithin = Within->getPrimaryContext();
116 }
117 if (!primaryWithin) {
118 // No definition, no lookup result.
119 return;
120 }
121 S->LookupQualifiedName(R, const_cast<clang::DeclContext*>(primaryWithin));
122 }
123}
124
125inline clang::NamedDecl* Named(clang::Sema* S,
126 const clang::DeclarationName& Name,
127 const clang::DeclContext* Within = nullptr) {
128 clang::LookupResult R(*S, Name, clang::SourceLocation(),
129 clang::Sema::LookupOrdinaryName,
130 RedeclarationKind::ForVisibleRedeclaration);
131 Named(S, R, Within);
132 return LookupResult2Decl<clang::NamedDecl>(R);
133}
134
135inline clang::NamedDecl* Named(clang::Sema* S, llvm::StringRef Name,
136 const clang::DeclContext* Within = nullptr) {
137 clang::DeclarationName DName = &S->Context.Idents.get(Name);
138 return Named(S, DName, Within);
139}
140
141inline clang::NamedDecl* Named(clang::Sema* S, const char* Name,
142 const clang::DeclContext* Within = nullptr) {
143 return Named(S, llvm::StringRef(Name), Within);
144}
145
146} // namespace Lookup
147} // namespace utils
148} // namespace CppInternal
149
150namespace CppInternal {
151
152#if defined(_WIN32) && (defined(_M_IX86) || defined(__i386__))
153/// Fallback resolver for decorated COFF-i386 symbols, based on cling's
154/// platform::DLSym. i386 linker names are decorated ('_' cdecl prefix,
155/// '@N' stdcall suffix, '__imp_' dllimport indirection) and ORC strips
156/// such prefixes only on MachO, so JIT'd references to the CRT and to
157/// runtime-loaded DLLs fail to materialize. Undecorate and retry.
158class COFFi386SymbolGenerator : public llvm::orc::DefinitionGenerator {
159public:
160 llvm::Error
161 tryToGenerate(llvm::orc::LookupState& LS, llvm::orc::LookupKind K,
162 llvm::orc::JITDylib& JD,
163 llvm::orc::JITDylibLookupFlags JDLookupFlags,
164 const llvm::orc::SymbolLookupSet& LookupSet) override {
165 llvm::orc::SymbolMap NewSymbols;
166 for (const auto& KV : LookupSet) {
167 llvm::StringRef Name = *KV.first;
168 // '?' C++ manglings are undecorated; the default generator owns them.
169 if (Name.empty() || Name.starts_with("?"))
170 continue;
171 if (void* Addr = lookupDecorated(Name))
172 NewSymbols[KV.first] = {llvm::orc::ExecutorAddr::fromPtr(Addr),
173 llvm::JITSymbolFlags::Exported};
174 }
175 if (NewSymbols.empty())
176 return llvm::Error::success();
177 return JD.define(llvm::orc::absoluteSymbols(std::move(NewSymbols)));
178 }
179
180private:
181 void* lookupDecorated(llvm::StringRef Name) {
182 bool Dllimport = Name.consume_front("__imp_");
183 Name.consume_front("_"); // i386 cdecl prefix
184 std::string S = Name.str();
185 void* Addr = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(S.c_str());
186 if (!Addr) {
187 // Export tables drop the stdcall '@N' suffix; retry without it.
188 size_t At = S.rfind('@');
189 if (At != std::string::npos && At + 1 < S.size() &&
190 S.find_first_not_of("0123456789", At + 1) == std::string::npos) {
191 S.resize(At);
192 Addr = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(S.c_str());
193 }
194 }
195 if (Addr && Dllimport) {
196 // __imp_ references bind to a pointer to the symbol; hand out a
197 // stable slot holding the resolved address.
198 m_ImportSlots.push_back(Addr);
199 return &m_ImportSlots.back();
200 }
201 return Addr;
202 }
203
204 std::deque<void*> m_ImportSlots;
205};
206#endif // _WIN32 && i386
207
208/// CppInterOp Interpreter
209///
211public:
212 struct FileDeleter {
213 void operator()(FILE* f /* owns */) {
214 if (f)
215 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
216 fclose(f);
217 }
218 };
219
220 struct IOContext {
221 std::unique_ptr<FILE, FileDeleter> stdin_file;
222 std::unique_ptr<FILE, FileDeleter> stdout_file;
223 std::unique_ptr<FILE, FileDeleter> stderr_file;
224
226 stdin_file.reset(tmpfile()); // NOLINT(cppcoreguidelines-owning-memory)
227 stdout_file.reset(tmpfile()); // NOLINT(cppcoreguidelines-owning-memory)
228 stderr_file.reset(tmpfile()); // NOLINT(cppcoreguidelines-owning-memory)
230 }
231 };
232
233private:
234 static std::tuple<int, int, int>
235 initAndGetFileDescriptors(std::vector<const char*>& vargs,
236 IOContext& io_ctx) {
237 int stdin_fd = 0;
238 int stdout_fd = 1;
239 int stderr_fd = 2;
240
241 // Only initialize temp files if not already initialized
242 if (!io_ctx.stdin_file || !io_ctx.stdout_file || !io_ctx.stderr_file) {
243 bool init = io_ctx.initializeTempFiles();
244 if (!init) {
245 llvm::errs() << "Can't start out-of-process JIT execution.\n";
246 stdin_fd = -1;
247 stdout_fd = -1;
248 stderr_fd = -1;
249 }
250 }
251 stdin_fd = fileno(io_ctx.stdin_file.get());
252 stdout_fd = fileno(io_ctx.stdout_file.get());
253 stderr_fd = fileno(io_ctx.stderr_file.get());
254
255 return std::make_tuple(stdin_fd, stdout_fd, stderr_fd);
256 }
257
258 std::unique_ptr<clang::Interpreter> inner;
259 std::unique_ptr<IOContext> io_context;
260 mutable std::unique_ptr<DynamicLibraryManager> sDLM;
261 mutable std::once_flag sDLMInit;
262 bool outOfProcess;
263
264public:
265 Interpreter(std::unique_ptr<clang::Interpreter> CI,
266 std::unique_ptr<IOContext> ctx = nullptr, bool oop = false)
267 : inner(std::move(CI)), io_context(std::move(ctx)), outOfProcess(oop) {}
268
269public:
270 static std::unique_ptr<Interpreter>
271 create(int argc, const char* const* argv, const char* llvmdir = nullptr,
272 const std::vector<std::shared_ptr<clang::ModuleFileExtension>>&
273 moduleExtensions = {},
274 void* extraLibHandle = nullptr, bool noRuntime = true) {
275 std::vector<const char*> vargs(argv + 1, argv + argc);
276
277 int stdin_fd = 0;
278 int stdout_fd = 1;
279 int stderr_fd = 2;
280 auto io_ctx = std::make_unique<IOContext>();
281 bool outOfProcess = false;
282
283#if LLVM_VERSION_MAJOR > 21 && !defined(_WIN32)
284 outOfProcess = std::any_of(vargs.begin(), vargs.end(), [](const char* arg) {
285 return llvm::StringRef(arg).trim() == "--use-oop-jit";
286 });
287#endif
288
289 if (outOfProcess) {
290 std::tie(stdin_fd, stdout_fd, stderr_fd) =
291 initAndGetFileDescriptors(vargs, *io_ctx);
292
293 if (stdin_fd == -1 || stdout_fd == -1 || stderr_fd == -1) {
294 llvm::errs()
295 << "Redirection files creation failed for Out-Of-Process JIT\n";
296 return nullptr;
297 }
298 }
299
300 // Currently, we can't pass IOContext in `createClangInterpreter`, that's
301 // why fd's are passed. This should be refactored later.
302 auto CI =
303 compat::createClangInterpreter(vargs, stdin_fd, stdout_fd, stderr_fd);
304 if (!CI) {
305 llvm::errs() << "Interpreter creation failed\n";
306 return nullptr;
307 }
308
309#if defined(_WIN32) && (defined(_M_IX86) || defined(__i386__))
310 // getExecutionEngine forces executor creation; install the generator
311 // before anything runs.
312 compat::getExecutionEngine(*CI)->getMainJITDylib().addGenerator(
313 std::make_unique<COFFi386SymbolGenerator>());
314#endif
315
316 return std::make_unique<Interpreter>(std::move(CI), std::move(io_ctx),
317 outOfProcess);
318 }
319
321
322 operator const clang::Interpreter&() const { return *inner; }
323 operator clang::Interpreter&() { return *inner; }
324
325 [[nodiscard]] bool isOutOfProcess() const { return outOfProcess; }
326
327// Since, we are using custom pipes instead of stdout, sterr,
328// it is kind of necessary to have this complication in StreamCaptureInfo.
329
330// TODO(issues/733): Refactor the stream redirection
331#ifndef _WIN32
333 if (!io_context)
334 return nullptr;
335 switch (FD) {
336 case (STDIN_FILENO):
337 return io_context->stdin_file.get();
338 case (STDOUT_FILENO):
339 return io_context->stdout_file.get();
340 case (STDERR_FILENO):
341 return io_context->stderr_file.get();
342 default:
343 llvm::errs() << "No temp file for the FD\n";
344 return nullptr;
345 }
346 }
347#endif
348
349 ///\brief Describes the return result of the different routines that do the
350 /// incremental compilation.
351 ///
353
354 const clang::CompilerInstance* getCompilerInstance() const {
355 return inner->getCompilerInstance();
356 }
357
358 llvm::orc::LLJIT* getExecutionEngine() const {
359 return compat::getExecutionEngine(*inner);
360 }
361
362 llvm::Expected<clang::PartialTranslationUnit&> Parse(llvm::StringRef Code) {
363 return inner->Parse(Code);
364 }
365
366 llvm::Error Execute(clang::PartialTranslationUnit& T) {
367 return inner->Execute(T);
368 }
369
370 llvm::Error ParseAndExecute(llvm::StringRef Code, clang::Value* V = nullptr) {
371 return inner->ParseAndExecute(Code, V);
372 }
373
374 llvm::Error Undo(unsigned N = 1) { return compat::Undo(*inner, N); }
375
376 void makeEngineOnce() const {
377 static bool make_engine_once = true;
378 if (make_engine_once) {
379 if (auto Err = inner->ParseAndExecute(""))
380 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "Error:");
381 make_engine_once = false;
382 }
383 }
384
385 /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses
386 /// the CodeGenModule's internal mangling cache to avoid recomputing the
387 /// mangled name.
388 llvm::Expected<llvm::orc::ExecutorAddr>
389 getSymbolAddress(clang::GlobalDecl GD) const {
391 auto AddrOrErr = compat::getSymbolAddress(*inner, GD);
392 if (llvm::Error Err = AddrOrErr.takeError())
393 return std::move(Err);
394 return llvm::orc::ExecutorAddr(*AddrOrErr);
395 }
396
397 /// \returns the \c ExecutorAddr of a given name as written in the IR.
398 llvm::Expected<llvm::orc::ExecutorAddr>
399 getSymbolAddress(llvm::StringRef IRName) const {
401 auto AddrOrErr = compat::getSymbolAddress(*inner, IRName);
402 if (llvm::Error Err = AddrOrErr.takeError())
403 return std::move(Err);
404 return llvm::orc::ExecutorAddr(*AddrOrErr);
405 }
406
407 /// \returns the \c ExecutorAddr of a given name as written in the object
408 /// file.
409 llvm::Expected<llvm::orc::ExecutorAddr>
410 getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const {
411 auto AddrOrErr = compat::getSymbolAddressFromLinkerName(*inner, LinkerName);
412 if (llvm::Error Err = AddrOrErr.takeError())
413 return std::move(Err);
414 return llvm::orc::ExecutorAddr(*AddrOrErr);
415 }
416
417 bool isInSyntaxOnlyMode() const {
418 return getCompilerInstance()->getFrontendOpts().ProgramAction ==
419 clang::frontend::ParseSyntaxOnly;
420 }
421
422 // FIXME: Mangle GD and call the other overload.
423 void* getAddressOfGlobal(const clang::GlobalDecl& GD) const {
424 auto addressOrErr = getSymbolAddress(GD);
425 if (addressOrErr)
426 return addressOrErr->toPtr<void*>();
427
428 llvm::consumeError(addressOrErr.takeError()); // okay to be missing
429 return nullptr;
430 }
431
432 void* getAddressOfGlobal(llvm::StringRef SymName) const {
433 if (isInSyntaxOnlyMode())
434 return nullptr;
435
436 auto addressOrErr =
437 getSymbolAddressFromLinkerName(SymName); // TODO: Or getSymbolAddress
438 if (addressOrErr)
439 return addressOrErr->toPtr<void*>();
440
441 llvm::consumeError(addressOrErr.takeError()); // okay to be missing
442 return nullptr;
443 }
444
445 CompilationResult declare(const std::string& input,
446 clang::PartialTranslationUnit** PTU = nullptr) {
447 return process(input, /*Value=*/nullptr, PTU);
448 }
449
450 ///\brief Maybe transform the input line to implement cint command line
451 /// semantics (declarations are global) and compile to produce a module.
452 ///
453 CompilationResult process(const std::string& input, clang::Value* V = 0,
454 clang::PartialTranslationUnit** PTU = nullptr,
455 bool disableValuePrinting = false) {
456 auto PTUOrErr = Parse(input);
457 if (!PTUOrErr) {
458 llvm::logAllUnhandledErrors(PTUOrErr.takeError(), llvm::errs(),
459 "Failed to parse via ::process:");
461 }
462
463 if (PTU)
464 *PTU = &*PTUOrErr;
465
466 if (auto Err = Execute(*PTUOrErr)) {
467 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
468 "Failed to execute via ::process:");
470 }
472 }
473
474 CompilationResult evaluate(const std::string& input, clang::Value& V) {
475 if (auto Err = ParseAndExecute(input, &V)) {
476 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
477 "Failed to execute via ::evaluate:");
479 }
481 }
482
483 void* compileFunction(llvm::StringRef name, llvm::StringRef code,
484 bool ifUnique, bool withAccessControl) {
485 //
486 // Compile the wrapper code.
487 //
488
489 if (isInSyntaxOnlyMode())
490 return nullptr;
491
492 if (ifUnique) {
493 if (void* Addr = (void*)getAddressOfGlobal(name)) {
494 return Addr;
495 }
496 }
497
498 clang::LangOptions& LO =
499 const_cast<clang::LangOptions&>(getCompilerInstance()->getLangOpts());
500 bool SavedAccessControl = LO.AccessControl;
501 LO.AccessControl = withAccessControl;
502
503 if (auto Err = ParseAndExecute(code)) {
504 LO.AccessControl = SavedAccessControl;
505 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
506 "Failed to compileFunction: ");
507 return nullptr;
508 }
509
510 LO.AccessControl = SavedAccessControl;
511
512 return getAddressOfGlobal(name);
513 }
514
515 const clang::CompilerInstance* getCI() const { return getCompilerInstance(); }
516
517 clang::Sema& getSema() const { return getCI()->getSema(); }
518
520 assert(compat::getExecutionEngine(*inner) && "We must have an executor");
521 // Replaces the C++11 magic-static thread-safe init the previous
522 // function-local DLM had for free.
523 std::call_once(sDLMInit, [this] {
524 sDLM = std::make_unique<DynamicLibraryManager>();
525 sDLM->initializeDyld([](llvm::StringRef) { /*ignore*/ return false; });
526 });
527 return sDLM.get();
528 }
529
531 return const_cast<DynamicLibraryManager*>(
532 const_cast<const Interpreter*>(this)->getDynamicLibraryManager());
533 }
534
535 ///\brief Adds multiple include paths separated by a delimiter.
536 ///
537 ///\param[in] PathsStr - Path(s)
538 ///\param[in] Delim - Delimiter to separate paths or NULL if a single path
539 ///
540 void AddIncludePaths(llvm::StringRef PathsStr, const char* Delim = ":") {
541 const clang::CompilerInstance* CI = getCompilerInstance();
542 clang::HeaderSearchOptions& HOpts =
543 const_cast<clang::HeaderSearchOptions&>(CI->getHeaderSearchOpts());
544
545 // Save the current number of entries
546 size_t Idx = HOpts.UserEntries.size();
547 CppInternal::utils::AddIncludePaths(PathsStr, HOpts, Delim);
548
549 clang::Preprocessor& PP = CI->getPreprocessor();
550 clang::SourceManager& SM = PP.getSourceManager();
551 clang::FileManager& FM = SM.getFileManager();
552 clang::HeaderSearch& HSearch = PP.getHeaderSearchInfo();
553 const bool isFramework = false;
554
555 // Add all the new entries into Preprocessor
556 for (const size_t N = HOpts.UserEntries.size(); Idx < N; ++Idx) {
557 const clang::HeaderSearchOptions::Entry& E = HOpts.UserEntries[Idx];
558 if (auto DE = FM.getOptionalDirectoryRef(E.Path))
559 HSearch.AddSearchPath(
560 clang::DirectoryLookup(*DE, clang::SrcMgr::C_User, isFramework),
561 E.Group == clang::frontend::Angled);
562 }
563 }
564
565 ///\brief Adds a single include path (-I).
566 ///
567 void AddIncludePath(llvm::StringRef PathsStr) {
568 return AddIncludePaths(PathsStr, nullptr);
569 }
570
571 ///\brief Get the current include paths that are used.
572 ///
573 ///\param[out] incpaths - Pass in a llvm::SmallVector<std::string, N> with
574 /// sufficiently sized N, to hold the result of the call.
575 ///\param[in] withSystem - if true, incpaths will also contain system
576 /// include paths (framework, STL etc).
577 ///\param[in] withFlags - if true, each element in incpaths will be prefixed
578 /// with a "-I" or similar, and some entries of incpaths will signal
579 /// a new include path region (e.g. "-cxx-isystem"). Also, flags
580 /// defining header search behavior will be included in incpaths, e.g.
581 /// "-nostdinc".
582 ///
583 void GetIncludePaths(llvm::SmallVectorImpl<std::string>& incpaths,
584 bool withSystem, bool withFlags) const {
585 CppInternal::utils::CopyIncludePaths(getCI()->getHeaderSearchOpts(),
586 incpaths, withSystem, withFlags);
587 }
588
589 CompilationResult loadLibrary(const std::string& filename, bool lookup) {
590 llvm::Triple triple(getCompilerInstance()->getTargetOpts().Triple);
591 if (triple.isWasm()) {
592 // On WASM, dlopen-style canonical lookup has no effect.
593 if (auto Err = inner->LoadDynamicLibrary(filename.c_str())) {
594 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
595 "loadLibrary: ");
596 return kFailure;
597 }
598 return kSuccess;
599 }
600
602 std::string canonicalLib;
603 if (lookup)
604 canonicalLib = DLM->lookupLibrary(filename);
605
606 const std::string& library = lookup ? canonicalLib : filename;
607 if (!library.empty()) {
608 switch (
609 DLM->loadLibrary(library, /*permanent*/ false, /*resolved*/ true)) {
610 case DynamicLibraryManager::kLoadLibSuccess: // Intentional fall through
612 return kSuccess;
614 assert(0 && "Cannot find library with existing canonical name!");
615 return kFailure;
616 default:
617 // Not a source file (canonical name is non-empty) but can't load.
618 return kFailure;
619 }
620 }
621 return kMoreInputExpected;
622 }
623
624 std::string toString(const char* type, void* obj) {
625 assert(0 && "toString is not implemented!");
626 std::string ret;
627 return ret; // TODO: Implement
628 }
629
630 CompilationResult undo(unsigned N = 1) {
631 if (llvm::Error Err = Undo(N)) {
632 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
633 "Failed to undo via ::undo");
634 return kFailure;
635 }
636 return kSuccess;
637 }
638
639}; // Interpreter
640} // namespace CppInternal
641
642#endif // CPPINTEROP_INTERPRETER_H
A helper class managing dynamic shared objects.
LoadLibResult loadLibrary(llvm::StringRef, bool permanent, bool resolved=false)
Loads a shared library.
@ kLoadLibAlreadyLoaded
library was already loaded
@ kLoadLibSuccess
library loaded successfully
std::string lookupLibrary(llvm::StringRef libStem, llvm::SmallVector< llvm::StringRef, 2 > RPath={}, llvm::SmallVector< llvm::StringRef, 2 > RunPath={}, llvm::StringRef libLoader="", bool variateLibStem=true) const
Looks up a library taking into account the current include paths and the system include paths.
CppInterOp Interpreter.
FILE * getRedirectionFileForOutOfProcess(int FD)
llvm::Expected< clang::PartialTranslationUnit & > Parse(llvm::StringRef Code)
DynamicLibraryManager * getDynamicLibraryManager()
Interpreter(std::unique_ptr< clang::Interpreter > CI, std::unique_ptr< IOContext > ctx=nullptr, bool oop=false)
CompilationResult declare(const std::string &input, clang::PartialTranslationUnit **PTU=nullptr)
CompilationResult loadLibrary(const std::string &filename, bool lookup)
CompilationResult undo(unsigned N=1)
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(clang::GlobalDecl GD) const
const clang::CompilerInstance * getCompilerInstance() const
llvm::Error Execute(clang::PartialTranslationUnit &T)
llvm::Error ParseAndExecute(llvm::StringRef Code, clang::Value *V=nullptr)
llvm::orc::LLJIT * getExecutionEngine() const
static std::unique_ptr< Interpreter > create(int argc, const char *const *argv, const char *llvmdir=nullptr, const std::vector< std::shared_ptr< clang::ModuleFileExtension > > &moduleExtensions={}, void *extraLibHandle=nullptr, bool noRuntime=true)
const DynamicLibraryManager * getDynamicLibraryManager() const
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(llvm::StringRef IRName) const
void AddIncludePath(llvm::StringRef PathsStr)
Adds a single include path (-I).
const clang::CompilerInstance * getCI() const
void * getAddressOfGlobal(const clang::GlobalDecl &GD) const
CompilationResult process(const std::string &input, clang::Value *V=0, clang::PartialTranslationUnit **PTU=nullptr, bool disableValuePrinting=false)
Maybe transform the input line to implement cint command line semantics (declarations are global) and...
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const
CompilationResult
Describes the return result of the different routines that do the incremental compilation.
CompilationResult evaluate(const std::string &input, clang::Value &V)
std::string toString(const char *type, void *obj)
clang::Sema & getSema() const
void AddIncludePaths(llvm::StringRef PathsStr, const char *Delim=":")
Adds multiple include paths separated by a delimiter.
void GetIncludePaths(llvm::SmallVectorImpl< std::string > &incpaths, bool withSystem, bool withFlags) const
Get the current include paths that are used.
void * getAddressOfGlobal(llvm::StringRef SymName) const
void * compileFunction(llvm::StringRef name, llvm::StringRef code, bool ifUnique, bool withAccessControl)
llvm::Error Undo(unsigned N=1)
void Named(clang::Sema *S, clang::LookupResult &R, const clang::DeclContext *Within=nullptr)
clang::NamespaceDecl * Namespace(clang::Sema *S, const char *Name, const clang::DeclContext *Within)
void CopyIncludePaths(const clang::HeaderSearchOptions &Opts, llvm::SmallVectorImpl< std::string > &incpaths, bool withSystem, bool withFlags)
Copies the current include paths into the HeaderSearchOptions.
Definition Paths.cpp:150
void AddIncludePaths(llvm::StringRef PathStr, clang::HeaderSearchOptions &HOpts, const char *Delim)
Adds multiple include paths separated by a delimiter into the given HeaderSearchOptions.
Definition Paths.cpp:337
llvm::Expected< llvm::JITTargetAddress > getSymbolAddressFromLinkerName(clang::Interpreter &I, llvm::StringRef LinkerName)
llvm::Error Undo(clang::Interpreter &I, unsigned N=1)
std::unique_ptr< clang::Interpreter > createClangInterpreter(std::vector< const char * > &args, int stdin_fd=-1, int stdout_fd=-1, int stderr_fd=-1)
llvm::orc::LLJIT * getExecutionEngine(clang::Interpreter &I)
llvm::Expected< llvm::JITTargetAddress > getSymbolAddress(clang::Interpreter &I, llvm::StringRef IRName)
std::unique_ptr< FILE, FileDeleter > stdin_file
std::unique_ptr< FILE, FileDeleter > stderr_file
std::unique_ptr< FILE, FileDeleter > stdout_file