llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: wlonestar (wlonestar) <details> <summary>Changes</summary> --- Patch is 27.57 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/88729.diff 9 Files Affected: - (modified) clang/include/clang/Interpreter/Interpreter.h (+2) - (modified) clang/include/clang/Interpreter/Value.h (+7-1) - (modified) clang/lib/Interpreter/CMakeLists.txt (+1) - (modified) clang/lib/Interpreter/IncrementalParser.h (+1) - (modified) clang/lib/Interpreter/Interpreter.cpp (+6-2) - (modified) clang/lib/Interpreter/InterpreterUtils.cpp (+1-1) - (modified) clang/lib/Interpreter/InterpreterUtils.h (+1-1) - (modified) clang/lib/Interpreter/Value.cpp (+9-4) - (added) clang/lib/Interpreter/ValuePrinter.cpp (+751) ``````````diff diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 970e0245417b51..3be29bd75cfca7 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -149,6 +149,8 @@ class Interpreter { CompilerInstance *getCompilerInstance(); llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine(); + Sema &getSema() const; + llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code); llvm::Error Execute(PartialTranslationUnit &T); llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr); diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h index d70e8f8719026b..186299a84db444 100644 --- a/clang/include/clang/Interpreter/Value.h +++ b/clang/include/clang/Interpreter/Value.h @@ -35,6 +35,7 @@ #include "llvm/Support/Compiler.h" #include <cstdint> +#include <string> // 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 @@ -117,6 +118,8 @@ class REPL_EXTERNAL_VISIBILITY Value { Value &operator=(Value &&RHS) noexcept; ~Value(); + std::string printValueInternal() const; + void printType(llvm::raw_ostream &Out) const; void printData(llvm::raw_ostream &Out) const; void print(llvm::raw_ostream &Out) const; @@ -126,7 +129,7 @@ class REPL_EXTERNAL_VISIBILITY Value { ASTContext &getASTContext(); const ASTContext &getASTContext() const; Interpreter &getInterpreter(); - const Interpreter &getInterpreter() const; + Interpreter &getInterpreter() const; QualType getType() const; bool isValid() const { return ValueKind != K_Unspecified; } @@ -136,6 +139,8 @@ class REPL_EXTERNAL_VISIBILITY Value { Kind getKind() const { return ValueKind; } void setKind(Kind K) { ValueKind = K; } void setOpaqueType(void *Ty) { OpaqueType = Ty; } + void setName(std::string name) { Name = name; } + std::string getName() const { return Name; } void *getPtr() const; void setPtr(void *Ptr) { Data.m_Ptr = Ptr; } @@ -197,6 +202,7 @@ class REPL_EXTERNAL_VISIBILITY Value { Storage Data; Kind ValueKind = K_Unspecified; bool IsManuallyAlloc = false; + std::string Name; }; template <> inline void *Value::as() const { diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index 9065f998f73c47..ea00bdc80f595d 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -20,6 +20,7 @@ add_clang_library(clangInterpreter Interpreter.cpp InterpreterUtils.cpp Value.cpp + ValuePrinter.cpp DEPENDS intrinsics_gen diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index e13b74c7f65948..c9acc59b1ed602 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -67,6 +67,7 @@ class IncrementalParser { CompilerInstance *getCI() { return CI.get(); } CodeGenerator *getCodeGen() const; + Parser &getParser() const { return *P; } /// Parses incremental input by creating an in-memory file. ///\returns a \c PartialTranslationUnit which holds information about the diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index cf31456b6950ac..aa6f6657670bca 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -336,6 +336,8 @@ llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() { return IncrExecutor->GetExecutionEngine(); } +Sema &Interpreter::getSema() const { return getCompilerInstance()->getSema(); } + ASTContext &Interpreter::getASTContext() { return getCompilerInstance()->getASTContext(); } @@ -427,7 +429,7 @@ llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { } llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { - + std::string name = Code.str(); auto PTU = Parse(Code); if (!PTU) return PTU.takeError(); @@ -437,10 +439,12 @@ llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) { if (LastValue.isValid()) { if (!V) { + LastValue.setName(name); LastValue.dump(); LastValue.clear(); - } else + } else { *V = std::move(LastValue); + } } return llvm::Error::success(); } diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp index c19cf6aa3156c9..cba64add8c54a7 100644 --- a/clang/lib/Interpreter/InterpreterUtils.cpp +++ b/clang/lib/Interpreter/InterpreterUtils.cpp @@ -102,7 +102,7 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name, return nullptr; } -std::string GetFullTypeName(ASTContext &Ctx, QualType QT) { +std::string GetFullTypeName(const ASTContext &Ctx, QualType QT) { PrintingPolicy Policy(Ctx.getPrintingPolicy()); Policy.SuppressScope = false; Policy.AnonymousTagLocations = false; diff --git a/clang/lib/Interpreter/InterpreterUtils.h b/clang/lib/Interpreter/InterpreterUtils.h index 8df158c17d4919..5699060754fb4d 100644 --- a/clang/lib/Interpreter/InterpreterUtils.h +++ b/clang/lib/Interpreter/InterpreterUtils.h @@ -48,7 +48,7 @@ NamespaceDecl *LookupNamespace(Sema &S, llvm::StringRef Name, NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name, const DeclContext *Within); -std::string GetFullTypeName(ASTContext &Ctx, QualType QT); +std::string GetFullTypeName(const ASTContext &Ctx, QualType QT); } // namespace clang #endif diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp index eb2ce9c9fd3302..ca11093481be89 100644 --- a/clang/lib/Interpreter/Value.cpp +++ b/clang/lib/Interpreter/Value.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Interpreter/Value.h" +#include "InterpreterUtils.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" #include "clang/Interpreter/Interpreter.h" @@ -222,6 +223,7 @@ void Value::clear() { OpaqueType = nullptr; Interp = nullptr; IsManuallyAlloc = false; + Name = ""; } Value::~Value() { clear(); } @@ -241,7 +243,7 @@ Interpreter &Value::getInterpreter() { return *Interp; } -const Interpreter &Value::getInterpreter() const { +Interpreter &Value::getInterpreter() const { assert(Interp != nullptr && "Can't get interpreter from a default constructed value"); return *Interp; @@ -256,14 +258,17 @@ const ASTContext &Value::getASTContext() const { void Value::dump() const { print(llvm::outs()); } void Value::printType(llvm::raw_ostream &Out) const { - Out << "Not implement yet.\n"; + Out << "(" << GetFullTypeName(getASTContext(), getType()) << ")\n"; } + void Value::printData(llvm::raw_ostream &Out) const { - Out << "Not implement yet.\n"; + Out << printValueInternal() << "\n"; } + void Value::print(llvm::raw_ostream &Out) const { assert(OpaqueType != nullptr && "Can't print default Value"); - Out << "Not implement yet.\n"; + Out << "(" << GetFullTypeName(getASTContext(), getType()) << ")" << ' ' + << printValueInternal() << "\n"; } } // namespace clang diff --git a/clang/lib/Interpreter/ValuePrinter.cpp b/clang/lib/Interpreter/ValuePrinter.cpp new file mode 100644 index 00000000000000..19b9dcd3d89504 --- /dev/null +++ b/clang/lib/Interpreter/ValuePrinter.cpp @@ -0,0 +1,751 @@ +//===--- ValuePrinter.cpp - Value Printer -------*- 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements some value printer functions for clang-repl. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/APValue.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Interpreter/Value.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedAttr.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_os_ostream.h" +#include "llvm/Support/raw_ostream.h" + +#include "InterpreterUtils.h" + +#include <cassert> +#include <codecvt> +#include <cstddef> +#include <cstdint> +#include <locale> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +namespace clang { + +std::string printAddress(const void *Ptr, const char Prefix = 0) { + if (!Ptr) { + return "nullptr"; + } + std::ostringstream ostr; + if (Prefix) { + ostr << Prefix; + } + ostr << Ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const void *ptr) { return printAddress(ptr, '@'); } + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const void **ptr) { return printAddress(*ptr); } + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const bool *ptr) { return *ptr ? "true" : "false"; } + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const char *ptr) { + std::string value = "'"; + switch (*ptr) { + case '\t': + value += "\\t"; + break; + case '\n': + value += "\\n"; + break; + case '\r': + value += "\\r"; + break; + case '\f': + value += "\\f"; + break; + case '\v': + value += "\\v"; + break; + default: + value += *ptr; + } + value += "'"; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const signed char *ptr) { + std::string value = "'"; + switch (*ptr) { + case '\t': + value += "\\t"; + break; + case '\n': + value += "\\n"; + break; + case '\r': + value += "\\r"; + break; + case '\f': + value += "\\f"; + break; + case '\v': + value += "\\v"; + break; + default: + value += *ptr; + } + value += "'"; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const unsigned char *ptr) { + std::string value = "'"; + switch (*ptr) { + case '\t': + value += "\\t"; + break; + case '\n': + value += "\\n"; + break; + case '\r': + value += "\\r"; + break; + case '\f': + value += "\\f"; + break; + case '\v': + value += "\\v"; + break; + default: + value += *ptr; + } + value += "'"; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const wchar_t *ptr) { + std::string value = "'"; + switch (*ptr) { + case '\t': + value += "\\t"; + break; + case '\n': + value += "\\n"; + break; + case '\r': + value += "\\r"; + break; + case '\f': + value += "\\f"; + break; + case '\v': + value += "\\v"; + break; + default: + value += *ptr; + } + value += "'"; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const char16_t *ptr) { + std::string value = "'"; + switch (*ptr) { + case '\t': + value += "\\t"; + break; + case '\n': + value += "\\n"; + break; + case '\r': + value += "\\r"; + break; + case '\f': + value += "\\f"; + break; + case '\v': + value += "\\v"; + break; + default: + value += *ptr; + } + value += "'"; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const char32_t *ptr) { + std::string value = "'"; + switch (*ptr) { + case '\t': + value += "\\t"; + break; + case '\n': + value += "\\n"; + break; + case '\r': + value += "\\r"; + break; + case '\f': + value += "\\f"; + break; + case '\v': + value += "\\v"; + break; + default: + value += *ptr; + } + value += "'"; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const unsigned short *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const short *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const unsigned int *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const int *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const unsigned long *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const long *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const unsigned long long *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const long long *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const float *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const double *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const long double *ptr) { + std::ostringstream ostr; + ostr << *ptr; + return ostr.str(); +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(char *ptr, bool seq) { + std::string value = "\""; + char *p = ptr; + while (*p != '\0') { + value += *p; + p++; + } + value += "\""; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(signed char *ptr, bool seq) { + std::string value = "\""; + signed char *p = ptr; + while (*p != '\0') { + value += *p; + p++; + } + value += "\""; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(unsigned char *ptr, bool seq) { + std::string value = "\""; + unsigned char *p = ptr; + while (*p != '\0') { + value += *p; + p++; + } + value += "\""; + return value; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(wchar_t *ptr, bool seq) { + std::wstring value; + wchar_t *p = ptr; + while (*p != '\0') { + value += *p; + p++; + } + std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter; + return "\"" + converter.to_bytes(value) + "\""; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(char16_t *ptr, bool seq) { + std::u16string value; + char16_t *p = ptr; + while (*p != '\0') { + value += *p; + p++; + } + std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; + return "\"" + converter.to_bytes(value) + "\""; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(char32_t *ptr, bool seq) { + std::u32string value; + char32_t *p = ptr; + while (*p != '\0') { + value += *p; + p++; + } + std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter; + return "\"" + converter.to_bytes(value) + "\""; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const std::string *ptr) { return "\"" + *ptr + "\""; } + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const std::wstring *ptr) { + std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter; + return "\"" + converter.to_bytes(*ptr) + "\""; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const std::u16string *ptr) { + std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; + return "\"" + converter.to_bytes(*ptr) + "\""; +} + +REPL_EXTERNAL_VISIBILITY +std::string printValue(const std::u32string *ptr) { + std::wstring_convert<std::codecvt_utf8_utf16<char32_t>, char32_t> converter; + return "\"" + converter.to_bytes(*ptr) + "\""; +} + +std::string printBuiltinTypeValue(const Value &V, BuiltinType::Kind Kind) { + switch (Kind) { + case BuiltinType::Bool: + return V.convertTo<bool>() ? "true" : "false"; + case BuiltinType::Char_U: + case BuiltinType::UChar: { + auto val = V.convertTo<unsigned char>(); + return printValue(&val); + } + case BuiltinType::Char_S: + case BuiltinType::SChar: { + auto val = V.convertTo<signed char>(); + return printValue(&val); + } + case BuiltinType::WChar_S: { + auto val = V.convertTo<wchar_t>(); + return printValue(&val); + } + case BuiltinType::Char16: { + auto val = V.convertTo<char16_t>(); + return printValue(&val); + } + case BuiltinType::Char32: { + auto val = V.convertTo<char32_t>(); + return printValue(&val); + } + case BuiltinType::UShort: + return std::to_string(V.convertTo<unsigned short>()); + case BuiltinType::Short: + return std::to_string(V.convertTo<short>()); + case BuiltinType::UInt: + return std::to_string(V.convertTo<unsigned int>()); + case BuiltinType::Int: + return std::to_string(V.convertTo<int>()); + case BuiltinType::ULong: + return std::to_string(V.convertTo<unsigned long>()); + case BuiltinType::Long: + return std::to_string(V.convertTo<long>()); + case BuiltinType::ULongLong: + return std::to_string(V.convertTo<unsigned long long>()); + case BuiltinType::LongLong: + return std::to_string(V.convertTo<long long>()); + case BuiltinType::Float: + return std::to_string(V.convertTo<float>()); + case BuiltinType::Double: + return std::to_string(V.convertTo<double>()); + case BuiltinType::LongDouble: + return std::to_string(V.convertTo<long double>()); + default: + break; + } + return ""; +} + +std::string printValueByPtr(void *Ptr, QualType Type, uint64_t Offset) { + if (const BuiltinType *bt = + llvm::dyn_cast<BuiltinType>(Type.getCanonicalType().getTypePtr())) { + std::ostringstream os; + Ptr = (void *)((char *)Ptr + Offset); + switch (bt->getKind()) { + case BuiltinType::Bool: + return printValue((bool *)Ptr); + case BuiltinType::Char_U: + return printValue((unsigned char *)Ptr); + case BuiltinType::UChar: + return printValue((unsigned char *)Ptr); + case BuiltinType::Char_S: + return printValue((signed char *)Ptr); + case BuiltinType::SChar: + return printValue((signed char *)Ptr); + case BuiltinType::WChar_S: + return printValue((wchar_t *)Ptr); + case BuiltinType::Char16: + return printValue((char16_t *)Ptr); + case BuiltinType::Char32: + return printValue((char32_t *)Ptr); + case BuiltinType::UShort: + return printValue((unsigned short *)Ptr); + case BuiltinType::Short: + return printValue((short *)Ptr); + case BuiltinType::UInt: + return printValue((unsigned int *)Ptr); + case BuiltinType::Int: + return printValue((int *)Ptr); + case BuiltinType::ULong: + return printValue((unsigned long *)Ptr); + case BuiltinType::Long: + return printValue((long *)Ptr); + case BuiltinType::ULongLong: + return printValue((unsigned long long *)Ptr); + case BuiltinType::LongLong: + return printValue((long long *)Ptr); + case BuiltinType::Float: + return printValue((float *)Ptr); + case BuiltinType::Double: + return printValue((double *)Ptr); + case BuiltinType::LongDouble: + return printValue((long double *)Ptr); + default: + break; + } + } + if (!Ptr) { + return "nullptr"; + } + return printAddress(Ptr, '@'); +} + +std::string printEnumValue(const Value &V, QualType Type) { + std::ostringstream ostr; + const ASTContext &C = V.getASTContext(); + const EnumType *EnumTy = Type->getAs<EnumType>(); + assert(EnumTy && "printEnumValue invoked for a non enum type"); + EnumDecl *decl = EnumTy->getDecl(); + uint64_t value = V.getULongLong(); + bool isFirst = true; + llvm::APSInt valAsAPSInt = C.MakeIntValue(value, Type); + for (EnumDecl::enumerator_iterator I = decl->enumerator_begin(), + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/88729 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits