Skip to content

Conversation

@da-viper
Copy link
Contributor

Vector registers have synthetic values for display purposes. This causes SBValue::GetExpressionPath to dispatch
to ValueObjectSynthetic instead of ValueObjectRegister, producing incorrect results.

Fixes #147144

Vector registers have synthetic values for display purposes.
This causes SBValue::GetExpressionPath to dispatch
to ValueObjectSynthetic instead of ValueObjectRegister,
producing incorrect results.
@llvmbot
Copy link
Member

llvmbot commented Nov 23, 2025

@llvm/pr-subscribers-lldb

Author: Ebuka Ezike (da-viper)

Changes

Vector registers have synthetic values for display purposes. This causes SBValue::GetExpressionPath to dispatch
to ValueObjectSynthetic instead of ValueObjectRegister, producing incorrect results.

Fixes #147144


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

5 Files Affected:

  • (modified) lldb/include/lldb/ValueObject/ValueObjectSynthetic.h (+5)
  • (modified) lldb/source/ValueObject/ValueObjectSynthetic.cpp (+12)
  • (added) lldb/test/API/python_api/exprpath_register/Makefile (+3)
  • (added) lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py (+64)
  • (added) lldb/test/API/python_api/exprpath_register/main.c (+10)
diff --git a/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h b/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
index 063d796ee4eec..1a82fd78bbba3 100644
--- a/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
+++ b/lldb/include/lldb/ValueObject/ValueObjectSynthetic.h
@@ -123,6 +123,11 @@ class ValueObjectSynthetic : public ValueObject {
 
   void SetLanguageFlags(uint64_t flags) override;
 
+  void
+  GetExpressionPath(Stream &stream,
+                    GetExpressionPathFormat epformat =
+                        eGetExpressionPathFormatDereferencePointers) override;
+
 protected:
   bool UpdateValue() override;
 
diff --git a/lldb/source/ValueObject/ValueObjectSynthetic.cpp b/lldb/source/ValueObject/ValueObjectSynthetic.cpp
index f673c51a88412..1b689257224df 100644
--- a/lldb/source/ValueObject/ValueObjectSynthetic.cpp
+++ b/lldb/source/ValueObject/ValueObjectSynthetic.cpp
@@ -443,3 +443,15 @@ void ValueObjectSynthetic::SetLanguageFlags(uint64_t flags) {
   else
     this->ValueObject::SetLanguageFlags(flags);
 }
+
+void ValueObjectSynthetic::GetExpressionPath(Stream &stream,
+                                             GetExpressionPathFormat epformat) {
+  if (const lldb::ValueType obj_value_type = GetValueType();
+      IsSynthetic() && (obj_value_type == lldb::eValueTypeRegister ||
+                        obj_value_type == lldb::eValueTypeRegisterSet)) {
+
+    if (const lldb::ValueObjectSP raw_value = GetNonSyntheticValue())
+      return raw_value->GetExpressionPath(stream, epformat);
+  }
+  return ValueObject::GetExpressionPath(stream, epformat);
+}
diff --git a/lldb/test/API/python_api/exprpath_register/Makefile b/lldb/test/API/python_api/exprpath_register/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/python_api/exprpath_register/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py b/lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py
new file mode 100644
index 0000000000000..4ffbc5e49fb0d
--- /dev/null
+++ b/lldb/test/API/python_api/exprpath_register/TestExprPathRegisters.py
@@ -0,0 +1,64 @@
+"""
+Test Getting the expression path for registers works correctly
+"""
+
+import lldb
+from lldbsuite.test import lldbutil
+from lldbsuite.test.lldbtest import TestBase, VALID_BREAKPOINT, VALID_TARGET
+
+
+class TestExprPathRegisters(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def verify_register_path(self, reg_value: lldb.SBValue):
+        stream = lldb.SBStream()
+        reg_name = reg_value.name
+        self.assertTrue(
+            reg_value.GetExpressionPath(stream),
+            f"Expected an expression path for register {reg_name}.",
+        )
+        reg_expr_path = stream.GetData()
+        self.assertEqual(reg_expr_path, f"${reg_name}")
+
+    def test_float_registers(self):
+        """Verify the expression path of the registers is valid."""
+        self.build()
+        _, _, thread, _ = lldbutil.run_to_name_breakpoint(self, "my_foo")
+        frame = thread.GetSelectedFrame()
+        self.assertTrue(frame, "Expected a valid Frame.")
+
+        # possible floating point register on some cpus.
+        register_names = [
+            "xmm0",
+            "ymm0",
+            "v0",
+            "v1",
+            "f0",
+            "f1",
+            "d0",
+            "d1",
+            "vr0",
+            "vr1",
+            "st0",
+            "st1",
+        ]
+        for name in register_names:
+            reg_value = frame.FindRegister(name)
+            # some the register will not be available for the cpu
+            # only verify if it is valid.
+            if reg_value:
+                self.verify_register_path(reg_value)
+
+    def test_all_registers(self):
+        """Test all the registers that is avaiable on the machine"""
+        self.build()
+        _, _, thread, _ = lldbutil.run_to_name_breakpoint(self, "my_foo")
+        frame = thread.GetSelectedFrame()
+        self.assertTrue(frame, "Expected a valid Frame.")
+
+        register_sets = frame.GetRegisters()
+        self.assertTrue(register_sets.IsValid(), "Expected Frame Registers")
+
+        for register_set in register_sets:
+            for register in register_set.children:
+                self.verify_register_path(register)
diff --git a/lldb/test/API/python_api/exprpath_register/main.c b/lldb/test/API/python_api/exprpath_register/main.c
new file mode 100644
index 0000000000000..4809a87cdf210
--- /dev/null
+++ b/lldb/test/API/python_api/exprpath_register/main.c
@@ -0,0 +1,10 @@
+
+float my_foo() {
+  float result = 10.0 + 20.0;
+  return result;
+}
+
+int main(void) {
+  float result = my_foo();
+  return (int)result;
+}

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.

[lldb-dap] Incorrect value of evaluateName for vector registers

2 participants