-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LLDB] Add DIL code for handling plain variable names. #120971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
c14a0e3
[LLDB] Add DIL code for handling plain variable names.
cmtice 680f558
[LLDB] Add DIL code for handling plain variable names.
cmtice e21728a
[LLDB] Add DIL code for handling plain variable names.
cmtice e4e9cc4
[LLDB] Add DIL code for handling plain variable names.
cmtice fbeba18
Fix clang format issues.
cmtice aa0c721
[LLDB] Add DIL code for handling plain variable names.
cmtice d3a9ca6
[LLDB] Add DIL code for handling plain variable names.
cmtice c7eb5fd
Fix clang format issue in test.
cmtice 9d881e2
Re-do some if-statements to facilitate early exits.
cmtice d2665f0
FIx clang-format issue.
cmtice fe8c0bf
Merge remote-tracking branch 'origin/main' into DIL-variables
cmtice b5cf8b2
Update code to match changes in the recently committed DILLexer.
cmtice dc9b456
Address many of the review comments:
cmtice 06ff79b
Address remaining review comments:
cmtice 5d592e3
Address some review comments:
cmtice 33a9971
Update python tests to use expect_var_path where possible.
cmtice 07d0d15
Update error message handling to use DiagnosticDetails.
cmtice 42c52f3
Address/fix remaining reviewer comments:
cmtice 08a918d
Fix format errors in Python tests.
cmtice 27723db
Add static cast to fix buildkite error.
cmtice 07b6a4f
Minor style & format cleanups; also update error handling.
cmtice eb4a375
Fix clang-format issues.
cmtice 8b448ea
Code cleanups and reviewer suggestions around error handling.
cmtice 179bc8c
Clean up error handling.
cmtice ebc9e0a
Remove unused overload of BailOut function.
cmtice 49341ad
Use llvm::Error::success() to initialize llvm::Error (remove hack).
cmtice 40bd61a
Remove unused arguments from IdentifierNode class.
cmtice 1d9bb1c
Minor code cleanups requested by reviewer.
cmtice 358d28a
Check for & rollback errors in TentativeParsingRollaback.
cmtice File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
(* Data Inspection Language (DIL) definition - LLDB Debug Expressions *) | ||
|
||
(* This is currently a subset of the final DIL Language, matching the current | ||
DIL implementation. *) | ||
|
||
expression = primary_expression ; | ||
|
||
primary_expression = id_expression | ||
| "(" expression ")"; | ||
|
||
id_expression = unqualified_id | ||
| qualified_id | ||
| register ; | ||
|
||
unqualified_id = identifier ; | ||
|
||
qualified_id = ["::"] [nested_name_specifier] unqualified_id | ||
| ["::"] identifier ; | ||
|
||
identifier = ? C99 Identifier ? ; | ||
|
||
register = "$" ? Register name ? ; | ||
|
||
nested_name_specifier = type_name "::" | ||
| namespace_name '::' | ||
| nested_name_specifier identifier "::" ; | ||
|
||
type_name = class_name | ||
| enum_name | ||
| typedef_name; | ||
|
||
class_name = identifier ; | ||
|
||
enum_name = identifier ; | ||
|
||
typedef_name = identifier ; | ||
|
||
namespace_name = identifier ; | ||
|
||
|
||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
//===-- 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_VALUEOBJECT_DILAST_H | ||
#define LLDB_VALUEOBJECT_DILAST_H | ||
|
||
#include "lldb/ValueObject/ValueObject.h" | ||
#include "llvm/Support/Error.h" | ||
#include <cstdint> | ||
#include <string> | ||
|
||
namespace lldb_private::dil { | ||
|
||
/// The various types DIL AST nodes (used by the DIL parser). | ||
enum class NodeKind { | ||
eErrorNode, | ||
eIdentifierNode, | ||
}; | ||
|
||
/// 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 ASTNode { | ||
public: | ||
ASTNode(uint32_t location, NodeKind kind) | ||
: m_location(location), m_kind(kind) {} | ||
virtual ~ASTNode() = default; | ||
|
||
virtual llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const = 0; | ||
|
||
uint32_t GetLocation() const { return m_location; } | ||
NodeKind GetKind() const { return m_kind; } | ||
|
||
private: | ||
uint32_t m_location; | ||
const NodeKind m_kind; | ||
}; | ||
|
||
using ASTNodeUP = std::unique_ptr<ASTNode>; | ||
|
||
class ErrorNode : public ASTNode { | ||
public: | ||
ErrorNode() : ASTNode(0, NodeKind::eErrorNode) {} | ||
llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override; | ||
|
||
static bool classof(const ASTNode *node) { | ||
return node->GetKind() == NodeKind::eErrorNode; | ||
} | ||
}; | ||
|
||
class IdentifierNode : public ASTNode { | ||
public: | ||
IdentifierNode(uint32_t location, std::string name) | ||
: ASTNode(location, NodeKind::eIdentifierNode), m_name(std::move(name)) {} | ||
|
||
llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override; | ||
|
||
std::string GetName() const { return m_name; } | ||
|
||
static bool classof(const ASTNode *node) { | ||
return node->GetKind() == NodeKind::eIdentifierNode; | ||
} | ||
|
||
private: | ||
std::string m_name; | ||
}; | ||
|
||
/// This class contains one Visit method for each specialized type of | ||
/// DIL AST node. The Visit methods are used to dispatch a DIL AST node to | ||
/// the correct function in the DIL expression evaluator for evaluating that | ||
/// type of AST node. | ||
class Visitor { | ||
public: | ||
virtual ~Visitor() = default; | ||
virtual llvm::Expected<lldb::ValueObjectSP> | ||
Visit(const IdentifierNode *node) = 0; | ||
}; | ||
|
||
} // namespace lldb_private::dil | ||
|
||
#endif // LLDB_VALUEOBJECT_DILAST_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,63 @@ | ||||||||||
//===-- DILEval.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_VALUEOBJECT_DILEVAL_H | ||||||||||
#define LLDB_VALUEOBJECT_DILEVAL_H | ||||||||||
|
||||||||||
#include "lldb/ValueObject/DILAST.h" | ||||||||||
#include "lldb/ValueObject/DILParser.h" | ||||||||||
#include "llvm/ADT/StringRef.h" | ||||||||||
#include "llvm/Support/Error.h" | ||||||||||
#include <memory> | ||||||||||
#include <vector> | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
namespace lldb_private::dil { | ||||||||||
|
||||||||||
/// Given the name of an identifier (variable name, member name, type name, | ||||||||||
/// etc.), find the ValueObject for that name (if it exists), excluding global | ||||||||||
/// variables, and create and return an IdentifierInfo object containing all | ||||||||||
/// the relevant information about that object (for DIL parsing and | ||||||||||
/// evaluating). | ||||||||||
lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref, | ||||||||||
std::shared_ptr<StackFrame> frame_sp, | ||||||||||
lldb::DynamicValueType use_dynamic, | ||||||||||
CompilerType *scope_ptr = nullptr); | ||||||||||
|
||||||||||
/// Given the name of an identifier, check to see if it matches the name of a | ||||||||||
/// global variable. If so, find the ValueObject for that global variable, and | ||||||||||
/// create and return an IdentifierInfo object containing all the relevant | ||||||||||
/// informatin about it. | ||||||||||
lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref, | ||||||||||
std::shared_ptr<StackFrame> frame_sp, | ||||||||||
lldb::TargetSP target_sp, | ||||||||||
lldb::DynamicValueType use_dynamic, | ||||||||||
CompilerType *scope_ptr = nullptr); | ||||||||||
|
||||||||||
class Interpreter : Visitor { | ||||||||||
public: | ||||||||||
Interpreter(lldb::TargetSP target, llvm::StringRef expr, | ||||||||||
lldb::DynamicValueType use_dynamic, | ||||||||||
std::shared_ptr<StackFrame> frame_sp); | ||||||||||
|
||||||||||
llvm::Expected<lldb::ValueObjectSP> Evaluate(const ASTNode *node); | ||||||||||
|
||||||||||
private: | ||||||||||
llvm::Expected<lldb::ValueObjectSP> | ||||||||||
Visit(const IdentifierNode *node) override; | ||||||||||
|
||||||||||
// Used by the interpreter to create objects, perform casts, etc. | ||||||||||
lldb::TargetSP m_target; | ||||||||||
llvm::StringRef m_expr; | ||||||||||
lldb::ValueObjectSP m_scope; | ||||||||||
lldb::DynamicValueType m_default_dynamic; | ||||||||||
std::shared_ptr<StackFrame> m_exe_ctx_scope; | ||||||||||
}; | ||||||||||
|
||||||||||
} // namespace lldb_private::dil | ||||||||||
|
||||||||||
#endif // LLDB_VALUEOBJECT_DILEVAL_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
//===-- DILParser.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_VALUEOBJECT_DILPARSER_H | ||
#define LLDB_VALUEOBJECT_DILPARSER_H | ||
|
||
#include "lldb/Target/ExecutionContextScope.h" | ||
#include "lldb/Utility/DiagnosticsRendering.h" | ||
#include "lldb/Utility/Status.h" | ||
#include "lldb/ValueObject/DILAST.h" | ||
#include "lldb/ValueObject/DILLexer.h" | ||
#include "llvm/Support/Error.h" | ||
#include <memory> | ||
#include <optional> | ||
#include <string> | ||
#include <system_error> | ||
#include <tuple> | ||
#include <vector> | ||
|
||
namespace lldb_private::dil { | ||
|
||
enum class ErrorCode : unsigned char { | ||
kOk = 0, | ||
kInvalidExpressionSyntax, | ||
kUndeclaredIdentifier, | ||
kUnknown, | ||
}; | ||
labath marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// The following is modeled on class OptionParseError. | ||
class DILDiagnosticError | ||
: public llvm::ErrorInfo<DILDiagnosticError, DiagnosticError> { | ||
DiagnosticDetail m_detail; | ||
|
||
public: | ||
using llvm::ErrorInfo<DILDiagnosticError, DiagnosticError>::ErrorInfo; | ||
DILDiagnosticError(DiagnosticDetail detail) | ||
: ErrorInfo(make_error_code(std::errc::invalid_argument)), | ||
m_detail(std::move(detail)) {} | ||
|
||
DILDiagnosticError(llvm::StringRef expr, const std::string &message, | ||
uint32_t loc, uint16_t err_len); | ||
|
||
std::unique_ptr<CloneableError> Clone() const override { | ||
return std::make_unique<DILDiagnosticError>(m_detail); | ||
} | ||
|
||
llvm::ArrayRef<DiagnosticDetail> GetDetails() const override { | ||
return {m_detail}; | ||
} | ||
|
||
std::string message() const override { return m_detail.rendered; } | ||
}; | ||
|
||
/// Pure recursive descent parser for C++ like expressions. | ||
/// EBNF grammar for the parser is described in lldb/docs/dil-expr-lang.ebnf | ||
class DILParser { | ||
public: | ||
static llvm::Expected<ASTNodeUP> Parse(llvm::StringRef dil_input_expr, | ||
DILLexer lexer, | ||
std::shared_ptr<StackFrame> frame_sp, | ||
lldb::DynamicValueType use_dynamic, | ||
bool use_synthetic, bool fragile_ivar, | ||
bool check_ptr_vs_member); | ||
|
||
~DILParser() = default; | ||
|
||
bool UseSynthetic() { return m_use_synthetic; } | ||
|
||
lldb::DynamicValueType UseDynamic() { return m_use_dynamic; } | ||
|
||
private: | ||
explicit DILParser(llvm::StringRef dil_input_expr, DILLexer lexer, | ||
std::shared_ptr<StackFrame> frame_sp, | ||
lldb::DynamicValueType use_dynamic, bool use_synthetic, | ||
bool fragile_ivar, bool check_ptr_vs_member, | ||
llvm::Error &error); | ||
|
||
ASTNodeUP Run(); | ||
|
||
ASTNodeUP ParseExpression(); | ||
ASTNodeUP ParsePrimaryExpression(); | ||
|
||
std::string ParseNestedNameSpecifier(); | ||
|
||
std::string ParseIdExpression(); | ||
std::string ParseUnqualifiedId(); | ||
|
||
void BailOut(const std::string &error, uint32_t loc, uint16_t err_len); | ||
|
||
void Expect(Token::Kind kind); | ||
|
||
void TentativeParsingRollback(uint32_t saved_idx) { | ||
if (m_error) | ||
llvm::consumeError(std::move(m_error)); | ||
m_dil_lexer.ResetTokenIdx(saved_idx); | ||
} | ||
|
||
Token CurToken() { return m_dil_lexer.GetCurrentToken(); } | ||
|
||
// Parser doesn't own the evaluation context. The produced AST may depend on | ||
// it (for example, for source locations), so it's expected that expression | ||
// context will outlive the parser. | ||
std::shared_ptr<StackFrame> m_ctx_scope; | ||
|
||
llvm::StringRef m_input_expr; | ||
|
||
DILLexer m_dil_lexer; | ||
|
||
// Holds an error if it occures during parsing. | ||
llvm::Error &m_error; | ||
|
||
lldb::DynamicValueType m_use_dynamic; | ||
bool m_use_synthetic; | ||
bool m_fragile_ivar; | ||
bool m_check_ptr_vs_member; | ||
}; // class DILParser | ||
|
||
} // namespace lldb_private::dil | ||
|
||
#endif // LLDB_VALUEOBJECT_DILPARSER_H |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.