================ @@ -0,0 +1,459 @@ +//===-- DILAST.h ------------------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_CORE_DILAST_H +#define LLDB_CORE_DILAST_H + +#include <memory> +#include <optional> +#include <string> +#include <variant> +#include <vector> + +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Utility/ConstString.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/Support/Casting.h" + +namespace lldb_private { + +namespace DIL { + +/// Struct to hold information about member fields. Used by the parser for the +/// Data Inspection Language (DIL). +struct MemberInfo { + std::optional<std::string> name; + CompilerType type; + std::optional<uint32_t> bitfield_size_in_bits; + bool is_synthetic; + bool is_dynamic; + lldb::ValueObjectSP val_obj_sp; +}; + +/// Get the appropriate ValueObjectSP, consulting the use_dynamic and +/// use_synthetic options passed, acquiring the process & target locks if +/// appropriate. +lldb::ValueObjectSP GetDynamicOrSyntheticValue( + lldb::ValueObjectSP valobj_sp, + lldb::DynamicValueType use_dynamic = lldb::eNoDynamicValues, + bool use_synthetic = false); + +/// The various types DIL AST nodes (used by the DIL parser). +enum class NodeKind { + eErrorNode, + eScalarLiteralNode, + eStringLiteralNode, + eIdentifierNode, + eCStyleCastNode, + eMemberOfNode, + eArraySubscriptNode, + eUnaryOpNode, + eSmartPtrToPtrDecayNode +}; + +/// The C-Style casts for type promotion allowed by DIL. +enum class TypePromotionCastKind { + eArithmetic, + ePointer, +}; + +/// The Unary operators recognized by DIL. +enum class UnaryOpKind { + AddrOf, // "&" + Deref, // "*" + Minus, // "-" +}; + +/// Given a string representing a type, returns the CompilerType corresponding +/// to the named type, if it exists. +CompilerType +ResolveTypeByName(const std::string &name, + std::shared_ptr<ExecutionContextScope> ctx_scope); + +/// Class used to store & manipulate information about identifiers. +class IdentifierInfo { +private: + using MemberPath = std::vector<uint32_t>; + using IdentifierInfoUP = std::unique_ptr<IdentifierInfo>; + +public: + enum class Kind { + eValue, + eContextArg, + eMemberPath, + eThisKeyword, + }; + + static IdentifierInfoUP FromValue(lldb::ValueObjectSP value_sp) { + CompilerType type; + if (value_sp) + type = value_sp->GetCompilerType(); + return IdentifierInfoUP( + new IdentifierInfo(Kind::eValue, type, value_sp, {})); + } + + static IdentifierInfoUP FromContextArg(CompilerType type) { + lldb::ValueObjectSP empty_value; + return IdentifierInfoUP( + new IdentifierInfo(Kind::eContextArg, type, empty_value, {})); + } + + static IdentifierInfoUP FromMemberPath(CompilerType type, MemberPath path) { + lldb::ValueObjectSP empty_value; + return IdentifierInfoUP(new IdentifierInfo(Kind::eMemberPath, type, + empty_value, std::move(path))); + } + + static IdentifierInfoUP FromThisKeyword(CompilerType type) { + lldb::ValueObjectSP empty_value; + return IdentifierInfoUP( + new IdentifierInfo(Kind::eThisKeyword, type, empty_value, {})); + } + + Kind kind() const { return m_kind; } + lldb::ValueObjectSP value() const { return m_value; } + const MemberPath &path() const { return m_path; } + + CompilerType GetType() { return m_type; } + bool IsValid() const { return m_type.IsValid(); } + + IdentifierInfo(Kind kind, CompilerType type, lldb::ValueObjectSP value, + MemberPath path) + : m_kind(kind), m_type(type), m_value(std::move(value)), + m_path(std::move(path)) {} + +private: + Kind m_kind; + CompilerType m_type; + lldb::ValueObjectSP m_value; + MemberPath m_path; +}; + +/// Given the name of an identifier (variable name, member name, type name, +/// etc.), find the ValueObject for that name (if it exists) and create and +/// return an IdentifierInfo object containing all the relevant information +/// about that object (for DIL parsing and evaluating). +std::unique_ptr<IdentifierInfo> LookupIdentifier( + const std::string &name, std::shared_ptr<ExecutionContextScope> ctx_scope, + lldb::DynamicValueType use_dynamic, CompilerType *scope_ptr = nullptr); + +/// Forward declaration, for use in DIL AST nodes. Definition is at the very +/// end of this file. +class Visitor; + +/// The rest of the classes in this file, except for the Visitor class at the +/// very end, define all the types of AST nodes used by the DIL parser and +/// expression evaluator. The DIL parser parses the input string and creates the +/// AST parse tree from the AST nodes. The resulting AST node tree gets passed +/// to the DIL expression evaluator, which evaluates the DIL AST nodes and +/// creates/returns a ValueObjectSP containing the result. + +/// Base class for AST nodes used by the Data Inspection Language (DIL) parser. +/// All of the specialized types of AST nodes inherit from this (virtual) base +/// class. +class DILASTNode { +public: + DILASTNode(clang::SourceLocation location, NodeKind kind) + : m_location(location), m_kind(kind) {} + virtual ~DILASTNode() = default; + + virtual void Accept(Visitor *v) const = 0; + + virtual bool is_rvalue() const = 0; + virtual bool is_bitfield() const { return false; }; + virtual bool is_context_var() const { return false; }; + virtual bool is_literal_zero() const { return false; } + virtual uint32_t bitfield_size() const { return 0; } + virtual CompilerType result_type() const = 0; + + clang::SourceLocation GetLocation() const { return m_location; } + NodeKind getKind() const { return m_kind; } + + // The expression result type, but dereferenced in case it's a reference. This + // is for convenience, since for the purposes of the semantic analysis only + // the dereferenced type matters. + CompilerType GetDereferencedResultType() const; + +private: + clang::SourceLocation m_location; + const NodeKind m_kind; +}; + +using DILASTNodeUP = std::unique_ptr<DILASTNode>; + +class ErrorNode : public DILASTNode { +public: + ErrorNode(CompilerType empty_type) + : DILASTNode(clang::SourceLocation(), NodeKind::eErrorNode), + m_empty_type(empty_type) {} + void Accept(Visitor *v) const override; + bool is_rvalue() const override { return false; } + CompilerType result_type() const override { return m_empty_type; } + CompilerType result_type_real() const { return m_empty_type; } + + static bool classof(const DILASTNode *node) { + return node->getKind() == NodeKind::eErrorNode; + } + +private: + CompilerType m_empty_type; +}; + +class ScalarLiteralNode : public DILASTNode { +public: + ScalarLiteralNode(clang::SourceLocation location, CompilerType type, + Scalar value, bool is_literal_zero) + : DILASTNode(location, NodeKind::eScalarLiteralNode), m_type(type), + m_value(value), m_is_literal_zero(is_literal_zero) {} + + void Accept(Visitor *v) const override; + bool is_rvalue() const override { return true; } + bool is_literal_zero() const override { return m_is_literal_zero; } + CompilerType result_type() const override { return m_type; } + + auto value() const { return m_value; } + + static bool classof(const DILASTNode *node) { + return node->getKind() == NodeKind::eScalarLiteralNode; + } + +private: + CompilerType m_type; + Scalar m_value; + bool m_is_literal_zero; ---------------- labath wrote:
Would it make sense to have a special node type for a literal zero? (I genuinely don't know, I'm just asking). https://github.com/llvm/llvm-project/pull/95738 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits