llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Ilia Kuklin (kuilpd) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/141422.diff 11 Files Affected: - (modified) lldb/include/lldb/ValueObject/DILAST.h (+27) - (modified) lldb/include/lldb/ValueObject/DILEval.h (+2) - (modified) lldb/include/lldb/ValueObject/DILLexer.h (+1) - (modified) lldb/source/ValueObject/DILAST.cpp (+5) - (modified) lldb/source/ValueObject/DILEval.cpp (+32) - (modified) lldb/source/ValueObject/DILLexer.cpp (+5-2) - (modified) lldb/source/ValueObject/DILParser.cpp (+18-4) - (modified) lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py (+1-1) - (added) lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/Makefile (+3) - (added) lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py (+56) - (added) lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp (+9) ``````````diff diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h index 6c7838e05c93c..709f0639135f1 100644 --- a/lldb/include/lldb/ValueObject/DILAST.h +++ b/lldb/include/lldb/ValueObject/DILAST.h @@ -19,6 +19,7 @@ namespace lldb_private::dil { /// The various types DIL AST nodes (used by the DIL parser). enum class NodeKind { eArraySubscriptNode, + eBitExtractionNode, eErrorNode, eIdentifierNode, eMemberOfNode, @@ -153,6 +154,30 @@ class ArraySubscriptNode : public ASTNode { int64_t m_index; }; +class BitFieldExtractionNode : public ASTNode { +public: + BitFieldExtractionNode(uint32_t location, ASTNodeUP base, int64_t first_index, + int64_t last_index) + : ASTNode(location, NodeKind::eBitExtractionNode), + m_base(std::move(base)), m_first_index(first_index), + m_last_index(last_index) {} + + llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override; + + ASTNode *GetBase() const { return m_base.get(); } + int64_t GetFirstIndex() const { return m_first_index; } + int64_t GetLastIndex() const { return m_last_index; } + + static bool classof(const ASTNode *node) { + return node->GetKind() == NodeKind::eBitExtractionNode; + } + +private: + ASTNodeUP m_base; + int64_t m_first_index; + int64_t m_last_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 @@ -168,6 +193,8 @@ class Visitor { Visit(const UnaryOpNode *node) = 0; virtual llvm::Expected<lldb::ValueObjectSP> Visit(const ArraySubscriptNode *node) = 0; + virtual llvm::Expected<lldb::ValueObjectSP> + Visit(const BitFieldExtractionNode *node) = 0; }; } // namespace lldb_private::dil diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 9d0fa53c6622a..2a0cb548a810f 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -54,6 +54,8 @@ class Interpreter : Visitor { llvm::Expected<lldb::ValueObjectSP> Visit(const UnaryOpNode *node) override; llvm::Expected<lldb::ValueObjectSP> Visit(const ArraySubscriptNode *node) override; + llvm::Expected<lldb::ValueObjectSP> + Visit(const BitFieldExtractionNode *node) override; // Used by the interpreter to create objects, perform casts, etc. lldb::TargetSP m_target; diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h index 7d70f88f9a718..9c1ba97680253 100644 --- a/lldb/include/lldb/ValueObject/DILLexer.h +++ b/lldb/include/lldb/ValueObject/DILLexer.h @@ -31,6 +31,7 @@ class Token { identifier, l_paren, l_square, + minus, numeric_constant, period, r_paren, diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp index 8b5e64ad462cc..b1cd824c2299e 100644 --- a/lldb/source/ValueObject/DILAST.cpp +++ b/lldb/source/ValueObject/DILAST.cpp @@ -32,4 +32,9 @@ ArraySubscriptNode::Accept(Visitor *v) const { return v->Visit(this); } +llvm::Expected<lldb::ValueObjectSP> +BitFieldExtractionNode::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 c8cb54aa18a93..b2bb4e20ddc24 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -430,4 +430,36 @@ Interpreter::Visit(const ArraySubscriptNode *node) { return base->GetSyntheticArrayMember(signed_child_idx, true); } +llvm::Expected<lldb::ValueObjectSP> +Interpreter::Visit(const BitFieldExtractionNode *node) { + auto lhs_or_err = Evaluate(node->GetBase()); + if (!lhs_or_err) + return lhs_or_err; + lldb::ValueObjectSP base = *lhs_or_err; + int64_t first_index = node->GetFirstIndex(); + int64_t last_index = node->GetLastIndex(); + + // if the format given is [high-low], swap range + if (first_index > last_index) + std::swap(first_index, last_index); + + Status error; + if (base->GetCompilerType().IsReferenceType()) { + base = base->Dereference(error); + if (error.Fail()) + return error.ToError(); + } + lldb::ValueObjectSP child_valobj_sp = + base->GetSyntheticBitFieldChild(first_index, last_index, true); + if (!child_valobj_sp) { + std::string message = llvm::formatv( + "bitfield range {0}-{1} is not valid for \"({2}) {3}\"", first_index, + last_index, base->GetTypeName().AsCString("<invalid type>"), + base->GetName().AsCString()); + return llvm::make_error<DILDiagnosticError>(m_expr, message, + node->GetLocation()); + } + return child_valobj_sp; +} + } // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp index 99182d2da1131..eaefaf484bc18 100644 --- a/lldb/source/ValueObject/DILLexer.cpp +++ b/lldb/source/ValueObject/DILLexer.cpp @@ -34,6 +34,8 @@ llvm::StringRef Token::GetTokenName(Kind kind) { return "l_paren"; case Kind::l_square: return "l_square"; + case Kind::minus: + return "minus"; case Kind::numeric_constant: return "numeric_constant"; case Kind::period: @@ -113,8 +115,9 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr, constexpr std::pair<Token::Kind, const char *> operators[] = { {Token::amp, "&"}, {Token::arrow, "->"}, {Token::coloncolon, "::"}, - {Token::l_paren, "("}, {Token::l_square, "["}, {Token::period, "."}, - {Token::r_paren, ")"}, {Token::r_square, "]"}, {Token::star, "*"}, + {Token::l_paren, "("}, {Token::l_square, "["}, {Token::minus, "-"}, + {Token::period, "."}, {Token::r_paren, ")"}, {Token::r_square, "]"}, + {Token::star, "*"}, }; for (auto [kind, str] : operators) { if (remainder.consume_front(str)) diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index 9667885734f21..32af0820acb98 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -120,6 +120,7 @@ ASTNodeUP DILParser::ParseUnaryExpression() { // postfix_expression: // primary_expression // postfix_expression "[" integer_literal "]" +// postfix_expression "[" integer_literal "-" integer_literal "]" // postfix_expression "." id_expression // postfix_expression "->" id_expression // @@ -131,17 +132,30 @@ ASTNodeUP DILParser::ParsePostfixExpression() { switch (token.GetKind()) { case Token::l_square: { m_dil_lexer.Advance(); - std::optional<int64_t> rhs = ParseIntegerConstant(); - if (!rhs) { + std::optional<int64_t> index = ParseIntegerConstant(); + if (!index) { BailOut( llvm::formatv("failed to parse integer constant: {0}", CurToken()), CurToken().GetLocation(), CurToken().GetSpelling().length()); return std::make_unique<ErrorNode>(); } + if (CurToken().GetKind() == Token::minus) { + m_dil_lexer.Advance(); + std::optional<int64_t> last_index = ParseIntegerConstant(); + if (!last_index) { + BailOut(llvm::formatv("failed to parse integer constant: {0}", + CurToken()), + CurToken().GetLocation(), CurToken().GetSpelling().length()); + return std::make_unique<ErrorNode>(); + } + lhs = std::make_unique<BitFieldExtractionNode>( + loc, std::move(lhs), std::move(*index), std::move(*last_index)); + } else { + lhs = std::make_unique<ArraySubscriptNode>(loc, std::move(lhs), + std::move(*index)); + } Expect(Token::r_square); m_dil_lexer.Advance(); - lhs = std::make_unique<ArraySubscriptNode>(loc, std::move(lhs), - std::move(*rhs)); break; } case Token::period: diff --git a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py index 740a64f1477ff..c28ec6bda799e 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py +++ b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py @@ -62,7 +62,7 @@ def test_subscript(self): self.expect( "frame var 'int_arr[-1]'", error=True, - substrs=["unrecognized token"], + substrs=["failed to parse integer constant"], ) # Test for floating point index diff --git a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/Makefile b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/Makefile new file mode 100644 index 0000000000000..99998b20bcb05 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules 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 new file mode 100644 index 0000000000000..7b5ef0650b6e1 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py @@ -0,0 +1,56 @@ +""" +Test DIL BifField extraction. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test import lldbutil + + +class TestFrameVarDILBitFieldExtraction(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def expect_var_path(self, expr, compare_to_framevar=False, value=None, type=None): + value_dil = super().expect_var_path(expr, value=value, type=type) + if compare_to_framevar: + self.runCmd("settings set target.experimental.use-DIL false") + value_frv = super().expect_var_path(expr, value=value, type=type) + self.runCmd("settings set target.experimental.use-DIL true") + self.assertEqual(value_dil.GetValue(), value_frv.GetValue()) + + def test_bitfield_extraction(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp") + ) + + self.runCmd("settings set target.experimental.use-DIL true") + + # Test ranges and type + self.expect_var_path("value[0-1]", True, value="3", type="int:2") + self.expect_var_path("value[4-7]", True, value="7", type="int:4") + self.expect_var_path("value[7-0]", True, value="115", type="int:8") + + # Test reference and dereferenced pointer + self.expect_var_path("value_ref[0-1]", value="3", type="int:2") + self.expect_var_path("(*value_ptr)[0-1]", value="3", type="int:2") + + # Test array and pointer + self.expect( + "frame var 'int_arr[0-2]'", + error=True, + substrs=["bitfield range 0-2 is not valid"], + ) + self.expect( + "frame var 'value_ptr[0-1]'", + error=True, + substrs=["bitfield range 0-1 is not valid"], + ) + + # Test invalid input + self.expect( + "frame var 'value[1-]'", + error=True, + substrs=["failed to parse integer constant"], + ) diff --git a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp new file mode 100644 index 0000000000000..a35f68a9e30a8 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp @@ -0,0 +1,9 @@ +int main(int argc, char **argv) { + int value = 0b01110011; + int &value_ref = value; + int *value_ptr = &value; + + int int_arr[] = {7, 3, 1}; + + return 0; // Set a breakpoint here +} `````````` </details> https://github.com/llvm/llvm-project/pull/141422 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits