https://github.com/kuilpd created https://github.com/llvm/llvm-project/pull/184017
None >From d2634ad124b1e117e1d7af36c9e59dc25bcd7e24 Mon Sep 17 00:00:00 2001 From: Ilia Kuklin <[email protected]> Date: Sun, 1 Mar 2026 21:46:43 +0500 Subject: [PATCH] [lldb] Add arithmetic binary subtraction to DIL --- lldb/docs/dil-expr-lang.ebnf | 3 ++- lldb/include/lldb/ValueObject/DILAST.h | 1 + lldb/include/lldb/ValueObject/DILEval.h | 3 +++ lldb/source/ValueObject/DILAST.cpp | 2 ++ lldb/source/ValueObject/DILEval.cpp | 26 +++++++++++++++++++ lldb/source/ValueObject/DILParser.cpp | 2 +- .../TestFrameVarDILBitFieldExtraction.py | 8 +++--- .../Arithmetic/TestFrameVarDILArithmetic.py | 25 ++++++++++++++++++ .../frame/var-dil/expr/Arithmetic/main.cpp | 2 ++ 9 files changed, 65 insertions(+), 7 deletions(-) diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf index 127c1d6337efa..cdf85d75fd8e2 100644 --- a/lldb/docs/dil-expr-lang.ebnf +++ b/lldb/docs/dil-expr-lang.ebnf @@ -5,7 +5,8 @@ expression = additive_expression ; -additive_expression = cast_expression {"+" cast_expression} ; +additive_expression = cast_expression {"+" cast_expression} + cast_expression {"-" cast_expression} ; cast_expression = unary_expression | "(" type_id ")" cast_expression; diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h index 226f80ac70c5e..350722fa6f22d 100644 --- a/lldb/include/lldb/ValueObject/DILAST.h +++ b/lldb/include/lldb/ValueObject/DILAST.h @@ -43,6 +43,7 @@ enum class UnaryOpKind { /// The binary operators recognized by DIL. enum class BinaryOpKind { Add, // "+" + Sub, // "-" }; /// Translates DIL tokens to BinaryOpKind. diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 54d33129908a3..a6223c4d998ab 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -97,6 +97,9 @@ class Interpreter : Visitor { llvm::Expected<lldb::ValueObjectSP> EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location); + llvm::Expected<lldb::ValueObjectSP> + EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, + uint32_t location); llvm::Expected<CompilerType> PickIntegerType(lldb::TypeSystemSP type_system, std::shared_ptr<ExecutionContextScope> ctx, diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp index 180708f79c269..dadd4cd365c7e 100644 --- a/lldb/source/ValueObject/DILAST.cpp +++ b/lldb/source/ValueObject/DILAST.cpp @@ -15,6 +15,8 @@ BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind) { switch (token_kind) { case Token::plus: return BinaryOpKind::Add; + case Token::minus: + return BinaryOpKind::Sub; default: break; } diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index acefb5dc6133b..1b841d39a034e 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -558,6 +558,8 @@ Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs, switch (kind) { case BinaryOpKind::Add: return value_object(l + r); + case BinaryOpKind::Sub: + return value_object(l - r); } return llvm::make_error<DILDiagnosticError>( m_expr, "invalid arithmetic operation", location); @@ -585,6 +587,28 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition( location); } +llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction( + lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) { + // Operation '-' works for: + // {scalar,unscoped_enum} <-> {scalar,unscoped_enum} + // TODO: Pointer arithmetics + auto orig_lhs_type = lhs->GetCompilerType(); + auto orig_rhs_type = rhs->GetCompilerType(); + auto type_or_err = ArithmeticConversion(lhs, rhs, location); + if (!type_or_err) + return type_or_err.takeError(); + CompilerType result_type = *type_or_err; + + if (result_type.IsScalarType()) + return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location); + + std::string errMsg = + llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')", + orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName()); + return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg), + location); +} + llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const BinaryOpNode &node) { auto lhs_or_err = EvaluateAndDereference(node.GetLHS()); @@ -609,6 +633,8 @@ Interpreter::Visit(const BinaryOpNode &node) { switch (node.GetKind()) { case BinaryOpKind::Add: return EvaluateBinaryAddition(lhs, rhs, node.GetLocation()); + case BinaryOpKind::Sub: + return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation()); } return llvm::make_error<DILDiagnosticError>( diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index f07607c93d927..bb5a86bc7168b 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -138,7 +138,7 @@ ASTNodeUP DILParser::ParseAdditiveExpression() { auto lhs = ParseCastExpression(); assert(lhs && "ASTNodeUP must not contain a nullptr"); - while (CurToken().Is(Token::plus)) { + while (CurToken().IsOneOf({Token::plus, Token::minus})) { Token token = CurToken(); m_dil_lexer.Advance(); auto rhs = ParseCastExpression(); diff --git a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py index 0899083568125..026658c0cd25f 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py +++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py @@ -35,6 +35,9 @@ def test_bitfield_extraction(self): self.expect_var_path("value[0:enum_one]", value="3", type="int:2") self.expect_var_path("value[enum_one:0]", value="3", type="int:2") + # Test that old range syntax is now a binary subtraction + self.expect_var_path("value[6-1]", value="1", type="int:1") + # Test array and pointer self.expect( "frame var 'int_arr[0:2]'", @@ -63,8 +66,3 @@ def test_bitfield_extraction(self): error=True, substrs=["bit index is not an integer"], ) - self.expect( - "frame var 'value[0-2]'", - error=True, - substrs=["use of '-' for bitfield range is deprecated; use ':' instead"], - ) diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py index 5b68c493ba3a5..bdf95d7b22cb5 100644 --- a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py @@ -63,15 +63,25 @@ def test_arithmetic(self): self.expect_var_path("1 + s + (x + l)", value="18", type="long") self.expect_var_path("+2 + (-1)", value="1", type="int") self.expect_var_path("-2 + (+1)", value="-1", type="int") + self.expect_var_path("1 + (2 - 3)", value="0") + self.expect_var_path("s - x - 1", value="7") # Check limits and overflows frame = thread.GetFrameAtIndex(0) int_min = frame.GetValueForVariablePath("int_min").GetValue() + int_max = frame.GetValueForVariablePath("int_max").GetValue() + uint_max = frame.GetValueForVariablePath("uint_max").GetValue() ll_min = frame.GetValueForVariablePath("ll_min").GetValue() + ll_max = frame.GetValueForVariablePath("ll_max").GetValue() + ull_max = frame.GetValueForVariablePath("ull_max").GetValue() self.expect_var_path("int_max + 1", value=int_min) + self.expect_var_path("int_min - 1", value=int_max) self.expect_var_path("uint_max + 1", value="0") + self.expect_var_path("uint_zero - 1", value=uint_max) self.expect_var_path("ll_max + 1", value=ll_min) + self.expect_var_path("ll_min - 1", value=ll_max) self.expect_var_path("ull_max + 1", value="0") + self.expect_var_path("ull_zero - 1", value=ull_max) # Check signed integer promotion when different types have the same size uint = frame.GetValueForVariablePath("ui") @@ -87,5 +97,20 @@ def test_arithmetic(self): # Check references and typedefs self.expect_var_path("ref + 1", value="3") + self.expect_var_path("ref - 1l", value="1") self.expect_var_path("my_ref + 1", value="3") + self.expect_var_path("my_ref - 1", value="1") self.expect_var_path("ref + my_ref", value="4") + self.expect_var_path("ref - my_ref", value="0") + + # TODO: Pointer arithmetics + self.expect( + "frame var -- 'p + 1'", + error=True, + substrs=["invalid operands to binary expression ('int *' and 'int')"], + ) + self.expect( + "frame var -- 'p - 1'", + error=True, + substrs=["invalid operands to binary expression ('int *' and 'int')"], + ) diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp index f41b89beb2bde..1561ed6c8f655 100644 --- a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp @@ -33,9 +33,11 @@ int main(int argc, char **argv) { int int_max = std::numeric_limits<int>::max(); int int_min = std::numeric_limits<int>::min(); unsigned int uint_max = std::numeric_limits<unsigned int>::max(); + unsigned int uint_zero = 0; long long ll_max = std::numeric_limits<long long>::max(); long long ll_min = std::numeric_limits<long long>::min(); unsigned long long ull_max = std::numeric_limits<unsigned long long>::max(); + unsigned long long ull_zero = 0; return 0; // Set a breakpoint here } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
