Skip to content

Revert "[LLDB] Add array subscription and integer parsing to DIL" #141059

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 1 commit into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions lldb/docs/dil-expr-lang.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@
expression = unary_expression ;

unary_expression = unary_operator expression
| postfix_expression ;
| primary_expression ;

unary_operator = "*" | "&" ;

postfix_expression = primary_expression
| postfix_expression "[" integer_literal "]";

primary_expression = id_expression
| "(" expression ")";

id_expression = unqualified_id
| qualified_id
| register ;
| register ;

unqualified_id = identifier ;

Expand All @@ -27,8 +24,6 @@ qualified_id = ["::"] [nested_name_specifier] unqualified_id

identifier = ? C99 Identifier ? ;

integer_literal = ? Integer constant: hexademical, decimal, octal, binary ? ;

register = "$" ? Register name ? ;

nested_name_specifier = type_name "::"
Expand Down
28 changes: 2 additions & 26 deletions lldb/include/lldb/ValueObject/DILAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ namespace lldb_private::dil {

/// The various types DIL AST nodes (used by the DIL parser).
enum class NodeKind {
eArraySubscriptNode,
eErrorNode,
eIdentifierNode,
eScalarLiteralNode,
eUnaryOpNode,
};

Expand Down Expand Up @@ -98,8 +96,8 @@ class UnaryOpNode : public ASTNode {

llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;

UnaryOpKind GetKind() const { return m_kind; }
ASTNode *GetOperand() const { return m_operand.get(); }
UnaryOpKind kind() const { return m_kind; }
ASTNode *operand() const { return m_operand.get(); }

static bool classof(const ASTNode *node) {
return node->GetKind() == NodeKind::eUnaryOpNode;
Expand All @@ -110,26 +108,6 @@ class UnaryOpNode : public ASTNode {
ASTNodeUP m_operand;
};

class ArraySubscriptNode : public ASTNode {
public:
ArraySubscriptNode(uint32_t location, ASTNodeUP base, int64_t index)
: ASTNode(location, NodeKind::eArraySubscriptNode),
m_base(std::move(base)), m_index(index) {}

llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;

ASTNode *GetBase() const { return m_base.get(); }
int64_t GetIndex() const { return m_index; }

static bool classof(const ASTNode *node) {
return node->GetKind() == NodeKind::eArraySubscriptNode;
}

private:
ASTNodeUP m_base;
int64_t m_index;
};

/// 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
Expand All @@ -141,8 +119,6 @@ class Visitor {
Visit(const IdentifierNode *node) = 0;
virtual llvm::Expected<lldb::ValueObjectSP>
Visit(const UnaryOpNode *node) = 0;
virtual llvm::Expected<lldb::ValueObjectSP>
Visit(const ArraySubscriptNode *node) = 0;
};

} // namespace lldb_private::dil
Expand Down
2 changes: 0 additions & 2 deletions lldb/include/lldb/ValueObject/DILEval.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ class Interpreter : Visitor {
llvm::Expected<lldb::ValueObjectSP>
Visit(const IdentifierNode *node) override;
llvm::Expected<lldb::ValueObjectSP> Visit(const UnaryOpNode *node) override;
llvm::Expected<lldb::ValueObjectSP>
Visit(const ArraySubscriptNode *node) override;

// Used by the interpreter to create objects, perform casts, etc.
lldb::TargetSP m_target;
Expand Down
3 changes: 0 additions & 3 deletions lldb/include/lldb/ValueObject/DILLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ class Token {
eof,
identifier,
l_paren,
l_square,
numeric_constant,
r_paren,
r_square,
star,
};

Expand Down
2 changes: 0 additions & 2 deletions lldb/include/lldb/ValueObject/DILParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,12 @@ class DILParser {

ASTNodeUP ParseExpression();
ASTNodeUP ParseUnaryExpression();
ASTNodeUP ParsePostfixExpression();
ASTNodeUP ParsePrimaryExpression();

std::string ParseNestedNameSpecifier();

std::string ParseIdExpression();
std::string ParseUnqualifiedId();
std::optional<int64_t> ParseIntegerConstant();

void BailOut(const std::string &error, uint32_t loc, uint16_t err_len);

Expand Down
5 changes: 0 additions & 5 deletions lldb/source/ValueObject/DILAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,4 @@ llvm::Expected<lldb::ValueObjectSP> UnaryOpNode::Accept(Visitor *v) const {
return v->Visit(this);
}

llvm::Expected<lldb::ValueObjectSP>
ArraySubscriptNode::Accept(Visitor *v) const {
return v->Visit(this);
}

} // namespace lldb_private::dil
51 changes: 2 additions & 49 deletions lldb/source/ValueObject/DILEval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,13 @@ Interpreter::Visit(const IdentifierNode *node) {
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const UnaryOpNode *node) {
Status error;
auto rhs_or_err = Evaluate(node->GetOperand());
auto rhs_or_err = Evaluate(node->operand());
if (!rhs_or_err)
return rhs_or_err;

lldb::ValueObjectSP rhs = *rhs_or_err;

switch (node->GetKind()) {
switch (node->kind()) {
case UnaryOpKind::Deref: {
lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue(m_default_dynamic);
if (dynamic_rhs)
Expand Down Expand Up @@ -272,51 +272,4 @@ Interpreter::Visit(const UnaryOpNode *node) {
m_expr, "invalid ast: unexpected binary operator", node->GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const ArraySubscriptNode *node) {
auto lhs_or_err = Evaluate(node->GetBase());
if (!lhs_or_err)
return lhs_or_err;
lldb::ValueObjectSP base = *lhs_or_err;

// Check to see if 'base' has a synthetic value; if so, try using that.
uint64_t child_idx = node->GetIndex();
if (lldb::ValueObjectSP synthetic = base->GetSyntheticValue()) {
llvm::Expected<uint32_t> num_children =
synthetic->GetNumChildren(child_idx + 1);
if (!num_children)
return llvm::make_error<DILDiagnosticError>(
m_expr, toString(num_children.takeError()), node->GetLocation());
if (child_idx >= *num_children) {
std::string message = llvm::formatv(
"array index {0} is not valid for \"({1}) {2}\"", child_idx,
base->GetTypeName().AsCString("<invalid type>"),
base->GetName().AsCString());
return llvm::make_error<DILDiagnosticError>(m_expr, message,
node->GetLocation());
}
if (lldb::ValueObjectSP child_valobj_sp =
synthetic->GetChildAtIndex(child_idx))
return child_valobj_sp;
}

auto base_type = base->GetCompilerType().GetNonReferenceType();
if (!base_type.IsPointerType() && !base_type.IsArrayType())
return llvm::make_error<DILDiagnosticError>(
m_expr, "subscripted value is not an array or pointer",
node->GetLocation());
if (base_type.IsPointerToVoid())
return llvm::make_error<DILDiagnosticError>(
m_expr, "subscript of pointer to incomplete type 'void'",
node->GetLocation());

if (base_type.IsArrayType()) {
if (lldb::ValueObjectSP child_valobj_sp = base->GetChildAtIndex(child_idx))
return child_valobj_sp;
}

int64_t signed_child_idx = node->GetIndex();
return base->GetSyntheticArrayMember(signed_child_idx, true);
}

} // namespace lldb_private::dil
30 changes: 3 additions & 27 deletions lldb/source/ValueObject/DILLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

#include "lldb/ValueObject/DILLexer.h"
#include "lldb/Utility/Status.h"
#include "lldb/ValueObject/DILParser.h"
#include "llvm/ADT/StringSwitch.h"

namespace lldb_private::dil {
Expand All @@ -30,14 +29,8 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
return "identifier";
case Kind::l_paren:
return "l_paren";
case Kind::l_square:
return "l_square";
case Kind::numeric_constant:
return "numeric_constant";
case Kind::r_paren:
return "r_paren";
case Kind::r_square:
return "r_square";
case Token::star:
return "star";
}
Expand All @@ -64,18 +57,6 @@ static std::optional<llvm::StringRef> IsWord(llvm::StringRef expr,
return candidate;
}

static bool IsNumberBodyChar(char ch) { return IsDigit(ch) || IsLetter(ch); }

static std::optional<llvm::StringRef> IsNumber(llvm::StringRef expr,
llvm::StringRef &remainder) {
if (IsDigit(remainder[0])) {
llvm::StringRef number = remainder.take_while(IsNumberBodyChar);
remainder = remainder.drop_front(number.size());
return number;
}
return std::nullopt;
}

llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr) {
std::vector<Token> tokens;
llvm::StringRef remainder = expr;
Expand All @@ -100,26 +81,21 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
return Token(Token::eof, "", (uint32_t)expr.size());

uint32_t position = cur_pos - expr.begin();
std::optional<llvm::StringRef> maybe_number = IsNumber(expr, remainder);
if (maybe_number)
return Token(Token::numeric_constant, maybe_number->str(), position);
std::optional<llvm::StringRef> maybe_word = IsWord(expr, remainder);
if (maybe_word)
return Token(Token::identifier, maybe_word->str(), position);

constexpr std::pair<Token::Kind, const char *> operators[] = {
{Token::amp, "&"}, {Token::coloncolon, "::"}, {Token::l_paren, "("},
{Token::l_square, "["}, {Token::r_paren, ")"}, {Token::r_square, "]"},
{Token::star, "*"},
{Token::amp, "&"}, {Token::coloncolon, "::"}, {Token::l_paren, "("},
{Token::r_paren, ")"}, {Token::star, "*"},
};
for (auto [kind, str] : operators) {
if (remainder.consume_front(str))
return Token(kind, str, position);
}

// Unrecognized character(s) in string; unable to lex it.
return llvm::make_error<DILDiagnosticError>(expr, "unrecognized token",
position);
return llvm::createStringError("Unable to lex input string");
}

} // namespace lldb_private::dil
54 changes: 1 addition & 53 deletions lldb/source/ValueObject/DILParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,42 +111,7 @@ ASTNodeUP DILParser::ParseUnaryExpression() {
llvm_unreachable("invalid token kind");
}
}
return ParsePostfixExpression();
}

// Parse a postfix_expression.
//
// postfix_expression:
// primary_expression
// postfix_expression "[" integer_literal "]"
//
ASTNodeUP DILParser::ParsePostfixExpression() {
ASTNodeUP lhs = ParsePrimaryExpression();
while (CurToken().Is(Token::l_square)) {
uint32_t loc = CurToken().GetLocation();
Token token = CurToken();
switch (token.GetKind()) {
case Token::l_square: {
m_dil_lexer.Advance();
std::optional<int64_t> rhs = ParseIntegerConstant();
if (!rhs) {
BailOut(
llvm::formatv("failed to parse integer constant: {0}", CurToken()),
CurToken().GetLocation(), CurToken().GetSpelling().length());
return std::make_unique<ErrorNode>();
}
Expect(Token::r_square);
m_dil_lexer.Advance();
lhs = std::make_unique<ArraySubscriptNode>(loc, std::move(lhs),
std::move(*rhs));
break;
}
default:
llvm_unreachable("invalid token");
}
}

return lhs;
return ParsePrimaryExpression();
}

// Parse a primary_expression.
Expand Down Expand Up @@ -315,23 +280,6 @@ void DILParser::BailOut(const std::string &error, uint32_t loc,
m_dil_lexer.ResetTokenIdx(m_dil_lexer.NumLexedTokens() - 1);
}

// Parse a integer_literal.
//
// integer_literal:
// ? Integer constant ?
//
std::optional<int64_t> DILParser::ParseIntegerConstant() {
auto spelling = CurToken().GetSpelling();
llvm::StringRef spelling_ref = spelling;
int64_t raw_value;
if (!spelling_ref.getAsInteger<int64_t>(0, raw_value)) {
m_dil_lexer.Advance();
return raw_value;
}

return std::nullopt;
}

void DILParser::Expect(Token::Kind kind) {
if (CurToken().IsNot(kind)) {
BailOut(llvm::formatv("expected {0}, got: {1}", kind, CurToken()),
Expand Down

This file was deleted.

Loading
Loading