junaire updated this revision to Diff 488158.
junaire added a comment.

Make build bots happy


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141215/new/

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/PrettyPrint.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp

Index: clang/tools/clang-repl/ClangRepl.cpp
===================================================================
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/Decl.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
@@ -18,6 +19,8 @@
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/LineEditor/LineEditor.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h" // llvm_shutdown
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetSelect.h" // llvm::Initialize*
@@ -65,6 +68,18 @@
   return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
+static void DeclareMagicFunctions(clang::Interpreter &Interp) {
+  llvm::ArrayRef<llvm::StringRef> MagicFunctions = {
+      "void __InterpreterPrettyPrint(void*, char);",
+      "void __InterpreterPrettyPrint(void*, int);",
+      "void __InterpreterPrettyPrint(void*, float);",
+      "void __InterpreterPrettyPrint(void*, double);",
+  };
+  for (llvm::StringRef Function : MagicFunctions) {
+    llvm::cantFail(Interp.ParseAndExecute(Function));
+  }
+}
+
 llvm::ExitOnError ExitOnErr;
 int main(int argc, const char **argv) {
   ExitOnErr.setBanner("clang-repl: ");
@@ -109,21 +124,57 @@
 
   bool HasError = false;
 
+  DeclareMagicFunctions(*Interp);
   if (OptInputs.empty()) {
     llvm::LineEditor LE("clang-repl");
     // FIXME: Add LE.setListCompleter
     while (llvm::Optional<std::string> Line = LE.readLine()) {
-      if (*Line == R"(%quit)")
+      llvm::StringRef Code = *Line;
+      if (Code.empty()) {
+        continue;
+      }
+      if (Code == R"(%quit)")
         break;
-      if (*Line == R"(%undo)") {
+      if (Code == R"(%undo)") {
         if (auto Err = Interp->Undo()) {
           llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
           HasError = true;
         }
         continue;
       }
+      // TODO: Find a more reliable way to determine if this is something we
+      // need to prettty print.
+      if (!Code.starts_with("//") && !Code.starts_with("#") &&
+          !Code.ends_with("}") && !Code.ends_with(";")) {
+        clang::Interpreter::PrettyPrintRAII X(*Interp);
+        // Capture the expression we want to print.
+        auto ExprOrErr = Interp->CaptureExpr(Code);
+        if (!ExprOrErr) {
+          llvm::logAllUnhandledErrors(ExprOrErr.takeError(), llvm::errs(),
+                                      "error: ");
+          HasError = true;
+        } else {
+          // Synthesize a CallExpr to `__InterpreterPrettyPrint`.
+          clang::Expr *E = Interp->SynthesizeCall(ExprOrErr.get());
+          // Generate a PartialTranslationUnit from the CallExpr.
+          llvm::Expected<clang::PartialTranslationUnit &> SynthesizedPTUOrErr =
+              Interp->GenPTU(E);
+          if (!SynthesizedPTUOrErr) {
+            llvm::logAllUnhandledErrors(SynthesizedPTUOrErr.takeError(),
+                                        llvm::errs(), "error: ");
+            HasError = true;
+          }
+          // Let JIT handle all the rest.
+          if (auto Err = Interp->Execute(SynthesizedPTUOrErr.get())) {
+            llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
+                                        "error: ");
+            HasError = true;
+          }
+        }
+        continue;
+      }
 
-      if (auto Err = Interp->ParseAndExecute(*Line)) {
+      if (auto Err = Interp->ParseAndExecute(Code)) {
         llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
         HasError = true;
       }
Index: clang/tools/clang-repl/CMakeLists.txt
===================================================================
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -12,6 +12,7 @@
   )
 
 clang_target_link_libraries(clang-repl PRIVATE
+  clangAST
   clangBasic
   clangFrontend
   clangInterpreter
Index: clang/lib/Interpreter/PrettyPrint.cpp
===================================================================
--- /dev/null
+++ clang/lib/Interpreter/PrettyPrint.cpp
@@ -0,0 +1,37 @@
+#include "clang/AST/Type.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+static void PrintType(void *OpaqueType) {
+  QualType *QT = reinterpret_cast<QualType *>(OpaqueType);
+  assert(QT && "type can't be null during value pretty printing");
+  llvm::errs() << "[" << QT->getAsString() << "]";
+}
+
+template <typename T> static void PrintImpl(void *OpaqueType, T Val) {
+  PrintType(OpaqueType);
+  llvm::errs() << ": ";
+  llvm::errs() << Val;
+  llvm::errs() << "\n";
+}
+
+LLVM_EXTERNAL_VISIBILITY void __InterpreterPrettyPrint(void *OpaqueType,
+                                                       char Val) {
+  PrintImpl(OpaqueType, Val);
+}
+
+LLVM_EXTERNAL_VISIBILITY void __InterpreterPrettyPrint(void *OpaqueType,
+                                                       int Val) {
+  PrintImpl(OpaqueType, Val);
+}
+
+LLVM_EXTERNAL_VISIBILITY void __InterpreterPrettyPrint(void *OpaqueType,
+                                                       float Val) {
+  PrintImpl(OpaqueType, Val);
+}
+
+LLVM_EXTERNAL_VISIBILITY void __InterpreterPrettyPrint(void *OpaqueType,
+                                                       double Val) {
+  PrintImpl(OpaqueType, Val);
+}
Index: clang/lib/Interpreter/Interpreter.cpp
===================================================================
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -15,8 +15,8 @@
 
 #include "IncrementalExecutor.h"
 #include "IncrementalParser.h"
-
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
@@ -28,9 +28,13 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
 
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Host.h"
 
 using namespace clang;
@@ -176,7 +180,7 @@
   llvm::ErrorAsOutParameter EAO(&Err);
   auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
   TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
-  IncrParser = std::make_unique<IncrementalParser>(std::move(CI),
+  IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI),
                                                    *TSCtx->getContext(), Err);
 }
 
@@ -283,3 +287,82 @@
   }
   return llvm::Error::success();
 }
+
+llvm::Expected<Expr *> Interpreter::CaptureExpr(llvm::StringRef Line) {
+  auto PTU = Parse(Line);
+  if (!PTU)
+    return PTU.takeError();
+  for (auto *D : PTU->TUPart->decls()) {
+    if (const auto *S = llvm::dyn_cast<clang::TopLevelStmtDecl>(D)) {
+      if (const auto *E = llvm::dyn_cast<clang::Expr>(S->getStmt())) {
+        return const_cast<Expr *>(E);
+      }
+    }
+  }
+  return llvm::make_error<llvm::StringError>("Can not capture any Expr*!",
+                                             std::error_code());
+}
+
+llvm::Expected<PartialTranslationUnit &> Interpreter::GenPTU(clang::Expr *E) {
+  Sema &S = getCompilerInstance()->getSema();
+  SmallVector<Decl *, 2> DeclsInGroup;
+  DeclsInGroup.push_back(S.ActOnTopLevelStmtDecl(E));
+  Sema::DeclGroupPtrTy DeclGroupPtr = S.BuildDeclaratorGroup(DeclsInGroup);
+  return IncrParser->Parse(DeclGroupPtr);
+}
+
+static constexpr llvm::StringRef MagicRuntimeInterface =
+    "__InterpreterPrettyPrint";
+
+bool Interpreter::FindRuntimeInterface() {
+  if (RuntimeInterface)
+    return true;
+
+  Sema &S = getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+  LookupResult R(S, &Ctx.Idents.get(MagicRuntimeInterface), SourceLocation(),
+                 Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
+  S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl());
+  if (R.empty()) {
+    return false;
+  }
+  CXXScopeSpec CSS;
+  RuntimeInterface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
+  return true;
+}
+
+static IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uintptr_t Ptr) {
+  const llvm::APInt Addr(8 * sizeof(void *), Ptr);
+  return IntegerLiteral::Create(C, Addr, C.getUIntPtrType(), SourceLocation());
+}
+
+static Expr *CStyleCastPtrExpr(Sema *S, QualType Ty, Expr *E) {
+  ASTContext &Ctx = S->getASTContext();
+  if (!Ty->isPointerType())
+    Ty = Ctx.getPointerType(Ty);
+
+  TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
+  Expr *Result =
+      S->BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E).get();
+  assert(Result && "Cannot create CStyleCastPtrExpr");
+  return Result;
+}
+
+static Expr *CStyleCastPtrExpr(Sema *S, QualType Ty, uintptr_t Ptr) {
+  ASTContext &Ctx = S->getASTContext();
+  return CStyleCastPtrExpr(S, Ty, IntegerLiteralExpr(Ctx, Ptr));
+}
+
+Expr *Interpreter::SynthesizeCall(clang::Expr *E) {
+  Sema &S = getCompilerInstance()->getSema();
+  if (!FindRuntimeInterface()) {
+    llvm_unreachable("We can't find the runtime iterface for pretty print!");
+  }
+  Expr *TypeArg = CStyleCastPtrExpr(&S, S.getASTContext().VoidPtrTy,
+                                    (uintptr_t)E->getType().getAsOpaquePtr());
+  llvm::SmallVector<Expr *, 2> Args = {TypeArg, E};
+  ExprResult Result = S.ActOnCallExpr(/*Scope=*/nullptr, RuntimeInterface,
+                                      E->getBeginLoc(), Args, E->getEndLoc());
+  assert(!Result.isInvalid() && "Failed to generate the CallExpr!");
+  return Result.get();
+}
Index: clang/lib/Interpreter/IncrementalParser.h
===================================================================
--- clang/lib/Interpreter/IncrementalParser.h
+++ clang/lib/Interpreter/IncrementalParser.h
@@ -16,7 +16,7 @@
 #include "clang/Interpreter/PartialTranslationUnit.h"
 
 #include "clang/AST/GlobalDecl.h"
-
+#include "clang/Parse/Parser.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
@@ -32,7 +32,7 @@
 class CompilerInstance;
 class IncrementalAction;
 class Parser;
-
+class Interpreter;
 /// Provides support for incremental compilation. Keeps track of the state
 /// changes between the subsequent incremental input.
 ///
@@ -49,15 +49,15 @@
   /// Consumer to process the produced top level decls. Owned by Act.
   ASTConsumer *Consumer = nullptr;
 
-  /// Counts the number of direct user input lines that have been parsed.
-  unsigned InputCount = 0;
-
   /// List containing every information about every incrementally parsed piece
   /// of code.
   std::list<PartialTranslationUnit> PTUs;
 
+  Interpreter &Interp;
+
 public:
-  IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
+  IncrementalParser(Interpreter &Interp,
+                    std::unique_ptr<CompilerInstance> Instance,
                     llvm::LLVMContext &LLVMCtx, llvm::Error &Err);
   ~IncrementalParser();
 
@@ -68,6 +68,8 @@
   /// \c TranslationUnitDecl and \c llvm::Module corresponding to the input.
   llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Input);
 
+  llvm::Expected<PartialTranslationUnit &> Parse(Parser::DeclGroupPtrTy D);
+
   /// Uses the CodeGenModule mangled name cache and avoids recomputing.
   ///\returns the mangled name of a \c GD.
   llvm::StringRef GetMangledName(GlobalDecl GD) const;
@@ -76,8 +78,8 @@
 
   std::list<PartialTranslationUnit> &getPTUs() { return PTUs; }
 
-private:
-  llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
+  llvm::Expected<PartialTranslationUnit &>
+  ParseOrWrapTopLevelDecl(Parser::DeclGroupPtrTy SynthesizedDecl = nullptr);
 };
 } // end namespace clang
 
Index: clang/lib/Interpreter/IncrementalParser.cpp
===================================================================
--- clang/lib/Interpreter/IncrementalParser.cpp
+++ clang/lib/Interpreter/IncrementalParser.cpp
@@ -19,9 +19,9 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/FrontendTool/Utils.h"
+#include "clang/Interpreter/Interpreter.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Sema/Sema.h"
-
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Error.h"
@@ -122,10 +122,11 @@
   }
 };
 
-IncrementalParser::IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
+IncrementalParser::IncrementalParser(Interpreter &Interp,
+                                     std::unique_ptr<CompilerInstance> Instance,
                                      llvm::LLVMContext &LLVMCtx,
                                      llvm::Error &Err)
-    : CI(std::move(Instance)) {
+    : CI(std::move(Instance)), Interp(Interp) {
   llvm::ErrorAsOutParameter EAO(&Err);
   Act = std::make_unique<IncrementalAction>(*CI, LLVMCtx, Err);
   if (Err)
@@ -143,7 +144,8 @@
 }
 
 llvm::Expected<PartialTranslationUnit &>
-IncrementalParser::ParseOrWrapTopLevelDecl() {
+IncrementalParser::ParseOrWrapTopLevelDecl(
+    Parser::DeclGroupPtrTy SynthesizedDecl) {
   // Recover resources if we crash before exiting this method.
   Sema &S = CI->getSema();
   llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
@@ -169,14 +171,24 @@
     S.ActOnTranslationUnitScope(P->getCurScope());
   }
 
-  Parser::DeclGroupPtrTy ADecl;
-  Sema::ModuleImportState ImportState;
-  for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
-       AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {
-    if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
-      return llvm::make_error<llvm::StringError>("Parsing failed. "
-                                                 "The consumer rejected a decl",
-                                                 std::error_code());
+  if (SynthesizedDecl) {
+    if (!Consumer->HandleTopLevelDecl(SynthesizedDecl.get())) {
+      return llvm::make_error<llvm::StringError>(
+          "Parsing failed. "
+          "The consumer rejected the synthesized decl",
+          std::error_code());
+    }
+  } else {
+    Parser::DeclGroupPtrTy ADecl;
+    Sema::ModuleImportState ImportState;
+    for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
+         AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {
+      if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
+        return llvm::make_error<llvm::StringError>(
+            "Parsing failed. "
+            "The consumer rejected a decl",
+            std::error_code());
+    }
   }
 
   DiagnosticsEngine &Diags = getCI()->getDiagnostics();
@@ -213,24 +225,41 @@
   return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
 }
 
-llvm::Expected<PartialTranslationUnit &>
-IncrementalParser::Parse(llvm::StringRef input) {
-  Preprocessor &PP = CI->getPreprocessor();
-  assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
-
+static std::unique_ptr<llvm::MemoryBuffer> MakeInputBuf(StringRef Input,
+                                                        bool NeedExtraSemi) {
+  /// Counts the number of direct user input lines that have been parsed.
+  static unsigned InputCount = 0;
   std::ostringstream SourceName;
   SourceName << "input_line_" << InputCount++;
-
   // Create an uninitialized memory buffer, copy code in and append "\n"
-  size_t InputSize = input.size(); // don't include trailing 0
+  size_t InputSize = Input.size(); // don't include trailing 0
+  size_t AllocSize = Input.size() + 1;
+
+  // Space for the extra missing semi.
+  if (NeedExtraSemi) {
+    AllocSize += 1;
+  }
+
   // MemBuffer size should *not* include terminating zero
   std::unique_ptr<llvm::MemoryBuffer> MB(
-      llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
+      llvm::WritableMemoryBuffer::getNewUninitMemBuffer(AllocSize,
                                                         SourceName.str()));
   char *MBStart = const_cast<char *>(MB->getBufferStart());
-  memcpy(MBStart, input.data(), InputSize);
-  MBStart[InputSize] = '\n';
+  memcpy(MBStart, Input.data(), InputSize);
+  if (NeedExtraSemi) {
+    MBStart[AllocSize - 2] = ';';
+  }
+  MBStart[AllocSize - 1] = '\n';
+  return MB;
+}
+
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::Parse(llvm::StringRef input) {
+  Preprocessor &PP = CI->getPreprocessor();
+  assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
 
+  std::unique_ptr<llvm::MemoryBuffer> MB =
+      MakeInputBuf(input, Interp.isPrettyPrintMode());
   SourceManager &SM = CI->getSourceManager();
 
   // FIXME: Create SourceLocation, which will allow clang to order the overload
@@ -278,6 +307,24 @@
   return PTU;
 }
 
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::Parse(Parser::DeclGroupPtrTy D) {
+  llvm::Expected<PartialTranslationUnit &> PTUOrErr =
+      ParseOrWrapTopLevelDecl(D);
+  if (!PTUOrErr) {
+    return PTUOrErr.takeError();
+  }
+  if (CodeGenerator *CG = getCodeGen(Act.get())) {
+    std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
+    CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
+                    M->getContext());
+
+    PTUOrErr.get().TheModule = std::move(M);
+  }
+
+  return PTUOrErr;
+}
+
 void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
   TranslationUnitDecl *MostRecentTU = PTU.TUPart;
   TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
Index: clang/lib/Interpreter/CMakeLists.txt
===================================================================
--- clang/lib/Interpreter/CMakeLists.txt
+++ clang/lib/Interpreter/CMakeLists.txt
@@ -12,6 +12,7 @@
   IncrementalExecutor.cpp
   IncrementalParser.cpp
   Interpreter.cpp
+  PrettyPrint.cpp
 
   DEPENDS
   intrinsics_gen
Index: clang/include/clang/Interpreter/Interpreter.h
===================================================================
--- clang/include/clang/Interpreter/Interpreter.h
+++ clang/include/clang/Interpreter/Interpreter.h
@@ -49,6 +49,8 @@
   std::unique_ptr<llvm::orc::ThreadSafeContext> TSCtx;
   std::unique_ptr<IncrementalParser> IncrParser;
   std::unique_ptr<IncrementalExecutor> IncrExecutor;
+  Expr *RuntimeInterface = nullptr;
+  bool PrettyPrintMode = false;
 
   Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err);
 
@@ -85,6 +87,26 @@
   /// file.
   llvm::Expected<llvm::JITTargetAddress>
   getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
+
+  llvm::Expected<Expr *> CaptureExpr(llvm::StringRef Line);
+
+  bool FindRuntimeInterface();
+
+  Expr *SynthesizeCall(clang::Expr *E);
+
+  llvm::Expected<PartialTranslationUnit &> GenPTU(clang::Expr *E);
+
+  bool isPrettyPrintMode() const { return PrettyPrintMode; }
+  void enterPrettyPrintMode() { PrettyPrintMode = true; }
+  void exitPrettyPrintMode() { PrettyPrintMode = false; }
+
+  struct PrettyPrintRAII {
+    Interpreter &Interp;
+    PrettyPrintRAII(Interpreter &I) : Interp(I) {
+      Interp.enterPrettyPrintMode();
+    }
+    ~PrettyPrintRAII() { Interp.exitPrettyPrintMode(); }
+  };
 };
 } // namespace clang
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to