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

Address some comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  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/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===================================================================
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector<const char *>;
 static std::unique_ptr<Interpreter>
@@ -276,8 +281,7 @@
   std::vector<const char *> Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr<Interpreter> Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-                               "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
                                "class A {};"
                                "struct B {"
                                "  template<typename T>"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr<Interpreter> Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", &V1));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", &V2));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+      "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", &V3));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", &V4));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", &V5));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===================================================================
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
     case tok::annot_module_begin:
     case tok::annot_module_end:
     case tok::annot_module_include:
+    case tok::annot_input_end:
       // Stop before we change submodules. They generally indicate a "good"
       // place to pick up parsing again (except in the special case where
       // we're trying to skip to EOF).
@@ -616,8 +617,8 @@
 
   // Skip over the EOF token, flagging end of previous input for incremental
   // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-    ConsumeToken();
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_input_end))
+    ConsumeAnnotationToken();
 
   Result = nullptr;
   switch (Tok.getKind()) {
@@ -697,6 +698,7 @@
     return false;
 
   case tok::eof:
+  case tok::annot_input_end:
     // Check whether -fmax-tokens= was reached.
     if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
       PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -543,9 +543,22 @@
     return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If we're parsing an ExprStmt and the last semicolon is missing and the
+  // incremental externsion is enabled and we're reaching the end, consider we
+  // want to do value printing. Note we shouldn't eat the token since the
+  // callback need it.
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_input_end))
+    CurTok = &Tok;
+  else
+    // Otherwise, eat the semicolon.
+    ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (!R.isInvalid() && CurTok)
+    CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2077,6 +2077,7 @@
     case tok::annot_module_begin:
     case tok::annot_module_end:
     case tok::annot_module_include:
+    case tok::annot_input_end:
       return;
 
     default:
@@ -5456,6 +5457,12 @@
 
   SmallVector<Decl *, 2> DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_input_end) && Tok.getAnnotationValue() != nullptr) {
+    ConsumeAnnotationToken();
+    cast<TopLevelStmtDecl>(DeclsInGroup.back())->setValuePrinting();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
     DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===================================================================
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -836,6 +836,7 @@
     case tok::annot_module_begin:
     case tok::annot_module_end:
     case tok::annot_module_include:
+    case tok::annot_input_end:
       // Ran out of tokens.
       return false;
 
@@ -1242,6 +1243,7 @@
     case tok::annot_module_begin:
     case tok::annot_module_end:
     case tok::annot_module_include:
+    case tok::annot_input_end:
       // Ran out of tokens.
       return false;
 
Index: clang/lib/Lex/PPLexerChange.cpp
===================================================================
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -535,13 +535,19 @@
       return LeavingSubmodule;
     }
   }
-
   // If this is the end of the main file, form an EOF token.
   assert(CurLexer && "Got EOF but no current lexer set!");
   const char *EndPos = getCurLexerEndPos();
   Result.startToken();
   CurLexer->BufferPtr = EndPos;
-  CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
+
+  if (isIncrementalProcessingEnabled()) {
+    CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_input_end);
+    Result.setAnnotationEndLoc(Result.getLocation());
+    Result.setAnnotationValue(nullptr);
+  } else {
+    CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
+  }
 
   if (isCodeCompletionEnabled()) {
     // Inserting the code-completion point increases the source buffer by 1,
Index: clang/lib/Interpreter/Value.cpp
===================================================================
--- /dev/null
+++ clang/lib/Interpreter/Value.cpp
@@ -0,0 +1,246 @@
+//===--- Interpreter.h - Incremental Compiation and Execution---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the class that used to represent a value in incremental
+// C++.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Interpreter/Value.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/Interpreter/Interpreter.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
+
+using namespace clang;
+
+namespace {
+
+// This is internal buffer maintained by Value, used to hold temporaries.
+class ValueStorage {
+public:
+  using DtorFunc = void (*)(void *);
+
+  static unsigned char *CreatePayload(void *DtorF, size_t AllocSize,
+                                      size_t ElementsSize) {
+    if (AllocSize < sizeof(Canary))
+      AllocSize = sizeof(Canary);
+    unsigned char *Buf =
+        new unsigned char[ValueStorage::getPayloadOffset() + AllocSize];
+    ValueStorage *VS = new (Buf) ValueStorage(DtorF, AllocSize, ElementsSize);
+    std::memcpy(VS->getPayload(), Canary, sizeof(Canary));
+    return VS->getPayload();
+  }
+
+  unsigned char *getPayload() { return Storage; }
+  const unsigned char *getPayload() const { return Storage; }
+
+  static unsigned getPayloadOffset() {
+    static ValueStorage Dummy(nullptr, 0, 0);
+    return Dummy.getPayload() - reinterpret_cast<unsigned char *>(&Dummy);
+  }
+
+  static ValueStorage *getFromPayload(void *Payload) {
+    ValueStorage *R = reinterpret_cast<ValueStorage *>(
+        (unsigned char *)Payload - getPayloadOffset());
+    return R;
+  }
+
+  void Retain() { ++RefCnt; }
+
+  void Release() {
+    assert(RefCnt > 0 && "Can't release if reference count is already zero");
+    if (--RefCnt == 0) {
+      // We hace a non-trivial dtor.
+      if (Dtor && IsAlive()) {
+        assert(Elements && "We at least should have 1 element in Value");
+        size_t Stride = AllocSize / Elements;
+        for (size_t Idx = 0; Idx < Elements; ++Idx)
+          (*Dtor)(getPayload() + Idx * Stride);
+      }
+      delete[] reinterpret_cast<unsigned char *>(this);
+    }
+  }
+
+  bool IsAlive() const {
+    return std::memcmp(getPayload(), Canary, sizeof(Canary)) != 0;
+  }
+
+private:
+  ValueStorage(void *DtorF, size_t AllocSize, size_t ElementsNum)
+      : RefCnt(1), Dtor(reinterpret_cast<DtorFunc>(DtorF)),
+        AllocSize(AllocSize), Elements(ElementsNum) {}
+
+  mutable unsigned RefCnt;
+  DtorFunc Dtor = nullptr;
+  size_t AllocSize = 0;
+  size_t Elements = 0;
+  unsigned char Storage[1];
+
+  static constexpr unsigned char Canary[8] = {0x4c, 0x37, 0xad, 0x8f,
+                                              0x2d, 0x23, 0x95, 0x91};
+};
+} // namespace
+
+static Value::Kind ConvertQualTypeToKind(ASTContext &Ctx, QualType QT) {
+  if (Ctx.hasSameType(QT, Ctx.VoidTy))
+    return Value::K_Void;
+
+  if (const auto *ET = dyn_cast<EnumType>(QT.getTypePtr()))
+    QT = ET->getDecl()->getIntegerType();
+
+  if (!QT->isBuiltinType() || QT->castAs<BuiltinType>()->isNullPtrType())
+    return Value::K_PtrOrObj;
+
+  switch (QT->getAs<BuiltinType>()->getKind()) {
+  default:
+    assert(false && "Type not supported");
+    return Value::K_Unspecified;
+#define X(type, name)                                                          \
+  case BuiltinType::name:                                                      \
+    return Value::K_##name;
+    REPL_BUILTIN_TYPES
+#undef X
+  }
+}
+
+Value::Value(void *In, void *Ty) : Interp(In), OpaqueType(Ty) {
+  setKind(ConvertQualTypeToKind(getASTContext(), getType()));
+  if (ValueKind == K_PtrOrObj) {
+    QualType Canon = getType().getCanonicalType();
+    if ((Canon->isPointerType() || Canon->isObjectType() ||
+         Canon->isReferenceType()) &&
+        (Canon->isRecordType() || Canon->isConstantArrayType() ||
+         Canon->isMemberPointerType())) {
+      IsManuallyAlloc = true;
+      // Compile dtor function.
+      Interpreter &Interp = getInterpreter();
+      void *DtorF = nullptr;
+      size_t ElementsSize = 1;
+      QualType DtorTy = getType();
+
+      if (const auto *ArrTy =
+              llvm::dyn_cast<ConstantArrayType>(DtorTy.getTypePtr())) {
+        DtorTy = ArrTy->getElementType();
+        llvm::APInt ArrSize(sizeof(size_t) * 8, 1);
+        do {
+          ArrSize *= ArrTy->getSize();
+          ArrTy = llvm::dyn_cast<ConstantArrayType>(
+              ArrTy->getElementType().getTypePtr());
+        } while (ArrTy);
+        ElementsSize = static_cast<size_t>(ArrSize.getZExtValue());
+      }
+      if (const auto *RT = DtorTy->getAs<RecordType>()) {
+        if (CXXRecordDecl *CXXRD =
+                llvm::dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+          if (llvm::Expected<llvm::JITTargetAddress> Addr =
+                  Interp.CompileDtorCall(CXXRD))
+            DtorF = reinterpret_cast<void *>(*Addr);
+          else
+            llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs());
+        }
+      }
+
+      size_t AllocSize =
+          getASTContext().getTypeSizeInChars(getType()).getQuantity();
+      unsigned char *Payload =
+          ValueStorage::CreatePayload(DtorF, AllocSize, ElementsSize);
+      setPtr((void *)Payload);
+    }
+  }
+}
+
+Value::Value(const Value &RHS)
+    : Interp(RHS.Interp), OpaqueType(RHS.OpaqueType), Data(RHS.Data),
+      ValueKind(RHS.ValueKind), IsManuallyAlloc(RHS.IsManuallyAlloc) {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Retain();
+}
+
+Value::Value(Value &&RHS) noexcept {
+  Interp = std::exchange(RHS.Interp, nullptr);
+  OpaqueType = std::exchange(RHS.OpaqueType, nullptr);
+  Data = RHS.Data;
+  ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
+  IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc, false);
+
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+}
+
+Value &Value::operator=(const Value &RHS) {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+
+  Interp = RHS.Interp;
+  OpaqueType = RHS.OpaqueType;
+  Data = RHS.Data;
+  ValueKind = RHS.ValueKind;
+  IsManuallyAlloc = RHS.IsManuallyAlloc;
+
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Retain();
+
+  return *this;
+}
+
+Value &Value::operator=(Value &&RHS) noexcept {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+
+  Interp = std::exchange(RHS.Interp, nullptr);
+  OpaqueType = std::exchange(RHS.OpaqueType, nullptr);
+  ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
+  IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc, false);
+
+  Data = RHS.Data;
+
+  return *this;
+}
+
+Value::~Value() {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+}
+
+void *Value::getPtr() const {
+  assert(ValueKind == K_PtrOrObj);
+  return Data.m_Ptr;
+}
+
+QualType Value::getType() const {
+  return QualType::getFromOpaquePtr(OpaqueType);
+}
+
+Interpreter &Value::getInterpreter() const {
+  assert(Interp != nullptr &&
+         "Can't get interpreter from a default constructed value");
+  return *reinterpret_cast<Interpreter *>(Interp);
+}
+
+ASTContext &Value::getASTContext() const {
+  return getInterpreter().getASTContext();
+}
+
+void Value::dump() const { print(llvm::outs()); }
+
+void Value::printType(llvm::raw_ostream &Out) const {
+  Out << "Not implement yet.\n";
+}
+void Value::printData(llvm::raw_ostream &Out) const {
+  Out << "Not implement yet.\n";
+}
+void Value::print(llvm::raw_ostream &Out) const {
+  assert(OpaqueType != nullptr && "Can't print default Value");
+  Out << "Not implement yet.\n";
+}
Index: clang/lib/Interpreter/InterpreterUtils.h
===================================================================
--- /dev/null
+++ clang/lib/Interpreter/InterpreterUtils.h
@@ -0,0 +1,55 @@
+//===--- InterpreterUtils.h - Incremental Utils --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements some common utils used in the incremental library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INTERPRETER_UTILS_H
+#define LLVM_CLANG_INTERPRETER_UTILS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "clang/Sema/Lookup.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/TargetParser/Host.h"
+
+// TODO: create a sub namespace `repl`.
+namespace clang {
+IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uintptr_t Ptr);
+
+Expr *CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E);
+
+Expr *CStyleCastPtrExpr(Sema &S, QualType Ty, uintptr_t Ptr);
+
+Sema::DeclGroupPtrTy CreateDGPtrFrom(Sema &S, Decl *D);
+
+NamespaceDecl *LookupNamespace(Sema &S, llvm::StringRef Name,
+                               const DeclContext *Within = nullptr);
+
+NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
+                       const DeclContext *Within);
+
+std::string GetFullTypeName(ASTContext &Ctx, QualType QT);
+} // namespace clang
+
+#endif
Index: clang/lib/Interpreter/InterpreterUtils.cpp
===================================================================
--- /dev/null
+++ clang/lib/Interpreter/InterpreterUtils.cpp
@@ -0,0 +1,111 @@
+//===--- InterpreterUtils.cpp - Incremental Utils --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements some common utils used in the incremental library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InterpreterUtils.h"
+
+namespace clang {
+
+IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uintptr_t Ptr) {
+  const llvm::APInt Addr(8 * sizeof(void *), Ptr);
+  return IntegerLiteral::Create(C, Addr, C.getUIntPtrType(), SourceLocation());
+}
+
+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;
+}
+
+Expr *CStyleCastPtrExpr(Sema &S, QualType Ty, uintptr_t Ptr) {
+  ASTContext &Ctx = S.getASTContext();
+  return CStyleCastPtrExpr(S, Ty, IntegerLiteralExpr(Ctx, Ptr));
+}
+
+Sema::DeclGroupPtrTy CreateDGPtrFrom(Sema &S, Decl *D) {
+  SmallVector<Decl *, 1> DeclsInGroup;
+  DeclsInGroup.push_back(D);
+  Sema::DeclGroupPtrTy DeclGroupPtr = S.BuildDeclaratorGroup(DeclsInGroup);
+  return DeclGroupPtr;
+}
+
+NamespaceDecl *LookupNamespace(Sema &S, llvm::StringRef Name,
+                               const DeclContext *Within) {
+  DeclarationName DName = &S.Context.Idents.get(Name);
+  LookupResult R(S, DName, SourceLocation(),
+                 Sema::LookupNestedNameSpecifierName);
+  R.suppressDiagnostics();
+  if (!Within)
+    S.LookupName(R, S.TUScope);
+  else {
+    if (const clang::TagDecl *TD = dyn_cast<clang::TagDecl>(Within))
+      if (!TD->getDefinition())
+        // No definition, no lookup result.
+        return nullptr;
+
+    S.LookupQualifiedName(R, const_cast<DeclContext *>(Within));
+  }
+
+  if (R.empty())
+    return nullptr;
+
+  R.resolveKind();
+
+  return dyn_cast<NamespaceDecl>(R.getFoundDecl());
+}
+
+NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
+                       const DeclContext *Within) {
+  DeclarationName DName = &S.Context.Idents.get(Name);
+  LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
+                 Sema::ForVisibleRedeclaration);
+
+  R.suppressDiagnostics();
+
+  if (!Within)
+    S.LookupName(R, S.TUScope);
+  else {
+    const DeclContext *PrimaryWithin = nullptr;
+    if (const auto *TD = dyn_cast<TagDecl>(Within))
+      PrimaryWithin = llvm::dyn_cast_or_null<DeclContext>(TD->getDefinition());
+    else
+      PrimaryWithin = Within->getPrimaryContext();
+
+    // No definition, no lookup result.
+    if (!PrimaryWithin)
+      return nullptr;
+
+    S.LookupQualifiedName(R, const_cast<DeclContext *>(PrimaryWithin));
+  }
+
+  if (R.empty())
+    return nullptr;
+  R.resolveKind();
+
+  if (R.isSingleResult())
+    return llvm::dyn_cast<NamedDecl>(R.getFoundDecl());
+
+  return nullptr;
+}
+
+std::string GetFullTypeName(ASTContext &Ctx, QualType QT) {
+  PrintingPolicy Policy(Ctx.getPrintingPolicy());
+  Policy.SuppressScope = false;
+  Policy.AnonymousTagLocations = false;
+  return QT.getAsString(Policy);
+}
+} // namespace clang
Index: clang/lib/Interpreter/Interpreter.cpp
===================================================================
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -16,7 +16,11 @@
 #include "IncrementalExecutor.h"
 #include "IncrementalParser.h"
 
