//===------ Interpreter.cpp - Incremental Compilation and Execution -------===//
//
// 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 the component which performs incremental code
// compilation and execution.
//
//===----------------------------------------------------------------------===//

#include "DeviceOffload.h"
#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/CodeGenAction.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/Interpreter/Interpreter.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/ErrorHandling.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
//        tools/clang-import-test/clang-import-test.cpp
namespace {
/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
/// \returns NULL on error.
static llvm::Expected<const llvm::opt::ArgStringList *>
GetCC1Arguments(DiagnosticsEngine *Diagnostics,
                driver::Compilation *Compilation) {
  // We expect to get back exactly one Command job, if we didn't something
  // failed. Extract that job from the Compilation.
  const driver::JobList &Jobs = Compilation->getJobs();
  if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))
    return llvm::createStringError(llvm::errc::not_supported,
                                   "Driver initialization failed. "
                                   "Unable to create a driver job");

  // The one job we find should be to invoke clang again.
  const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
    return llvm::createStringError(llvm::errc::not_supported,
                                   "Driver initialization failed");

  return &Cmd->getArguments();
}

static llvm::Expected<std::unique_ptr<CompilerInstance>>
CreateCI(const llvm::opt::ArgStringList &Argv) {
  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());

  // Register the support for object-file-wrapped Clang modules.
  // FIXME: Clang should register these container operations automatically.
  auto PCHOps = Clang->getPCHContainerOperations();
  PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
  PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());

  // Buffer diagnostics from argument parsing so that we can output them using
  // a well formed diagnostic object.
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
  bool Success = CompilerInvocation::CreateFromArgs(
      Clang->getInvocation(), llvm::ArrayRef(Argv.begin(), Argv.size()), Diags);

  // Infer the builtin include path if unspecified.
  if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
      Clang->getHeaderSearchOpts().ResourceDir.empty())
    Clang->getHeaderSearchOpts().ResourceDir =
        CompilerInvocation::GetResourcesPath(Argv[0], nullptr);

  // Create the actual diagnostics engine.
  Clang->createDiagnostics();
  if (!Clang->hasDiagnostics())
    return llvm::createStringError(llvm::errc::not_supported,
                                   "Initialization failed. "
                                   "Unable to create diagnostics engine");

  DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
  if (!Success)
    return llvm::createStringError(llvm::errc::not_supported,
                                   "Initialization failed. "
                                   "Unable to flush diagnostics");

  // FIXME: Merge with CompilerInstance::ExecuteAction.
  llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
  Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);

  Clang->setTarget(TargetInfo::CreateTargetInfo(
      Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
  if (!Clang->hasTarget())
    return llvm::createStringError(llvm::errc::not_supported,
                                   "Initialization failed. "
                                   "Target is missing");

  Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());

  // Don't clear the AST before backend codegen since we do codegen multiple
  // times, reusing the same AST.
  Clang->getCodeGenOpts().ClearASTBeforeBackend = false;

  Clang->getFrontendOpts().DisableFree = false;
  Clang->getCodeGenOpts().DisableFree = false;
  return std::move(Clang);
}

} // anonymous namespace

llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {

  // If we don't know ClangArgv0 or the address of main() at this point, try
  // to guess it anyway (it's possible on some platforms).
  std::string MainExecutableName =
      llvm::sys::fs::getMainExecutable(nullptr, nullptr);

  ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());

  // Prepending -c to force the driver to do something if no action was
  // specified. By prepending we allow users to override the default
  // action and use other actions in incremental mode.
  // FIXME: Print proper driver diagnostics if the driver flags are wrong.
  // We do C++ by default; append right after argv[0] if no "-x" given
  ClangArgv.insert(ClangArgv.end(), "-Xclang");
  ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions");
  ClangArgv.insert(ClangArgv.end(), "-c");

  // Put a dummy C++ file on to ensure there's at least one compile job for the
  // driver to construct.
  ClangArgv.push_back("<<< inputs >>>");

  // Buffer diagnostics from argument parsing so that we can output them using a
  // well formed diagnostic object.
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
      CreateAndPopulateDiagOpts(ClangArgv);
  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);

  driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
                        llvm::sys::getProcessTriple(), Diags);
  Driver.setCheckInputsExist(false); // the input comes from mem buffers
  llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv);
  std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));

  if (Compilation->getArgs().hasArg(driver::options::OPT_v))
    Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);

  auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
  if (auto Err = ErrOrCC1Args.takeError())
    return std::move(Err);

  return CreateCI(**ErrOrCC1Args);
}

llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::CreateCpp() {
  std::vector<const char *> Argv;
  Argv.reserve(5 + 1 + UserArgs.size());
  Argv.push_back("-xc++");
  Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());

  return IncrementalCompilerBuilder::create(Argv);
}

llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::createCuda(bool device) {
  std::vector<const char *> Argv;
  Argv.reserve(5 + 4 + UserArgs.size());

  Argv.push_back("-xcuda");
  if (device)
    Argv.push_back("--cuda-device-only");
  else
    Argv.push_back("--cuda-host-only");

  std::string SDKPathArg = "--cuda-path=";
  if (!CudaSDKPath.empty()) {
    SDKPathArg += CudaSDKPath;
    Argv.push_back(SDKPathArg.c_str());
  }

  std::string ArchArg = "--offload-arch=";
  if (!OffloadArch.empty()) {
    ArchArg += OffloadArch;
    Argv.push_back(ArchArg.c_str());
  }

  Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());

  return IncrementalCompilerBuilder::create(Argv);
}

llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::CreateCudaDevice() {
  return IncrementalCompilerBuilder::createCuda(true);
}

llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::CreateCudaHost() {
  return IncrementalCompilerBuilder::createCuda(false);
}

Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
                         llvm::Error &Err) {
  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>(*this, std::move(CI),
                                                   *TSCtx->getContext(), Err);
}

Interpreter::~Interpreter() {
  if (IncrExecutor) {
    if (llvm::Error Err = IncrExecutor->cleanUp())
      llvm::report_fatal_error(
          llvm::Twine("Failed to clean up IncrementalExecutor: ") +
          toString(std::move(Err)));
  }
}

// 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"(
#ifdef __cplusplus
    void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
    void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
    void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
    void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
    void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
    void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
    void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
    struct __clang_Interpreter_NewTag{} __ci_newtag;
    void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
    template <class T, class = T (*)() /*disable for arrays*/>
    void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
      for (auto Idx = 0; Idx < Size; ++Idx)
        new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
    }
    template <class T, unsigned long N>
    void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
      __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
    }
#endif // __cplusplus
)";

llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
  llvm::Error Err = llvm::Error::success();
  auto Interp =
      std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
  if (Err)
    return std::move(Err);

  auto PTU = Interp->Parse(Runtimes);
  if (!PTU)
    return PTU.takeError();

  Interp->ValuePrintingInfo.resize(4);
  // 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->IncrParser->getPTUs().size();
  return std::move(Interp);
}

llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
                            std::unique_ptr<CompilerInstance> DCI) {
  // avoid writing fat binary to disk using an in-memory virtual file system
  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS =
      std::make_unique<llvm::vfs::InMemoryFileSystem>();
  llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
      std::make_unique<llvm::vfs::OverlayFileSystem>(
          llvm::vfs::getRealFileSystem());
  OverlayVFS->pushOverlay(IMVFS);
  CI->createFileManager(OverlayVFS);

  auto Interp = Interpreter::create(std::move(CI));
  if (auto E = Interp.takeError())
    return std::move(E);

  llvm::Error Err = llvm::Error::success();
  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
      **Interp, std::move(DCI), *(*Interp)->IncrParser.get(),
      *(*Interp)->TSCtx->getContext(), IMVFS, Err);
  if (Err)
    return std::move(Err);

  (*Interp)->DeviceParser = std::move(DeviceParser);

  return Interp;
}

const CompilerInstance *Interpreter::getCompilerInstance() const {
  return IncrParser->getCI();
}

CompilerInstance *Interpreter::getCompilerInstance() {
  return IncrParser->getCI();
}

llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
  if (!IncrExecutor) {
    if (auto Err = CreateExecutor())
      return std::move(Err);
  }

  return IncrExecutor->GetExecutionEngine();
}

ASTContext &Interpreter::getASTContext() {
  return getCompilerInstance()->getASTContext();
}

const ASTContext &Interpreter::getASTContext() const {
  return getCompilerInstance()->getASTContext();
}

size_t Interpreter::getEffectivePTUSize() const {
  std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
  assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
  return PTUs.size() - InitPTUSize;
}

llvm::Expected<PartialTranslationUnit &>
Interpreter::Parse(llvm::StringRef Code) {
  // If we have a device parser, parse it first.
  // The generated code will be included in the host compilation
  if (DeviceParser) {
    auto DevicePTU = DeviceParser->Parse(Code);
    if (auto E = DevicePTU.takeError())
      return std::move(E);
  }

  // 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);
}

llvm::Error Interpreter::CreateExecutor() {
  const clang::TargetInfo &TI =
      getCompilerInstance()->getASTContext().getTargetInfo();
  llvm::Error Err = llvm::Error::success();
  auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI);
  if (!Err)
    IncrExecutor = std::move(Executor);

  return Err;
}

llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
  assert(T.TheModule);
  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))
    return Err;

  if (auto Err = IncrExecutor->runCtors())
    return Err;

  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();
      LastValue.clear();
    } else
      *V = std::move(LastValue);
  }
  return llvm::Error::success();
}

llvm::Expected<llvm::orc::ExecutorAddr>
Interpreter::getSymbolAddress(GlobalDecl GD) const {
  if (!IncrExecutor)
    return llvm::make_error<llvm::StringError>("Operation failed. "
                                               "No execution engine",
                                               std::error_code());
  llvm::StringRef MangledName = IncrParser->GetMangledName(GD);
  return getSymbolAddress(MangledName);
}

llvm::Expected<llvm::orc::ExecutorAddr>
Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
  if (!IncrExecutor)
    return llvm::make_error<llvm::StringError>("Operation failed. "
                                               "No execution engine",
                                               std::error_code());

  return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
}

llvm::Expected<llvm::orc::ExecutorAddr>
Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
  if (!IncrExecutor)
    return llvm::make_error<llvm::StringError>("Operation failed. "
                                               "No execution engine",
                                               std::error_code());

  return IncrExecutor->getSymbolAddress(Name, IncrementalExecutor::LinkerName);
}

llvm::Error Interpreter::Undo(unsigned N) {

  std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
  if (N > getEffectivePTUSize())
    return llvm::make_error<llvm::StringError>("Operation failed. "
                                               "Too many undos",
                                               std::error_code());
  for (unsigned I = 0; I < N; I++) {
    if (IncrExecutor) {
      if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
        return Err;
    }

    IncrParser->CleanUpPTU(PTUs.back());
    PTUs.pop_back();
  }
  return llvm::Error::success();
}

llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
  auto EE = getExecutionEngine();
  if (!EE)
    return EE.takeError();

  auto &DL = EE->getDataLayout();

  if (auto DLSG = llvm::orc::DynamicLibrarySearchGenerator::Load(
          name, DL.getGlobalPrefix()))
    EE->getMainJITDylib().addGenerator(std::move(*DLSG));
  else
    return DLSG.takeError();

  return llvm::Error::success();
}

llvm::Expected<llvm::orc::ExecutorAddr>
Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
  assert(CXXRD && "Cannot compile a destructor for a nullptr");
  if (auto Dtor = Dtors.find(CXXRD); Dtor != Dtors.end())
    return Dtor->getSecond();

  if (CXXRD->hasIrrelevantDestructor())
    return llvm::orc::ExecutorAddr{};

  CXXDestructorDecl *DtorRD =
      getCompilerInstance()->getSema().LookupDestructor(CXXRD);

  llvm::StringRef Name =
      IncrParser->GetMangledName(GlobalDecl(DtorRD, Dtor_Base));
  auto AddrOrErr = getSymbolAddress(Name);
  if (!AddrOrErr)
    return AddrOrErr.takeError();

  Dtors[CXXRD] = *AddrOrErr;
  return AddrOrErr;
}

static constexpr llvm::StringRef MagicRuntimeInterface[] = {
    "__clang_Interpreter_SetValueNoAlloc",
    "__clang_Interpreter_SetValueWithAlloc",
    "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};

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;
  if (!LookupInterface(ValuePrintingInfo[NewTag],
                       MagicRuntimeInterface[NewTag]))
    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: {
      // __clang_Interpreter_SetValueWithAlloc.
      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));
      }

      // __clang_Interpreter_SetValueCopyArr.
      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(),
          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
      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);
    }
      // __clang_Interpreter_SetValueNoAlloc.
    case Interpreter::InterfaceKind::NoAlloc: {
      return S.ActOnCallExpr(
          /*Scope=*/nullptr,
          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
          E->getBeginLoc(), Args, E->getEndLoc());
    }
    default:
      llvm_unreachable("Unhandled Interpreter::InterfaceKind");
    }
  }

  Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
    return Interpreter::InterfaceKind::WithAlloc;
  }

  Interpreter::InterfaceKind
  VisitMemberPointerType(const MemberPointerType *Ty) {
    return Interpreter::InterfaceKind::WithAlloc;
  }

  Interpreter::InterfaceKind
  VisitConstantArrayType(const ConstantArrayType *Ty) {
    return Interpreter::InterfaceKind::CopyArray;
  }

  Interpreter::InterfaceKind
  VisitFunctionProtoType(const FunctionProtoType *Ty) {
    HandlePtrType(Ty);
    return Interpreter::InterfaceKind::NoAlloc;
  }

  Interpreter::InterfaceKind VisitPointerType(const PointerType *Ty) {
    HandlePtrType(Ty);
    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->isIntegralOrEnumerationType())
      HandleIntegralOrEnumType(Ty);
    else if (Ty->isVoidType()) {
      // Do we need to still run `E`?
    }

    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
  // `__clang_Interpreter_SetValueNoAlloc`.
  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());
  }

  void HandlePtrType(const Type *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());
  }
};
} // 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.
//   __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
//   // 2. If x is a struct, and a lvalue.
//   __clang_Interpreter_SetValueNoAlloc(ThisInterp, OpaqueValue, xQualType,
//   &x);
//   // 3. If x is a struct, but a rvalue.
//   new (__clang_Interpreter_SetValueWithAlloc(ThisInterp, OpaqueValue,
//   xQualType)) (x);

Expr *Interpreter::SynthesizeExpr(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`.
  auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);

  // Create parameter `OutVal`.
  auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);

  // Build `__clang_Interpreter_SetValue*` call.
  RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});

  ExprResult Result = Builder.getCall();
  // It could fail, like printing an array type in C. (not supported)
  if (Result.isInvalid())
    return E;
  return Result.get();
}

// Temporary rvalue struct that need special care.
REPL_EXTERNAL_VISIBILITY void *
__clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
                                      void *OpaqueType) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
  return VRef.getPtr();
}

// Pointers, lvalue struct that can take as a reference.
REPL_EXTERNAL_VISIBILITY void
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
                                    void *Val) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
  VRef.setPtr(Val);
}

REPL_EXTERNAL_VISIBILITY void
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal,
                                    void *OpaqueType) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
}

static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) {
  QualType QT = V.getType();
  if (const auto *ET = QT->getAs<EnumType>())
    QT = ET->getDecl()->getIntegerType();

  switch (QT->castAs<BuiltinType>()->getKind()) {
  default:
    llvm_unreachable("unknown type kind!");
#define X(type, name)                                                          \
  case BuiltinType::name:                                                      \
    V.set##name(Data);                                                         \
    break;
    REPL_BUILTIN_TYPES
#undef X
  }
}

REPL_EXTERNAL_VISIBILITY void
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
                                    unsigned long long Val) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
  SetValueDataBasedOnQualType(VRef, Val);
}

REPL_EXTERNAL_VISIBILITY void
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
                                    float Val) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
  VRef.setFloat(Val);
}

REPL_EXTERNAL_VISIBILITY void
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
                                    double Val) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
  VRef.setDouble(Val);
}

REPL_EXTERNAL_VISIBILITY void
__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
                                    long double Val) {
  Value &VRef = *(Value *)OutVal;
  VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
  VRef.setLongDouble(Val);
}

// A trampoline to work around the fact that operator placement new cannot
// really be forward declared due to libc++ and libstdc++ declaration mismatch.
// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
// definition in the interpreter runtime. We should move it in a runtime header
// which gets included by the interpreter and here.
struct __clang_Interpreter_NewTag {};
REPL_EXTERNAL_VISIBILITY void *
operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
  // Just forward to the standard operator placement new.
  return operator new(__sz, __p);
}
