[clang] 094ab47 - Revert "Reland [clang-repl] Introduce Value to capture expression results"
Jun Zhang via cfe-commits
cfe-commits at lists.llvm.org
Fri May 19 06:17:18 PDT 2023
Author: Jun Zhang
Date: 2023-05-19T20:56:21+08:00
New Revision: 094ab4781262b6cb49d57b0ecdf84b047c879295
URL: https://github.com/llvm/llvm-project/commit/094ab4781262b6cb49d57b0ecdf84b047c879295
DIFF: https://github.com/llvm/llvm-project/commit/094ab4781262b6cb49d57b0ecdf84b047c879295.diff
LOG: Revert "Reland [clang-repl] Introduce Value to capture expression results"
This reverts commit d71a4e02277a64a9dece591cdf2b34f15c3b19a0.
See http://45.33.8.238/macm1/61024/step_7.txt
Added:
Modified:
clang/include/clang/Interpreter/Interpreter.h
clang/lib/Interpreter/CMakeLists.txt
clang/lib/Interpreter/IncrementalParser.cpp
clang/lib/Interpreter/IncrementalParser.h
clang/lib/Interpreter/Interpreter.cpp
clang/tools/clang-repl/CMakeLists.txt
clang/unittests/Interpreter/CMakeLists.txt
clang/unittests/Interpreter/InterpreterTest.cpp
Removed:
clang/include/clang/Interpreter/Value.h
clang/lib/Interpreter/InterpreterUtils.cpp
clang/lib/Interpreter/InterpreterUtils.h
clang/lib/Interpreter/Value.cpp
################################################################################
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index e680218452d1c..b3d64458d777c 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -14,15 +14,14 @@
#ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
#define LLVM_CLANG_INTERPRETER_INTERPRETER_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 "clang/AST/GlobalDecl.h"
+
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/Support/Error.h"
+
#include <memory>
#include <vector>
@@ -55,26 +54,24 @@ class Interpreter {
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err);
llvm::Error CreateExecutor();
- unsigned InitPTUSize = 0;
-
- // This member holds the last result of the value printing. It's a class
- // member because we might want to access it after more inputs. If no value
- // printing happens, it's in an invalid state.
- Value LastValue;
public:
~Interpreter();
static llvm::Expected<std::unique_ptr<Interpreter>>
create(std::unique_ptr<CompilerInstance> CI);
- const ASTContext &getASTContext() const;
- ASTContext &getASTContext();
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, Value *V = nullptr);
- llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
+ 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();
+ }
/// Undo N previous incremental inputs.
llvm::Error Undo(unsigned N = 1);
@@ -95,23 +92,6 @@ class Interpreter {
/// file.
llvm::Expected<llvm::orc::ExecutorAddr>
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
-
- enum InterfaceKind { NoAlloc, WithAlloc, CopyArray };
-
- const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const {
- return ValuePrintingInfo;
- }
-
- Expr *SynthesizeExpr(Expr *E);
-
-private:
- size_t getEffectivePTUSize() const;
-
- bool FindRuntimeInterface();
-
- llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
-
- llvm::SmallVector<Expr *, 3> ValuePrintingInfo;
};
} // namespace clang
diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h
deleted file mode 100644
index 4df4367030ecd..0000000000000
--- a/clang/include/clang/Interpreter/Value.h
+++ /dev/null
@@ -1,202 +0,0 @@
-//===--- Value.h - Definition of interpreter value --------------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Value is a lightweight struct that is used for carrying execution results in
-// clang-repl. It's a special runtime that acts like a messager between compiled
-// code and interpreted code. This makes it possible to exchange interesting
-// information between the compiled & interpreted world.
-//
-// A typical usage is like the below:
-//
-// Value V;
-// Interp.ParseAndExecute("int x = 42;");
-// Interp.ParseAndExecute("x", &V);
-// V.getType(); // <-- Yields a clang::QualType.
-// V.getInt(); // <-- Yields 42.
-//
-// The current design is still highly experimental and nobody should rely on the
-// API being stable because we're hopefully going to make significant changes to
-// it in the relatively near future. For example, Value also intends to be used
-// as an exchange token for JIT support enabling remote execution on the embed
-// devices where the JIT infrastructure cannot fit. To support that we will need
-// to split the memory storage in a
diff erent place and perhaps add a resource
-// header is similar to intrinsics headers which have stricter performance
-// constraints.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INTERPRETER_VALUE_H
-#define LLVM_CLANG_INTERPRETER_VALUE_H
-
-#include "llvm/Support/Compiler.h"
-#include <cstdint>
-
-// NOTE: Since the REPL itself could also include this runtime, extreme caution
-// should be taken when MAKING CHANGES to this file, especially when INCLUDE NEW
-// HEADERS, like <string>, <memory> and etc. (That pulls a large number of
-// tokens and will impact the runtime performance of the REPL)
-
-namespace llvm {
-class raw_ostream;
-
-} // namespace llvm
-
-namespace clang {
-
-class ASTContext;
-class Interpreter;
-class QualType;
-
-#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
-
-#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(Interpreter *In, void *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;
- void clear();
-
- ASTContext &getASTContext();
- const ASTContext &getASTContext() const;
- Interpreter &getInterpreter();
- const Interpreter &getInterpreter() const;
- QualType getType() const;
-
- bool isValid() const { return ValueKind != K_Unspecified; }
- bool isVoid() const { return ValueKind == K_Void; }
- bool hasValue() const { return isValid() && !isVoid(); }
- 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; }
-
-#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
-
- /// \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 convertTo() const {
- return convertFwd<T>::cast(*this);
- }
-
-protected:
- bool isPointerOrObjectType() const { return ValueKind == K_PtrOrObj; }
-
- /// \brief Get to the value with type checking casting the underlying
- /// stored value to T.
- template <typename T> T as() const {
- switch (ValueKind) {
- default:
- return T();
-#define X(type, name) \
- case Value::K_##name: \
- return (T)Data.m_##name;
- REPL_BUILTIN_TYPES
-#undef X
- }
- }
-
- // Allow convertTo to be partially specialized.
- template <typename T> struct convertFwd {
- static T cast(const Value &V) {
- if (V.isPointerOrObjectType())
- return (T)(uintptr_t)V.as<void *>();
- if (!V.isValid() || V.isVoid()) {
- return T();
- }
- return V.as<T>();
- }
- };
-
- template <typename T> struct convertFwd<T *> {
- static T *cast(const Value &V) {
- if (V.isPointerOrObjectType())
- return (T *)(uintptr_t)V.as<void *>();
- return nullptr;
- }
- };
-
- Interpreter *Interp = nullptr;
- void *OpaqueType = nullptr;
- Storage Data;
- Kind ValueKind = K_Unspecified;
- bool IsManuallyAlloc = false;
-};
-
-template <> inline void *Value::as() const {
- if (isPointerOrObjectType())
- return Data.m_Ptr;
- return (void *)as<uintptr_t>();
-}
-
-} // namespace clang
-#endif
diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt
index 0df0ba6b8b856..721864c0cc1ea 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -14,8 +14,6 @@ add_clang_library(clangInterpreter
IncrementalExecutor.cpp
IncrementalParser.cpp
Interpreter.cpp
- InterpreterUtils.cpp
- Value.cpp
DEPENDS
intrinsics_gen
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index e431890712258..2b932623a5fea 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "IncrementalParser.h"
+
#include "clang/AST/DeclContextInternals.h"
#include "clang/CodeGen/BackendUtil.h"
#include "clang/CodeGen/CodeGenAction.h"
@@ -18,9 +19,9 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/FrontendTool/Utils.h"
-#include "clang/Interpreter/Interpreter.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
+
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
@@ -30,79 +31,6 @@
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->isSemiMissing())
- TSD->setStmt(Interp.SynthesizeExpr(cast<Expr>(TSD->getStmt())));
-
- return Consumer->HandleTopLevelDecl(DGR);
- }
- void HandleTranslationUnit(ASTContext &Ctx) override final {
- Consumer->HandleTranslationUnit(Ctx);
- }
- 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
@@ -194,8 +122,7 @@ class IncrementalAction : public WrapperFrontendAction {
}
};
-IncrementalParser::IncrementalParser(Interpreter &Interp,
- std::unique_ptr<CompilerInstance> Instance,
+IncrementalParser::IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
llvm::LLVMContext &LLVMCtx,
llvm::Error &Err)
: CI(std::move(Instance)) {
@@ -204,9 +131,6 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
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));
@@ -343,20 +267,15 @@ IncrementalParser::Parse(llvm::StringRef input) {
"Lexer must be EOF when starting incremental parse!");
}
- 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;
+ CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
+ M->getContext());
+
+ PTU->TheModule = std::move(M);
}
- return nullptr;
+
+ return PTU;
}
void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h
index 99e37588df9db..8e45d6b5931bc 100644
--- a/clang/lib/Interpreter/IncrementalParser.h
+++ b/clang/lib/Interpreter/IncrementalParser.h
@@ -16,6 +16,7 @@
#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"
@@ -30,8 +31,8 @@ namespace clang {
class ASTConsumer;
class CompilerInstance;
class IncrementalAction;
-class Interpreter;
class Parser;
+
/// Provides support for incremental compilation. Keeps track of the state
/// changes between the subsequent incremental input.
///
@@ -56,8 +57,7 @@ class IncrementalParser {
std::list<PartialTranslationUnit> PTUs;
public:
- IncrementalParser(Interpreter &Interp,
- std::unique_ptr<CompilerInstance> Instance,
+ IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
llvm::LLVMContext &LLVMCtx, llvm::Error &Err);
~IncrementalParser();
@@ -76,8 +76,6 @@ class IncrementalParser {
std::list<PartialTranslationUnit> &getPTUs() { return PTUs; }
- std::unique_ptr<llvm::Module> GenModule();
-
private:
llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
};
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index e41024a256525..24fb9da69a8bc 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -16,11 +16,7 @@
#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"
@@ -31,16 +27,13 @@
#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/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
@@ -184,7 +177,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
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),
+ IncrParser = std::make_unique<IncrementalParser>(std::move(CI),
*TSCtx->getContext(), Err);
}
@@ -197,29 +190,6 @@ Interpreter::~Interpreter() {
}
}
-// 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"(
- void* operator new(__SIZE_TYPE__, void* __p) noexcept;
- 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);
- 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)) 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);
- }
-)";
-
llvm::Expected<std::unique_ptr<Interpreter>>
Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
llvm::Error Err = llvm::Error::success();
@@ -227,14 +197,6 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
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->IncrParser->getPTUs().size();
return std::move(Interp);
}
@@ -251,26 +213,8 @@ llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
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) {
- // 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);
}
@@ -302,25 +246,6 @@ llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
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)
@@ -354,7 +279,7 @@ Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
llvm::Error Interpreter::Undo(unsigned N) {
std::list<PartialTranslationUnit> &PTUs = IncrParser->getPTUs();
- if (N > getEffectivePTUSize())
+ if (N > PTUs.size())
return llvm::make_error<llvm::StringError>("Operation failed. "
"Too many undos",
std::error_code());
@@ -385,343 +310,3 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
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"};
-
-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: {
- // __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()};
- 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());
- }
- }
- 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->getAs<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);
-}
diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp
deleted file mode 100644
index c19cf6aa3156c..0000000000000
--- a/clang/lib/Interpreter/InterpreterUtils.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//===--- 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, uint64_t Val) {
- return IntegerLiteral::Create(C, llvm::APSInt::getUnsigned(Val),
- C.UnsignedLongLongTy, 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, (uint64_t)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 auto *TD = dyn_cast<clang::TagDecl>(Within);
- TD && !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
diff --git a/clang/lib/Interpreter/InterpreterUtils.h b/clang/lib/Interpreter/InterpreterUtils.h
deleted file mode 100644
index 8df158c17d491..0000000000000
--- a/clang/lib/Interpreter/InterpreterUtils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===--- 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"
-
-namespace clang {
-IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uint64_t Val);
-
-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
diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp
deleted file mode 100644
index fe37eebac5257..0000000000000
--- a/clang/lib/Interpreter/Value.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-//===--- 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);
- }
- }
-
- // Check whether the storage is valid by validating the canary bits.
- // If someone accidentally write some invalid bits in the storage, the canary
- // will be changed first, and `IsAlive` will return false then.
- 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];
-
- // These are some canary bits that are used for protecting the storage been
- // damaged.
- static constexpr unsigned char Canary[8] = {0x4c, 0x37, 0xad, 0x8f,
- 0x2d, 0x23, 0x95, 0x91};
-};
-} // namespace
-
-static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT) {
- if (Ctx.hasSameType(QT, Ctx.VoidTy))
- return Value::K_Void;
-
- if (const auto *ET = QT->getAs<EnumType>())
- QT = ET->getDecl()->getIntegerType();
-
- const auto *BT = QT->getAs<BuiltinType>();
- if (!BT || BT->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(Interpreter *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::orc::ExecutorAddr> Addr =
- Interp.CompileDtorCall(CXXRD))
- DtorF = reinterpret_cast<void *>(Addr->getValue());
- 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;
-}
-
-void Value::clear() {
- if (IsManuallyAlloc)
- ValueStorage::getFromPayload(getPtr())->Release();
- ValueKind = K_Unspecified;
- OpaqueType = nullptr;
- Interp = nullptr;
- IsManuallyAlloc = false;
-}
-
-Value::~Value() { clear(); }
-
-void *Value::getPtr() const {
- assert(ValueKind == K_PtrOrObj);
- return Data.m_Ptr;
-}
-
-QualType Value::getType() const {
- return QualType::getFromOpaquePtr(OpaqueType);
-}
-
-Interpreter &Value::getInterpreter() {
- assert(Interp != nullptr &&
- "Can't get interpreter from a default constructed value");
- return *Interp;
-}
-
-const Interpreter &Value::getInterpreter() const {
- assert(Interp != nullptr &&
- "Can't get interpreter from a default constructed value");
- return *Interp;
-}
-
-ASTContext &Value::getASTContext() { return getInterpreter().getASTContext(); }
-
-const 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";
-}
diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt
index 2ccbe292fd49e..2ea0122a7b795 100644
--- a/clang/tools/clang-repl/CMakeLists.txt
+++ b/clang/tools/clang-repl/CMakeLists.txt
@@ -12,7 +12,6 @@ add_clang_tool(clang-repl
)
clang_target_link_libraries(clang-repl PRIVATE
- clangAST
clangBasic
clangFrontend
clangInterpreter
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 698494b9897f5..1a099dbbfe59a 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -22,5 +22,3 @@ target_link_libraries(ClangReplInterpreterTests PUBLIC
if(NOT WIN32)
add_subdirectory(ExceptionTests)
endif()
-
-export_executable_symbols(ClangReplInterpreterTests)
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 330fd18ab0a43..d555911a89451 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,7 +17,6 @@
#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"
@@ -34,11 +33,6 @@ using namespace clang;
#define CLANG_INTERPRETER_NO_SUPPORT_EXEC
#endif
-int Global = 42;
-// JIT reports symbol not found on Windows without the visibility attribute.
-REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
-REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
-
namespace {
using Args = std::vector<const char *>;
static std::unique_ptr<Interpreter>
@@ -282,7 +276,8 @@ TEST(IncrementalProcessing, InstantiateTemplate) {
std::vector<const char *> Args = {"-fno-delayed-template-parsing"};
std::unique_ptr<Interpreter> Interp = createInterpreter(Args);
- llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
+ llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
+ "extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
" template<typename T>"
@@ -320,103 +315,4 @@ TEST(IncrementalProcessing, InstantiateTemplate) {
free(NewA);
}
-#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
-TEST(InterpreterTest, DISABLED_Value) {
-#else
-TEST(InterpreterTest, Value) {
-#endif
- // We cannot execute on the platform.
- if (!HostSupportsJit())
- return;
-
- 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_TRUE(V1.hasValue());
- EXPECT_EQ(V1.getInt(), 42);
- EXPECT_EQ(V1.convertTo<int>(), 42);
- EXPECT_TRUE(V1.getType()->isIntegerType());
- EXPECT_EQ(V1.getKind(), Value::K_Int);
- EXPECT_FALSE(V1.isManuallyAlloc());
-
- Value V2;
- llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
- llvm::cantFail(Interp->ParseAndExecute("y", &V2));
- EXPECT_TRUE(V2.isValid());
- EXPECT_TRUE(V2.hasValue());
- EXPECT_EQ(V2.getDouble(), 3.14);
- EXPECT_EQ(V2.convertTo<double>(), 3.14);
- EXPECT_TRUE(V2.getType()->isFloatingType());
- EXPECT_EQ(V2.getKind(), Value::K_Double);
- EXPECT_FALSE(V2.isManuallyAlloc());
-
- 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.hasValue());
- EXPECT_TRUE(V3.getType()->isRecordType());
- EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
- EXPECT_TRUE(V3.isManuallyAlloc());
-
- 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);
-
- Value V6;
- llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
- llvm::cantFail(Interp->ParseAndExecute("foo()", &V6));
- EXPECT_TRUE(V6.isValid());
- EXPECT_FALSE(V6.hasValue());
- EXPECT_TRUE(V6.getType()->isVoidType());
- EXPECT_EQ(V6.getKind(), Value::K_Void);
- EXPECT_FALSE(V2.isManuallyAlloc());
-
- Value V7;
- llvm::cantFail(Interp->ParseAndExecute("foo", &V7));
- EXPECT_TRUE(V7.isValid());
- EXPECT_TRUE(V7.hasValue());
- EXPECT_TRUE(V7.getType()->isFunctionProtoType());
- EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
- EXPECT_FALSE(V7.isManuallyAlloc());
-
- Value V8;
- llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
- llvm::cantFail(Interp->ParseAndExecute("&SS::f", &V8));
- EXPECT_TRUE(V8.isValid());
- EXPECT_TRUE(V8.hasValue());
- EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
- EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
- EXPECT_TRUE(V8.isManuallyAlloc());
-
- Value V9;
- llvm::cantFail(Interp->ParseAndExecute("struct A { virtual int f(); };"));
- llvm::cantFail(
- Interp->ParseAndExecute("struct B : A { int f() { return 42; }};"));
- llvm::cantFail(Interp->ParseAndExecute("int (B::*ptr)() = &B::f;"));
- llvm::cantFail(Interp->ParseAndExecute("ptr", &V9));
- EXPECT_TRUE(V9.isValid());
- EXPECT_TRUE(V9.hasValue());
- EXPECT_TRUE(V9.getType()->isMemberFunctionPointerType());
- EXPECT_EQ(V9.getKind(), Value::K_PtrOrObj);
- EXPECT_TRUE(V9.isManuallyAlloc());
-}
} // end anonymous namespace
More information about the cfe-commits
mailing list