Skip to content

[clang-repl] Implement value printing of custom types #84769

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

vgvassilev
Copy link
Contributor

Differential revision: https://reviews.llvm.org/D146809

@vgvassilev vgvassilev self-assigned this Mar 11, 2024
Copy link

github-actions bot commented Mar 11, 2024

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff b4feb26606de84ff53d9b65a3b79c00a2b4d7c22 9554375738fcfaebab36e41f57618dafc5d7264c --extensions c,h,cpp -- clang/lib/Headers/__clang_interpreter_runtime_printvalue.h clang/lib/Interpreter/InterpreterValuePrinter.cpp clang/test/Interpreter/pretty-print.cpp clang/include/clang/AST/ASTContext.h clang/include/clang/Frontend/MultiplexConsumer.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/lib/Frontend/MultiplexConsumer.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/DeviceOffload.h clang/lib/Interpreter/IncrementalExecutor.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/InterpreterUtils.cpp clang/lib/Interpreter/InterpreterUtils.h clang/lib/Interpreter/Value.cpp clang/lib/Parse/ParseStmt.cpp clang/test/Interpreter/pretty-print.c clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CodeCompletionTest.cpp clang/unittests/Interpreter/InterpreterExtensionsTest.cpp
View the diff from clang-format here.
diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h
index 664f9e9008..c63d4236cc 100644
--- a/clang/include/clang/Interpreter/Value.h
+++ b/clang/include/clang/Interpreter/Value.h
@@ -178,7 +178,7 @@ protected:
   template <typename T> struct convertFwd {
     static T cast(const Value &V) {
       if (V.isPointerOrObjectType())
-        return *(T*)(uintptr_t)V.as<void *>();
+        return *(T *)(uintptr_t)V.as<void *>();
       if (!V.isValid() || V.isVoid()) {
         return T();
       }
diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
index df2ee3edcc..374b36db68 100644
--- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
+++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
@@ -280,13 +280,13 @@ static clang::LookupResult LookupUserDefined(Sema &S, QualType QT) {
   ASTContext &Ctx = S.getASTContext();
   if (S.getLangOpts().CPlusPlus) {
     if (auto *NSD = dyn_cast_or_null<NamespaceDecl>(LookupNamed(S, "caas")))
-      if (NamedDecl* RtD = LookupNamed(S, "runtime", NSD)) {
+      if (NamedDecl *RtD = LookupNamed(S, "runtime", NSD)) {
         Name = S.PP.getIdentifierInfo("to_string");
         LookupResult R(S, Name, SourceLocation(), Sema::LookupOrdinaryName);
         S.LookupQualifiedName(R, cast<DeclContext>(RtD)->getPrimaryContext());
         LookupResult::Filter F = R.makeFilter();
         while (F.hasNext()) {
-          NamedDecl* D = F.next();
+          NamedDecl *D = F.next();
           FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
           if (!FD && isa<FunctionTemplateDecl>(D))
             FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
@@ -325,10 +325,12 @@ static clang::LookupResult LookupUserDefined(Sema &S, QualType QT) {
 
 namespace clang {
 
-std::string Interpreter::CallUserSpecifiedPrinter(LookupResult &R, const Value &V) {
+std::string Interpreter::CallUserSpecifiedPrinter(LookupResult &R,
+                                                  const Value &V) {
   assert(!R.empty());
   // if (!R.isSingleResult())
-  //   return "{error: multiple results for '" + R.getLookupName().getAsString() +
+  //   return "{error: multiple results for '" + R.getLookupName().getAsString()
+  //   +
   //     "'}";
 
   Sema &S = getCompilerInstance()->getSema();
@@ -338,7 +340,8 @@ std::string Interpreter::CallUserSpecifiedPrinter(LookupResult &R, const Value &
   QualType RetTy = Ctx.getPointerType(Ctx.CharTy.withConst());
   if (Ctx.getLangOpts().CPlusPlus) {
     if (!S.StdNamespace)
-      return "{error: user-defined pretty printers require std::string; consider #include <string> }";
+      return "{error: user-defined pretty printers require std::string; "
+             "consider #include <string> }";
     // Find and cache std::string.
     if (S.StdNamespace && !StdString)
       StdString = LookupNamed(S, "string", S.getStdNamespace());
@@ -378,13 +381,13 @@ std::string Interpreter::CallUserSpecifiedPrinter(LookupResult &R, const Value &
     if (auto *Main = AddrOrErr->toPtr<std::string (*)()>())
       return (*Main)();
   } else {
-    if (auto *Main = AddrOrErr->toPtr<const char* (*)()>())
+    if (auto *Main = AddrOrErr->toPtr<const char *(*)()>())
       return (*Main)();
   }
   return "{Unable to print the value!}";
 }
 
-struct ValueRef: public Value {
+struct ValueRef : public Value {
   ValueRef(Interpreter *In, void *Ty) : Value(In, Ty) {
     // Tell the base class to not try to deallocate if it manages the value.
     IsManuallyAlloc = false;
@@ -403,21 +406,22 @@ std::string Interpreter::ValueDataToString(const Value &V) {
     for (unsigned Idx = 0, N = CAT->getZExtSize(); Idx < N; ++Idx) {
       QualType ElemTy = CAT->getElementType();
       ValueRef InnerV = ValueRef(this, ElemTy.getAsOpaquePtr());
-      const Type* BaseTy = CAT->getBaseElementTypeUnsafe();
+      const Type *BaseTy = CAT->getBaseElementTypeUnsafe();
       if (ElemTy->isBuiltinType()) {
         // Arrays model builtin types as a pointer to the builtin. We should
         // build the dereference to the element type if it is stored as a
         // builtin.
         InnerV.setData(V.convertTo<long double>());
       } else {
-        uintptr_t offset = (uintptr_t)V.getPtr() + Idx * Ctx.getTypeSize(BaseTy) / 8;
-        InnerV.setPtr((void*)offset);
+        uintptr_t offset =
+            (uintptr_t)V.getPtr() + Idx * Ctx.getTypeSize(BaseTy) / 8;
+        InnerV.setPtr((void *)offset);
       }
       result += ValueDataToString(InnerV);
       if (Idx < N - 1)
         result += ", ";
     }
-    result+=" }";
+    result += " }";
     return result;
   }
 

@vgvassilev
Copy link
Contributor Author

Hi @weliveindetail, I wanted to put in this PR which I am working from time to time on and will likely be very relevant for out-of-process execution. I still need to rebase it properly to the new "stuff" that landed recently. If you know how to rebase it faster, I would not mind some help...

Ideally, I'd like to implement a facility that aids interpreter-synthesized code. Right now the big ugliness is that we expose some API to the interpreter just to be able to send some code over codegen...

Another challenge is that we probably want to keep the stl type printing header slim and include only what we need from it. Perhaps looking if an include protector was defined only then include the related value printing primitives...

@vgvassilev
Copy link
Contributor Author

cc: @hahnjo, @devajithvs

The work started as part of https://reviews.llvm.org/D146809

This patch reworks a lot of the infrastructure to enable printing of types for
out-of-process execution on embedded devices.
vgvassilev added a commit to vgvassilev/llvm-project that referenced this pull request Sep 9, 2024
This patch improves the design of the IncrementalParser and Interpreter classes.
Now the incremental parser is only responsible for building the partial
translation unit declaration and the AST, while the Interpreter fills in the
lower level llvm::Module and other JIT-related infrastructure. Finally the
Interpreter class now orchestrates the AST and the LLVM IR with the
IncrementalParser and IncrementalExecutor classes.

The design improvement allows us to rework some of the logic that extracts an
interpreter value into the clang::Value object. The new implementation
simplifies use-cases which are used for out-of-process execution by allowing
interpreter to be inherited or customized with an clang::ASTConsumer.

This change will enable completing the pretty printing work which is in
llvm#84769
vgvassilev added a commit that referenced this pull request Sep 23, 2024
…ss. (#107737)

This patch improves the design of the IncrementalParser and Interpreter
classes. Now the incremental parser is only responsible for building the
partial translation unit declaration and the AST, while the Interpreter
fills in the lower level llvm::Module and other JIT-related
infrastructure. Finally the Interpreter class now orchestrates the AST
and the LLVM IR with the IncrementalParser and IncrementalExecutor
classes.

The design improvement allows us to rework some of the logic that
extracts an interpreter value into the clang::Value object. The new
implementation simplifies use-cases which are used for out-of-process
execution by allowing interpreter to be inherited or customized with an
clang::ASTConsumer.

This change will enable completing the pretty printing work which is in
#84769
@anutosh491
Copy link
Member

anutosh491 commented Jan 6, 2025

Hey @vgvassilev

Just curious to know as to what work is left here and if any help is needed for the same ?

I guess pretty printing for even the standard types might be good to have for starters.

@kr-2003
Copy link
Contributor

kr-2003 commented Apr 18, 2025

Hey, @vgvassilev

Curious to know the status of this. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants