Skip to content

Conversation

@cmtice
Copy link
Contributor

@cmtice cmtice commented Sep 11, 2025

This adds the ability to recognize (and create ValueObjects for) boolean literals ("true", "false") to DIL. This is a preliminary step to adding type casting (and also for the ternary op).

This adds the ability to recognize (and create ValueObjects for)
boolean literals ("true", "false") to DIL. This is a preliminary
step to adding type casting (and also for the ternary op).
@cmtice cmtice requested review from kuilpd and labath and removed request for JDevlieghere and labath September 11, 2025 05:01
@llvmbot llvmbot added the lldb label Sep 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2025

@llvm/pr-subscribers-lldb

Author: None (cmtice)

Changes

This adds the ability to recognize (and create ValueObjects for) boolean literals ("true", "false") to DIL. This is a preliminary step to adding type casting (and also for the ternary op).


Full diff: https://github.com/llvm/llvm-project/pull/157992.diff

9 Files Affected:

  • (modified) lldb/docs/dil-expr-lang.ebnf (+3)
  • (modified) lldb/include/lldb/ValueObject/DILAST.h (+20)
  • (modified) lldb/include/lldb/ValueObject/DILEval.h (+2)
  • (modified) lldb/include/lldb/ValueObject/DILLexer.h (+2)
  • (modified) lldb/include/lldb/ValueObject/DILParser.h (+3)
  • (modified) lldb/source/ValueObject/DILAST.cpp (+5)
  • (modified) lldb/source/ValueObject/DILEval.cpp (+6)
  • (modified) lldb/source/ValueObject/DILLexer.cpp (+12-3)
  • (modified) lldb/source/ValueObject/DILParser.cpp (+25)
diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
index 67328939ba420..70eda3bf40650 100644
--- a/lldb/docs/dil-expr-lang.ebnf
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -16,6 +16,7 @@ postfix_expression = primary_expression
                    | postfix_expression "->" id_expression ;
 
 primary_expression = numeric_literal
+                   | boolean_literal
                    | id_expression
                    | "(" expression ")" ;
 
@@ -35,6 +36,8 @@ integer_literal = ? Integer constant: hexademical, decimal, octal, binary ? ;
 numeric_literal = ? Integer constant: hexademical, decimal, octal, binary ?
                 | ? Floating constant ? ;
 
+boolean_literal = "true" | "false" ;
+
 register = "$" ? Register name ? ;
 
 nested_name_specifier = type_name "::"
diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h
index 1d10755c46e39..0f05d753f1b56 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -20,6 +20,7 @@ namespace lldb_private::dil {
 enum class NodeKind {
   eArraySubscriptNode,
   eBitExtractionNode,
+  eBooleanLiteralNode,
   eErrorNode,
   eFloatLiteralNode,
   eIdentifierNode,
@@ -226,6 +227,23 @@ class FloatLiteralNode : public ASTNode {
   llvm::APFloat m_value;
 };
 
+class BooleanLiteralNode : public ASTNode {
+public:
+  BooleanLiteralNode(uint32_t location, bool value)
+      : ASTNode(location, NodeKind::eBooleanLiteralNode), m_value(value) {}
+
+  llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
+
+  bool GetValue() const & { return m_value; }
+
+  static bool classof(const ASTNode *node) {
+    return node->GetKind() == NodeKind::eBooleanLiteralNode;
+  }
+
+private:
+  bool m_value;
+};
+
 /// 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
@@ -247,6 +265,8 @@ class Visitor {
   Visit(const IntegerLiteralNode *node) = 0;
   virtual llvm::Expected<lldb::ValueObjectSP>
   Visit(const FloatLiteralNode *node) = 0;
+  virtual llvm::Expected<lldb::ValueObjectSP>
+  Visit(const BooleanLiteralNode *node) = 0;
 };
 
 } // namespace lldb_private::dil
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index 5a48c2c989f4d..eab3218ff828f 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -58,6 +58,8 @@ class Interpreter : Visitor {
   Visit(const IntegerLiteralNode *node) override;
   llvm::Expected<lldb::ValueObjectSP>
   Visit(const FloatLiteralNode *node) override;
+  llvm::Expected<lldb::ValueObjectSP>
+  Visit(const BooleanLiteralNode *node) override;
 
   llvm::Expected<CompilerType>
   PickIntegerType(lldb::TypeSystemSP type_system,
diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 4345e6ce7f26b..28b94a79c5902 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -31,6 +31,8 @@ class Token {
     float_constant,
     identifier,
     integer_constant,
+    kw_false,
+    kw_true,
     l_paren,
     l_square,
     minus,
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
index 90df109337dcf..d17ed66d9b3ee 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -99,11 +99,14 @@ class DILParser {
   ASTNodeUP ParseNumericLiteral();
   ASTNodeUP ParseIntegerLiteral();
   ASTNodeUP ParseFloatingPointLiteral();
+  ASTNodeUP ParseBooleanLiteral();
 
   void BailOut(const std::string &error, uint32_t loc, uint16_t err_len);
 
   void Expect(Token::Kind kind);
 
+  void ExpectOneOf(std::vector<Token::Kind> kinds_vec);
+
   void TentativeParsingRollback(uint32_t saved_idx) {
     if (m_error)
       llvm::consumeError(std::move(m_error));
diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp
index 70564663a62cd..7ed34db6e20df 100644
--- a/lldb/source/ValueObject/DILAST.cpp
+++ b/lldb/source/ValueObject/DILAST.cpp
@@ -46,4 +46,9 @@ llvm::Expected<lldb::ValueObjectSP> FloatLiteralNode::Accept(Visitor *v) const {
   return v->Visit(this);
 }
 
+llvm::Expected<lldb::ValueObjectSP>
+BooleanLiteralNode::Accept(Visitor *v) const {
+  return v->Visit(this);
+}
+
 } // namespace lldb_private::dil
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index c6cf41ee9e9ee..a9dbfad298d05 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -602,4 +602,10 @@ Interpreter::Visit(const FloatLiteralNode *node) {
                                                   "result");
 }
 
+llvm::Expected<lldb::ValueObjectSP>
+Interpreter::Visit(const BooleanLiteralNode *node) {
+  bool value = node->GetValue();
+  return ValueObject::CreateValueObjectFromBool(m_target, value, "result");
+}
+
 } // namespace lldb_private::dil
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index 0b2288a9d9230..e0202a2fe24cc 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -34,6 +34,10 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
     return "identifier";
   case Kind::integer_constant:
     return "integer_constant";
+  case Kind::kw_false:
+    return "false";
+  case Kind::kw_true:
+    return "true";
   case Kind::l_paren:
     return "l_paren";
   case Kind::l_square:
@@ -42,7 +46,6 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
     return "minus";
   case Kind::period:
     return "period";
-    return "l_square";
   case Kind::plus:
     return "plus";
   case Kind::r_paren:
@@ -137,8 +140,14 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
     return Token(kind, maybe_number->str(), position);
   }
   std::optional<llvm::StringRef> maybe_word = IsWord(expr, remainder);
-  if (maybe_word)
-    return Token(Token::identifier, maybe_word->str(), position);
+  if (maybe_word) {
+    llvm::StringRef word = *maybe_word;
+    Token::Kind kind = llvm::StringSwitch<Token::Kind>(word)
+                           .Case("false", Token::kw_false)
+                           .Case("true", Token::kw_true)
+                           .Default(Token::identifier);
+    return Token(kind, word.str(), position);
+  }
 
   constexpr std::pair<Token::Kind, const char *> operators[] = {
       {Token::amp, "&"},      {Token::arrow, "->"},   {Token::coloncolon, "::"},
diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp
index 8c4f7fdb25bea..566bcaf81094a 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -180,12 +180,15 @@ ASTNodeUP DILParser::ParsePostfixExpression() {
 //
 //  primary_expression:
 //    numeric_literal
+//    boolean_literal
 //    id_expression
 //    "(" expression ")"
 //
 ASTNodeUP DILParser::ParsePrimaryExpression() {
   if (CurToken().IsOneOf({Token::integer_constant, Token::float_constant}))
     return ParseNumericLiteral();
+  if (CurToken().IsOneOf({Token::kw_true, Token::kw_false}))
+    return ParseBooleanLiteral();
   if (CurToken().IsOneOf(
           {Token::coloncolon, Token::identifier, Token::l_paren})) {
     // Save the source location for the diagnostics message.
@@ -336,6 +339,20 @@ std::string DILParser::ParseUnqualifiedId() {
   return identifier;
 }
 
+// Parse an boolean_literal.
+//
+//  boolean_literal:
+//    "true"
+//    "false"
+//
+ASTNodeUP DILParser::ParseBooleanLiteral() {
+  ExpectOneOf(std::vector<Token::Kind>{Token::kw_true, Token::kw_false});
+  uint32_t loc = CurToken().GetLocation();
+  bool literal_value = CurToken().Is(Token::kw_true);
+  m_dil_lexer.Advance();
+  return std::make_unique<BooleanLiteralNode>(loc, literal_value);
+}
+
 void DILParser::BailOut(const std::string &error, uint32_t loc,
                         uint16_t err_len) {
   if (m_error)
@@ -444,4 +461,12 @@ void DILParser::Expect(Token::Kind kind) {
   }
 }
 
+void DILParser::ExpectOneOf(std::vector<Token::Kind> kinds_vec) {
+  if (!CurToken().IsOneOf(kinds_vec)) {
+    BailOut(llvm::formatv("expected any of ({0}), got: {1}",
+                          llvm::iterator_range(kinds_vec), CurToken()),
+            CurToken().GetLocation(), CurToken().GetSpelling().length());
+  }
+}
+
 } // namespace lldb_private::dil

@kuilpd
Copy link
Contributor

kuilpd commented Sep 11, 2025

Can we add a couple of tests for these to TestFrameVarDILLiterals.py?

@cmtice
Copy link
Contributor Author

cmtice commented Sep 11, 2025

Can we add a couple of tests for these to TestFrameVarDILLiterals.py?

Done. :-)

@cmtice cmtice requested review from adrian-prantl and jimingham and removed request for labath September 13, 2025 00:16
Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty straightforward. LGTM.

@cmtice cmtice merged commit 9855d54 into llvm:main Sep 16, 2025
10 checks passed
kuilpd pushed a commit to kuilpd/llvm-project that referenced this pull request Oct 15, 2025
This adds the ability to recognize (and create ValueObjects for) boolean
literals ("true", "false") to DIL. This is a preliminary step to adding
type casting (and also for the ternary op).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants