diff options
author | Vassil Vassilev <v.g.vassilev@gmail.com> | 2025-07-19 09:25:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-19 09:25:27 +0300 |
commit | 9bf7d04c4386daf1ef0acf95782a59855c98474a (patch) | |
tree | 3230ebe6ebcb7d0240712c8bcc55fa24fe2c244b /clang/lib/Interpreter/Interpreter.cpp | |
parent | c875bb8eef6c60e7cd5814fdbab149abb86efa30 (diff) | |
download | llvm-9bf7d04c4386daf1ef0acf95782a59855c98474a.zip llvm-9bf7d04c4386daf1ef0acf95782a59855c98474a.tar.gz llvm-9bf7d04c4386daf1ef0acf95782a59855c98474a.tar.bz2 |
[clang-repl] Lay the basic infrastructure for pretty printing of types (#148701)
The idea is to store a type-value pair in clang::Value which is updated
by the interpreter runtime. The class copies builtin types and boxes
non-builtin types to provide some lifetime control.
The patch enables default printers for C and C++ using a very
minimalistic approach. We handle enums, arrays and user types. Once we
land this we can focus on enabling user-defined pretty-printers which
take control over printing of types
The work started as part of https://reviews.llvm.org/D146809, then we
created a giant in https://github.com/llvm/llvm-project/pull/84769
Diffstat (limited to 'clang/lib/Interpreter/Interpreter.cpp')
-rw-r--r-- | clang/lib/Interpreter/Interpreter.cpp | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index ed3bae5..db6a2bb 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -264,7 +264,7 @@ public: if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D)) if (TLSD && TLSD->isSemiMissing()) { auto ExprOrErr = - Interp.ExtractValueFromExpr(cast<Expr>(TLSD->getStmt())); + Interp.convertExprToValue(cast<Expr>(TLSD->getStmt())); if (llvm::Error E = ExprOrErr.takeError()) { llvm::logAllUnhandledErrors(std::move(E), llvm::errs(), "Value printing failed: "); @@ -440,11 +440,10 @@ const char *const Runtimes = R"( #define __CLANG_REPL__ 1 #ifdef __cplusplus #define EXTERN_C extern "C" - void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); struct __clang_Interpreter_NewTag{} __ci_newtag; void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; template <class T, class = T (*)() /*disable for arrays*/> - void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) { + void __clang_Interpreter_SetValueCopyArr(const T* Src, void* Placement, unsigned long Size) { for (auto Idx = 0; Idx < Size; ++Idx) new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]); } @@ -454,8 +453,12 @@ const char *const Runtimes = R"( } #else #define EXTERN_C extern + EXTERN_C void *memcpy(void *restrict dst, const void *restrict src, __SIZE_TYPE__ n); + EXTERN_C inline void __clang_Interpreter_SetValueCopyArr(const void* Src, void* Placement, unsigned long Size) { + memcpy(Placement, Src, Size); + } #endif // __cplusplus - + EXTERN_C void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); )"; @@ -470,12 +473,12 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI, // Add runtime code and set a marker to hide it from user code. Undo will not // go through that. - auto PTU = Interp->Parse(Runtimes); - if (!PTU) - return PTU.takeError(); + Err = Interp->ParseAndExecute(Runtimes); + if (Err) + return std::move(Err); + Interp->markUserCodeStart(); - Interp->ValuePrintingInfo.resize(4); return std::move(Interp); } @@ -524,12 +527,11 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, return std::move(Interp); } +CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); } const CompilerInstance *Interpreter::getCompilerInstance() const { - return CI.get(); + return const_cast<Interpreter *>(this)->getCompilerInstance(); } -CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); } - llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { if (!IncrExecutor) { if (auto Err = CreateExecutor()) @@ -610,7 +612,14 @@ Interpreter::Parse(llvm::StringRef Code) { if (!TuOrErr) return TuOrErr.takeError(); - return RegisterPTU(*TuOrErr); + PTUs.emplace_back(PartialTranslationUnit()); + PartialTranslationUnit &LastPTU = PTUs.back(); + LastPTU.TUPart = *TuOrErr; + + if (std::unique_ptr<llvm::Module> M = GenModule()) + LastPTU.TheModule = std::move(M); + + return LastPTU; } static llvm::Expected<llvm::orc::JITTargetMachineBuilder> @@ -808,10 +817,10 @@ Interpreter::GenModule(IncrementalAction *Action) { // sure it always stays empty. assert(((!CachedInCodeGenModule || !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) || - (CachedInCodeGenModule->empty() && - CachedInCodeGenModule->global_empty() && - CachedInCodeGenModule->alias_empty() && - CachedInCodeGenModule->ifunc_empty())) && + ((CachedInCodeGenModule->empty() && + CachedInCodeGenModule->global_empty() && + CachedInCodeGenModule->alias_empty() && + CachedInCodeGenModule->ifunc_empty()))) && "CodeGen wrote to a readonly module"); std::unique_ptr<llvm::Module> M(CG->ReleaseModule()); CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); @@ -828,4 +837,4 @@ CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const { return nullptr; return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator(); } -} // namespace clang +} // end namespace clang |