+#include "InterpreterUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
@@ -27,13 +31,15 @@
 #include "clang/Driver/Tool.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Lex/PreprocessorOptions.h"
-
+#include "clang/Sema/Lookup.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
-
 using namespace clang;
 
 // FIXME: Figure out how to unify with namespace init_convenience from
@@ -177,7 +183,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);
 }
 
@@ -190,6 +196,28 @@
   }
 }
 
+// These better to put in a runtime header but we can't. This is because we
+// can't find the precise resource directory in unittests so we have to hard
+// code them.
+const char *const Runtimes = R"(
+    #include <new>
+    void *__InterpreterSetValueWithAlloc(void*, void*, void*);
+    void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);
+    void __InterpreterSetValueNoAlloc(void*, void*, void*, float);
+    void __InterpreterSetValueNoAlloc(void*, void*, void*, double);
+    void __InterpreterSetValueNoAlloc(void*, void*, void*, long double);
+    void __InterpreterSetValueNoAlloc(void*,void*,void*,unsigned long long);
+    template <class T, class = T (*)() /*disable for arrays*/>
+    void __InterpreterSetValueCopyArr(T* Src, void* Placement, std::size_t Size) {
+      for (auto Idx = 0; Idx < Size; ++Idx)
+        new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]);
+    }
+    template <class T, std::size_t N>
+    void __InterpreterSetValueCopyArr(const T (*Src)[N], void* Placement, std::size_t Size) {
+      __InterpreterSetValueCopyArr(Src[0], Placement, Size);
+    }
+)";
+
 llvm::Expected<std::unique_ptr<Interpreter>>
 Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
   llvm::Error Err = llvm::Error::success();
@@ -197,6 +225,14 @@
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
+  if (llvm::Error Err = Interp->ParseAndExecute(Runtimes))
+    return std::move(Err);
+
+  Interp->ValuePrintingInfo.resize(3);
+  // FIXME: This is a ugly hack. Undo command checks its availability by looking
+  // at the size of the PTU list. However we have parsed something in the
+  // beginning of the REPL so we have to mark them as 'Irrevocable'.
+  Interp->InitPTUSize = Interp->getPTUs().size();
   return std::move(Interp);
 }
 
@@ -213,8 +249,24 @@
   return IncrExecutor->GetExecutionEngine();
 }
 
+ASTContext &Interpreter::getASTContext() const {
+  return getCompilerInstance()->getASTContext();
+}
+
+std::list<PartialTranslationUnit> &Interpreter::getPTUs() {
+  return IncrParser->getPTUs();
+}
+
+std::unique_ptr<llvm::Module> Interpreter::GenModule() {
+  return IncrParser->GenModule();
+}
+
 llvm::Expected<PartialTranslationUnit &>
 Interpreter::Parse(llvm::StringRef Code) {
+  // Tell the interpreter sliently ignore unused expressions since value
+  // printing could cause it.
+  getCompilerInstance()->getDiagnostics().setSeverity(
+      clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
   return IncrParser->Parse(Code);
 }
 
@@ -229,15 +281,14 @@
   return Err;
 }
 
-llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
-  assert(T.TheModule);
+llvm::Error Interpreter::Execute(PartialTranslationUnit &PTU) {
   if (!IncrExecutor) {
     auto Err = CreateExecutor();
     if (Err)
       return Err;
   }
   // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
-  if (auto Err = IncrExecutor->addModule(T))
+  if (auto Err = IncrExecutor->addModule(PTU))
     return Err;
 
   if (auto Err = IncrExecutor->runCtors())
@@ -246,6 +297,24 @@
   return llvm::Error::success();
 }
 
+llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
+
+  auto PTU = Parse(Code);
+  if (!PTU)
+    return PTU.takeError();
+  if (PTU->TheModule)
+    if (llvm::Error Err = Execute(*PTU))
+      return Err;
+
+  if (LastValue.isValid()) {
+    if (!V)
+      LastValue.dump();
+    else
+      *V = std::move(LastValue);
+  }
+  return llvm::Error::success();
+}
+
 llvm::Expected<llvm::JITTargetAddress>
 Interpreter::getSymbolAddress(GlobalDecl GD) const {
   if (!IncrExecutor)
@@ -279,7 +348,7 @@
 llvm::Error Interpreter::Undo(unsigned N) {
 
   std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
-  if (N > PTUs.size())
+  if (N + InitPTUSize > PTUs.size())
     return llvm::make_error<llvm::StringError>("Operation failed. "
                                                "Too many undos",
                                                std::error_code());
@@ -310,3 +379,314 @@
 
   return llvm::Error::success();
 }
+
+static std::string MangleName(ASTContext &C, GlobalDecl GD) {
+  std::unique_ptr<MangleContext> MangleC(C.createMangleContext());
+  std::string mangledName;
+  llvm::raw_string_ostream RawStr(mangledName);
+  MangleC->mangleName(GD, RawStr);
+  return RawStr.str();
+}
+
+llvm::Expected<llvm::JITTargetAddress>
+Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
+  assert(CXXRD && "Cannot compile a destructor for a nullptr");
+  // Take a a RD, get its dtor address using JIT, and store the function ptr.
+  if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
+    return Dtor->getSecond();
+
+  if (CXXRD->hasIrrelevantDestructor())
+    return llvm::JITTargetAddress{};
+
+  CXXDestructorDecl *DtorRD =
+      getCompilerInstance()->getSema().LookupDestructor(CXXRD);
+
+  std::string Name = MangleName(getASTContext(), GlobalDecl(DtorRD, Dtor_Base));
+  auto AddrOrErr = getSymbolAddress(Name);
+  if (!AddrOrErr)
+    return AddrOrErr.takeError();
+
+  Dtors[CXXRD] = *AddrOrErr;
+  return AddrOrErr;
+}
+
+static constexpr llvm::StringRef MagicRuntimeInterface[] = {
+    "__InterpreterSetValueNoAlloc", "__InterpreterSetValueWithAlloc",
+    "__InterpreterSetValueCopyArr"};
+
+bool Interpreter::FindRuntimeInterface() {
+  if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
+    return true;
+
+  Sema &S = getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+
+  auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
+    LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
+                   Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
+    S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl());
+    if (R.empty())
+      return false;
+
+    CXXScopeSpec CSS;
+    Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
+    return true;
+  };
+
+  if (!LookupInterface(ValuePrintingInfo[NoAlloc],
+                       MagicRuntimeInterface[NoAlloc]))
+    return false;
+  if (!LookupInterface(ValuePrintingInfo[WithAlloc],
+                       MagicRuntimeInterface[WithAlloc]))
+    return false;
+  if (!LookupInterface(ValuePrintingInfo[CopyArray],
+                       MagicRuntimeInterface[CopyArray]))
+    return false;
+  return true;
+}
+
+namespace {
+
+class RuntimeInterfaceBuilder
+    : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> {
+  clang::Interpreter &Interp;
+  ASTContext &Ctx;
+  Sema &S;
+  Expr *E;
+  llvm::SmallVector<Expr *, 3> Args;
+
+public:
+  RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef,
+                          Expr *VE, ArrayRef<Expr *> FixedArgs)
+      : Interp(In), Ctx(C), S(SemaRef), E(VE) {
+    // The Interpreter* parameter and the out parameter `OutVal`.
+    for (Expr *E : FixedArgs)
+      Args.push_back(E);
+
+    // Get rid of ExprWithCleanups.
+    if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
+      E = EWC->getSubExpr();
+  }
+
+  ExprResult getCall() {
+    QualType Ty = E->getType();
+    QualType DesugaredTy = Ty.getDesugaredType(Ctx);
+
+    // For lvalue struct, we treat it as a reference.
+    if (DesugaredTy->isRecordType() && E->isLValue()) {
+      DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
+      Ty = Ctx.getLValueReferenceType(Ty);
+    }
+
+    Expr *TypeArg =
+        CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr());
+    // The QualType parameter `OpaqueType`, represented as `void*`.
+    Args.push_back(TypeArg);
+
+    // We push the last parameter based on the type of the Expr. Note we need
+    // special care for rvalue struct.
+    Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy);
+    switch (Kind) {
+    case Interpreter::InterfaceKind::WithAlloc:
+    case Interpreter::InterfaceKind::CopyArray: {
+      // __InterpreterSetValueWithAlloc(ThisInterp, OpaqueValue, OpaqueType)
+      ExprResult AllocCall = S.ActOnCallExpr(
+          /*Scope=*/nullptr,
+          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
+          E->getBeginLoc(), Args, E->getEndLoc());
+      assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
+
+      TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
+
+      // Force CodeGen to emit destructor.
+      if (auto *RD = Ty->getAsCXXRecordDecl()) {
+        auto *Dtor = S.LookupDestructor(RD);
+        Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
+        Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
+            DeclGroupRef(Dtor));
+      }
+
+      // __InterpreterSetValueCopyArr(T* Src, void* Placement, std::size_t Size)
+      if (Kind == Interpreter::InterfaceKind::CopyArray) {
+        const auto *ConstantArrTy =
+            cast<ConstantArrayType>(DesugaredTy.getTypePtr());
+        size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy);
+        Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize);
+        Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
+        return S.ActOnCallExpr(
+            /*Scope *=*/nullptr,
+            Interp
+                .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
+            SourceLocation(), Args, SourceLocation());
+      }
+      Expr *Args[] = {AllocCall.get()};
+      ExprResult CXXNewCall = S.BuildCXXNew(
+          E->getSourceRange(),
+          /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
+          /*PlacementRParen=*/SourceLocation(),
+          /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
+          E->getSourceRange(), E);
+
+      assert(!CXXNewCall.isInvalid() &&
+             "Can't create runtime placement new call!");
+
+      return S.ActOnFinishFullExpr(CXXNewCall.get(),
+                                   /*DiscardedValue=*/false);
+    }
+      // __InterpreterSetValueNoAlloc(ThisInterp, OpaqueValue, QT, E)
+    case Interpreter::InterfaceKind::NoAlloc: {
+      return S.ActOnCallExpr(
+          /*Scope=*/nullptr,
+          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
+          E->getBeginLoc(), Args, E->getEndLoc());
+    }
+      llvm_unreachable("Unknown runtime interface kind");
+    }
+  }
+
+  Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
+    return Interpreter::InterfaceKind::WithAlloc;
+  }
+
+  Interpreter::InterfaceKind
+  VisitMemberPointerType(const MemberPointerType *Ty) {
+    llvm_unreachable("Not implemented yet");
+  }
+  Interpreter::InterfaceKind
+  VisitConstantArrayType(const ConstantArrayType *Ty) {
+    return Interpreter::InterfaceKind::CopyArray;
+  }
+
+  Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
+    TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy);
+    ExprResult CastedExpr =
+        S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E);
+    assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
+    Args.push_back(CastedExpr.get());
+    return Interpreter::InterfaceKind::NoAlloc;
+  }
+
+  Interpreter::InterfaceKind VisitReferenceType(const ReferenceType *Ty) {
+    ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
+    assert(!AddrOfE.isInvalid() && "Can not create unary expression");
+    Args.push_back(AddrOfE.get());
+    return Interpreter::InterfaceKind::NoAlloc;
+  }
+
+  Interpreter::InterfaceKind VisitBuiltinType(const BuiltinType *Ty) {
+    if (Ty->isNullPtrType())
+      Args.push_back(E);
+    else if (Ty->isFloatingType())
+      Args.push_back(E);
+    else if (Ty->isVoidType())
+      Args.push_back(E);
+    else if (Ty->isIntegralOrEnumerationType())
+      HandleIntegralOrEnumType(Ty);
+
+    return Interpreter::InterfaceKind::NoAlloc;
+  }
+
+  Interpreter::InterfaceKind VisitEnumType(const EnumType *Ty) {
+    HandleIntegralOrEnumType(Ty);
+    return Interpreter::InterfaceKind::NoAlloc;
+  }
+
+private:
+  // Force cast these types to uint64 to reduce the number of overloads of
+  // `__InterpreterSetValueNoAlloc`.
+  void HandleIntegralOrEnumType(const Type *Ty) {
+    TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ctx.UnsignedLongLongTy);
+    ExprResult CastedExpr =
+        S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E);
+    assert(!CastedExpr.isInvalid() && "Cannot create cstyle cast expr");
+    Args.push_back(CastedExpr.get());
+  }
+};
+} // namespace
+
+// This synthesizes a call expression to a speciall
+// function that is responsible for generating the Value.
+// In general, we transform:
+//   clang-repl> x
+// To:
+//   // 1. If x is a built-in type like int, float.
+//   __InterpreterSetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
+//   // 2. If x is a struct, and a lvalue.
+//   __InterpreterSetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, &x);
+//   // 3. If x is a struct, but a rvalue.
+//   new (__InterpreterSetValueWithAlloc(ThisInterp, OpaqueValue, xQualType))
+//   (x);
+
+Expr *Interpreter::SynthesizeExpr(clang::Expr *E) {
+  Sema &S = getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+
+  if (!FindRuntimeInterface())
+    llvm_unreachable("We can't find the runtime iterface for pretty print!");
+
+  // Create parameter `ThisInterp` for `__InterpreterSetValue*`
+  auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
+
+  // Create parameter `OutVal` for `__InterpreterSetValue*`
+  auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
+
+  // Build `__InterpreterSetValue*` call.
+  RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});
+
+  ExprResult Result = Builder.getCall();
+  assert(!Result.isInvalid() && "Failed to generate the CallExpr!");
+  return Result.get();
+}
+
+// Temporary rvalue struct that need special care.
+REPL_EXTERNAL_VISIBILITY void *
+__InterpreterSetValueWithAlloc(void *This, void *OutVal, void *OpaqueType) {
+  Value &VRef = *(Value *)OutVal;
+  VRef = Value(This, OpaqueType);
+  return VRef.getPtr();
+}
+
+// Pointers, lvalue struct that can take as a reference.
+REPL_EXTERNAL_VISIBILITY void __InterpreterSetValueNoAlloc(void *This,
+                                                           void *OutVal,
+                                                           void *OpaqueType,
+                                                           void *Val) {
+  Value &VRef = *(Value *)OutVal;
+  VRef = Value(This, OpaqueType);
+  VRef.setPtr(Val);
+}
+
+REPL_EXTERNAL_VISIBILITY void
+__InterpreterSetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
+                             unsigned long long Val) {
+  Value &VRef = *(Value *)OutVal;
+  VRef = Value(This, OpaqueType);
+  VRef.setULongLong(Val);
+}
+
+REPL_EXTERNAL_VISIBILITY void __InterpreterSetValueNoAlloc(void *This,
+                                                           void *OutVal,
+                                                           void *OpaqueType,
+                                                           float Val) {
+  Value &VRef = *(Value *)OutVal;
+  VRef = Value(This, OpaqueType);
+  VRef.setFloat(Val);
+}
+
+REPL_EXTERNAL_VISIBILITY void __InterpreterSetValueNoAlloc(void *This,
+                                                           void *OutVal,
+                                                           void *OpaqueType,
+                                                           double Val) {
+  Value &VRef = *(Value *)OutVal;
+  VRef = Value(This, OpaqueType);
+  VRef.setDouble(Val);
+}
+
+REPL_EXTERNAL_VISIBILITY void __InterpreterSetValueNoAlloc(void *This,
+                                                           void *OutVal,
+                                                           void *OpaqueType,
+                                                           long double Val) {
+  Value &VRef = *(Value *)OutVal;
+  VRef = Value(This, OpaqueType);
+  VRef.setLongDouble(Val);
+}
Index: clang/lib/Interpreter/IncrementalParser.h
===================================================================
--- clang/lib/Interpreter/IncrementalParser.h
+++ clang/lib/Interpreter/IncrementalParser.h
@@ -16,7 +16,6 @@
 #include "clang/Interpreter/PartialTranslationUnit.h"
 
 #include "clang/AST/GlobalDecl.h"
-
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
@@ -29,10 +28,11 @@
 
 namespace clang {
 class ASTConsumer;
+class CodeGenerator;
 class CompilerInstance;
 class IncrementalAction;
 class Parser;
-
+class Interpreter;
 /// Provides support for incremental compilation. Keeps track of the state
 /// changes between the subsequent incremental input.
 ///
@@ -57,7 +57,8 @@
   std::list<PartialTranslationUnit> PTUs;
 
 public:
-  IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
+  IncrementalParser(Interpreter &Interp,
+                    std::unique_ptr<CompilerInstance> Instance,
                     llvm::LLVMContext &LLVMCtx, llvm::Error &Err);
   ~IncrementalParser();
 
@@ -76,7 +77,7 @@
 
   std::list<PartialTranslationUnit> &getPTUs() { return PTUs; }
 
-private:
+  std::unique_ptr<llvm::Module> GenModule();
   llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
 };
 } // end namespace clang
Index: clang/lib/Interpreter/IncrementalParser.cpp
===================================================================
--- clang/lib/Interpreter/IncrementalParser.cpp
+++ clang/lib/Interpreter/IncrementalParser.cpp
@@ -11,7 +11,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "IncrementalParser.h"
-
 #include "clang/AST/DeclContextInternals.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/CodeGenAction.h"
@@ -19,9 +18,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"
@@ -31,6 +30,83 @@
 
 namespace clang {
 
+class IncrementalASTConsumer final : public ASTConsumer {
+  Interpreter &Interp;
+  std::unique_ptr<ASTConsumer> Consumer;
+
+public:
+  IncrementalASTConsumer(Interpreter &InterpRef, std::unique_ptr<ASTConsumer> C)
+      : Interp(InterpRef), Consumer(std::move(C)) {}
+
+  bool HandleTopLevelDecl(DeclGroupRef DGR) override final {
+    if (DGR.isNull())
+      return true;
+    if (!Consumer)
+      return true;
+
+    for (Decl *D : DGR)
+      if (auto *TSD = llvm::dyn_cast<TopLevelStmtDecl>(D);
+          TSD && TSD->isValuePrinting())
+        TSD->setStmt(Interp.SynthesizeExpr(cast<Expr>(TSD->getStmt())));
+
+    return Consumer->HandleTopLevelDecl(DGR);
+  }
+  void HandleTranslationUnit(ASTContext &Ctx) override final {
+    Consumer->HandleTranslationUnit(Ctx);
+  }
+  void Initialize(ASTContext &Context) override final {
+    // FIXME
+    // Consumer->Initialize(Context);
+  }
+  void HandleInlineFunctionDefinition(FunctionDecl *D) override final {
+    Consumer->HandleInlineFunctionDefinition(D);
+  }
+  void HandleInterestingDecl(DeclGroupRef D) override final {
+    Consumer->HandleInterestingDecl(D);
+  }
+  void HandleTagDeclDefinition(TagDecl *D) override final {
+    Consumer->HandleTagDeclDefinition(D);
+  }
+  void HandleTagDeclRequiredDefinition(const TagDecl *D) override final {
+    Consumer->HandleTagDeclRequiredDefinition(D);
+  }
+  void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override final {
+    Consumer->HandleCXXImplicitFunctionInstantiation(D);
+  }
+  void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override final {
+    Consumer->HandleTopLevelDeclInObjCContainer(D);
+  }
+  void HandleImplicitImportDecl(ImportDecl *D) override final {
+    Consumer->HandleImplicitImportDecl(D);
+  }
+  void CompleteTentativeDefinition(VarDecl *D) override final {
+    Consumer->CompleteTentativeDefinition(D);
+  }
+  void CompleteExternalDeclaration(VarDecl *D) override final {
+    Consumer->CompleteExternalDeclaration(D);
+  }
+  void AssignInheritanceModel(CXXRecordDecl *RD) override final {
+    Consumer->AssignInheritanceModel(RD);
+  }
+  void HandleCXXStaticMemberVarInstantiation(VarDecl *D) override final {
+    Consumer->HandleCXXStaticMemberVarInstantiation(D);
+  }
+  void HandleVTable(CXXRecordDecl *RD) override final {
+    Consumer->HandleVTable(RD);
+  }
+  ASTMutationListener *GetASTMutationListener() override final {
+    return Consumer->GetASTMutationListener();
+  }
+  ASTDeserializationListener *GetASTDeserializationListener() override final {
+    return Consumer->GetASTDeserializationListener();
+  }
+  void PrintStats() override final { Consumer->PrintStats(); }
+  bool shouldSkipFunctionBody(Decl *D) override final {
+    return Consumer->shouldSkipFunctionBody(D);
+  }
+  static bool classof(const clang::ASTConsumer *) { return true; }
+};
+
 /// A custom action enabling the incremental processing functionality.
 ///
 /// The usual \p FrontendAction expects one call to ExecuteAction and once it
@@ -122,7 +198,8 @@
   }
 };
 
-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)) {
@@ -131,6 +208,9 @@
   if (Err)
     return;
   CI->ExecuteAction(*Act);
+  std::unique_ptr<ASTConsumer> IncrConsumer =
+      std::make_unique<IncrementalASTConsumer>(Interp, CI->takeASTConsumer());
+  CI->setASTConsumer(std::move(IncrConsumer));
   Consumer = &CI->getASTConsumer();
   P.reset(
       new Parser(CI->getPreprocessor(), CI->getSema(), /*SkipBodies=*/false));
@@ -158,8 +238,8 @@
   LastPTU.TUPart = C.getTranslationUnitDecl();
 
   // Skip previous eof due to last incremental input.
-  if (P->getCurToken().is(tok::eof)) {
-    P->ConsumeToken();
+  if (P->getCurToken().is(tok::annot_input_end)) {
+    P->ConsumeAnyToken();
     // FIXME: Clang does not call ExitScope on finalizing the regular TU, we
     // might want to do that around HandleEndOfTranslationUnit.
     P->ExitScope();
@@ -259,25 +339,30 @@
     Token Tok;
     do {
       PP.Lex(Tok);
-    } while (Tok.isNot(tok::eof));
+    } while (Tok.isNot(tok::annot_input_end));
   }
 
   Token AssertTok;
   PP.Lex(AssertTok);
-  assert(AssertTok.is(tok::eof) &&
+  assert(AssertTok.is(tok::annot_input_end) &&
          "Lexer must be EOF when starting incremental parse!");
 
-  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());
-
+  if (std::unique_ptr<llvm::Module> M = GenModule())
     PTU->TheModule = std::move(M);
-  }
 
   return PTU;
 }
 
+std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {
+  static unsigned ID = 0;
+  if (CodeGenerator *CG = getCodeGen(Act.get())) {
+    std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
+    CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
+    return M;
+  }
+  return nullptr;
+}
+
 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,8 @@
   IncrementalExecutor.cpp
   IncrementalParser.cpp
   Interpreter.cpp
+  Value.cpp
+  InterpreterUtils.cpp
 
   DEPENDS
   intrinsics_gen
Index: clang/lib/Frontend/PrintPreprocessedOutput.cpp
===================================================================
--- clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -663,7 +663,8 @@
   // them.
   if (Tok.is(tok::eof) ||
       (Tok.isAnnotation() && !Tok.is(tok::annot_header_unit) &&
-       !Tok.is(tok::annot_module_begin) && !Tok.is(tok::annot_module_end)))
+       !Tok.is(tok::annot_module_begin) && !Tok.is(tok::annot_module_end) &&
+       !Tok.is(tok::annot_input_end)))
     return;
 
   // EmittedDirectiveOnThisLine takes priority over RequireSameLine.
@@ -819,6 +820,9 @@
       // -traditional-cpp the lexer keeps /all/ whitespace, including comments.
       PP.Lex(Tok);
       continue;
+    } else if (Tok.is(tok::annot_input_end)) {
+      PP.Lex(Tok);
+      continue;
     } else if (Tok.is(tok::eod)) {
       // Don't print end of directive tokens, since they are typically newlines
       // that mess up our line tracking. These come from unknown pre-processor
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -7216,8 +7216,14 @@
 }
 
 void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) {
-  assert(DeferredDeclsToEmit.empty() &&
-         "Should have emitted all decls deferred to emit.");
+  // FIXME: Re-enable the assertions once we fix regular codegen to not leave
+  // weak references behind.
+  // The code example also leaves entries in WeakRefReferences in regular clang.
+  // #include <memory>
+  // auto p = std::make_shared<int>(42);
+  //
+  // assert(DeferredDeclsToEmit.empty() &&
+  //        "Should have emitted all decls deferred to emit.");
   assert(NewBuilder->DeferredDecls.empty() &&
          "Newly created module should not have deferred decls");
   NewBuilder->DeferredDecls = std::move(DeferredDecls);
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -692,7 +692,8 @@
   bool isEofOrEom() {
     tok::TokenKind Kind = Tok.getKind();
     return Kind == tok::eof || Kind == tok::annot_module_begin ||
-           Kind == tok::annot_module_end || Kind == tok::annot_module_include;
+           Kind == tok::annot_module_end || Kind == tok::annot_module_include ||
+           Kind == tok::annot_input_end;
   }
 
   /// Checks if the \p Level is valid for use in a fold expression.
Index: clang/include/clang/Interpreter/Value.h
===================================================================
--- /dev/null
+++ clang/include/clang/Interpreter/Value.h
@@ -0,0 +1,174 @@
+//===--- Value.h - Incremental Compiation and Execution---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the class that used to represent a value in incremental
+// C++.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INTERPRETER_VALUE_H
+#define LLVM_CLANG_INTERPRETER_VALUE_H
+
+#include <cstdint>
+
+namespace llvm {
+class raw_ostream;
+
+} // namespace llvm
+
+namespace clang {
+
+class ASTContext;
+class Interpreter;
+
+#if __has_attribute(visibility) &&                                             \
+    (!(defined(_WIN32) || defined(__CYGWIN__)) ||                              \
+     (defined(__MINGW32__) && defined(__clang__)))
+#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
+#define REPL_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
+#else
+#define REPL_EXTERNAL_VISIBILITY
+#endif
+#else
+#if defined(_WIN32)
+#define REPL_EXTERNAL_VISIBILITY __declspec(dllexport)
+#endif
+#endif
+
+class Interpreter;
+class QualType;
+
+#define REPL_BUILTIN_TYPES                                                     \
+  X(bool, Bool)                                                                \
+  X(char, Char_S)                                                              \
+  X(signed char, SChar)                                                        \
+  X(unsigned char, UChar)                                                      \
+  X(short, Short)                                                              \
+  X(unsigned short, UShort)                                                    \
+  X(int, Int)                                                                  \
+  X(unsigned int, UInt)                                                        \
+  X(long, Long)                                                                \
+  X(unsigned long, ULong)                                                      \
+  X(long long, LongLong)                                                       \
+  X(unsigned long long, ULongLong)                                             \
+  X(float, Float)                                                              \
+  X(double, Double)                                                            \
+  X(long double, LongDouble)
+
+class REPL_EXTERNAL_VISIBILITY Value {
+  union Storage {
+#define X(type, name) type m_##name;
+    REPL_BUILTIN_TYPES
+#undef X
+    void *m_Ptr;
+  };
+
+public:
+  enum Kind {
+#define X(type, name) K_##name,
+    REPL_BUILTIN_TYPES
+#undef X
+
+        K_Void,
+    K_PtrOrObj,
+    K_Unspecified
+  };
+
+  Value() = default;
+  Value(void /*Interpreter*/ *In, void /*QualType*/ *Ty);
+  Value(const Value &RHS);
+  Value(Value &&RHS) noexcept;
+  Value &operator=(const Value &RHS);
+  Value &operator=(Value &&RHS) noexcept;
+  ~Value();
+
+  void printType(llvm::raw_ostream &Out) const;
+  void printData(llvm::raw_ostream &Out) const;
+  void print(llvm::raw_ostream &Out) const;
+  void dump() const;
+
+  ASTContext &getASTContext() const;
+  QualType getType() const;
+  Interpreter &getInterpreter() const;
+
+  bool isValid() const { return ValueKind != K_Unspecified; }
+  bool isVoid() const { return ValueKind == K_Void; }
+  bool isManuallyAlloc() const { return IsManuallyAlloc; }
+  Kind getKind() const { return ValueKind; }
+  void setKind(Kind K) { ValueKind = K; }
+  void setOpaqueType(void *Ty) { OpaqueType = Ty; }
+
+  void *getPtr() const;
+  void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
+
+  bool isPointerOrObjectType() const { return ValueKind == K_PtrOrObj; }
+
+#define X(type, name)                                                          \
+  void set##name(type Val) { Data.m_##name = Val; }                            \
+  type get##name() const { return Data.m_##name; }
+  REPL_BUILTIN_TYPES
+#undef X
+
+  // Allow castAs to be partially specialized.
+  template <typename T> struct CastFwd {
+    static T cast(const Value &V) {
+      if (V.isPointerOrObjectType())
+        return (T)(uintptr_t)V.getAs<void *>();
+      if (!V.isValid() || V.isVoid()) {
+        return T();
+      }
+      return V.getAs<T>();
+    }
+  };
+
+  template <typename T> struct CastFwd<T *> {
+    static T *cast(const Value &V) {
+      if (V.isPointerOrObjectType())
+        return (T *)(uintptr_t)V.getAs<void *>();
+      return nullptr;
+    }
+  };
+
+  /// \brief Get the value with cast.
+  //
+  /// Get the value cast to T. This is similar to reinterpret_cast<T>(value),
+  /// casting the value of builtins (except void), enums and pointers.
+  /// Values referencing an object are treated as pointers to the object.
+  template <typename T> T castAs() const { return CastFwd<T>::cast(*this); }
+
+  /// \brief Get to the value with type checking casting the underlying
+  /// stored value to T.
+  template <typename T> T getAs() const {
+    switch (ValueKind) {
+    default:
+      return T();
+#define X(type, name)                                                          \
+  case Value::K_##name:                                                        \
+    return (T)Data.m_##name;
+      REPL_BUILTIN_TYPES
+#undef X
+    }
+  }
+
+private:
+  // Interpreter, QualType are stored as void* to reduce dependencies.
+  void *Interp = nullptr;
+  void *OpaqueType = nullptr;
+  Storage Data;
+  Kind ValueKind = K_Unspecified;
+  bool IsManuallyAlloc = false;
+};
+
+template <> inline void *Value::getAs() const {
+  if (isPointerOrObjectType())
+    return Data.m_Ptr;
+  return (void *)getAs<uintptr_t>();
+}
+
+} // namespace clang
+#endif
Index: clang/include/clang/Interpreter/Interpreter.h
===================================================================
--- clang/include/clang/Interpreter/Interpreter.h
+++ clang/include/clang/Interpreter/Interpreter.h
@@ -14,13 +14,14 @@
 #ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
 #define LLVM_CLANG_INTERPRETER_INTERPRETER_H
 
-#include "clang/Interpreter/PartialTranslationUnit.h"
-
+#include "clang/AST/Decl.h"
 #include "clang/AST/GlobalDecl.h"
+#include "clang/Interpreter/PartialTranslationUnit.h"
+#include "clang/Interpreter/Value.h"
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/Support/Error.h"
-
 #include <memory>
 #include <vector>
 
@@ -53,24 +54,22 @@
   Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err);
 
   llvm::Error CreateExecutor();
+  unsigned InitPTUSize = 0;
+
+  Value LastValue;
 
 public:
   ~Interpreter();
   static llvm::Expected<std::unique_ptr<Interpreter>>
   create(std::unique_ptr<CompilerInstance> CI);
+  ASTContext &getASTContext() const;
   const CompilerInstance *getCompilerInstance() const;
   llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine();
 
   llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
   llvm::Error Execute(PartialTranslationUnit &T);
-  llvm::Error ParseAndExecute(llvm::StringRef Code) {
-    auto PTU = Parse(Code);
-    if (!PTU)
-      return PTU.takeError();
-    if (PTU->TheModule)
-      return Execute(*PTU);
-    return llvm::Error::success();
-  }
+  llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
+  llvm::Expected<llvm::JITTargetAddress> CompileDtorCall(CXXRecordDecl *CXXRD);
 
   /// Undo N previous incremental inputs.
   llvm::Error Undo(unsigned N = 1);
@@ -91,6 +90,25 @@
   /// file.
   llvm::Expected<llvm::JITTargetAddress>
   getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
+
+  std::list<PartialTranslationUnit> &getPTUs();
+
+  enum InterfaceKind { NoAlloc, WithAlloc, CopyArray };
+
+  llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() {
+    return ValuePrintingInfo;
+  }
+
+  Expr *SynthesizeExpr(clang::Expr *E);
+
+private:
+  bool FindRuntimeInterface();
+
+  std::unique_ptr<llvm::Module> GenModule();
+
+  llvm::DenseMap<CXXRecordDecl *, llvm::JITTargetAddress> Dtors;
+
+  llvm::SmallVector<Expr *, 3> ValuePrintingInfo;
 };
 } // namespace clang
 
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -941,6 +941,9 @@
 // into the name of a header unit.
 ANNOTATION(header_unit)
 
+// Annotation for end of input in clang-repl.
+ANNOTATION(input_end)
+
 #undef PRAGMA_ANNOTATION
 #undef ANNOTATION
 #undef TESTING_KEYWORD
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -4324,6 +4324,7 @@
   friend class ASTDeclWriter;
 
   Stmt *Statement = nullptr;
+  bool IsSemiMissing = false;
 
   TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S)
       : Decl(TopLevelStmt, DC, L), Statement(S) {}
@@ -4337,6 +4338,12 @@
   SourceRange getSourceRange() const override LLVM_READONLY;
   Stmt *getStmt() { return Statement; }
   const Stmt *getStmt() const { return Statement; }
+  void setStmt(Stmt *S) {
+    assert(IsSemiMissing && "Operation supported for printing values only!");
+    Statement = S;
+  }
+  bool isValuePrinting() const { return IsSemiMissing; }
+  void setValuePrinting(bool Missing = true) { IsSemiMissing = Missing; }
 
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == TopLevelStmt; }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to