[Lldb-commits] [lldb] 0dfcfb5 - [lldb][DataFormatter] VectorType: fix format for arrays with size not a power-of-2 (#68907)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Oct 13 12:07:45 PDT 2023
Author: Michael Buch
Date: 2023-10-13T20:07:41+01:00
New Revision: 0dfcfb53d7bba22b3a5d36853837d5889b32a744
URL: https://github.com/llvm/llvm-project/commit/0dfcfb53d7bba22b3a5d36853837d5889b32a744
DIFF: https://github.com/llvm/llvm-project/commit/0dfcfb53d7bba22b3a5d36853837d5889b32a744.diff
LOG: [lldb][DataFormatter] VectorType: fix format for arrays with size not a power-of-2 (#68907)
To get the number of children for a VectorType (i.e.,
a type declared with a `vector_size`/`ext_vector_type` attribute)
LLDB previously did following calculation:
1. Get byte-size of the vector container from Clang (`getTypeInfo`).
2. Get byte-size of the element type we want to interpret the array as.
(e.g., sometimes we want to interpret an `unsigned char vec[16]`
as a `float32[]`).
3. `numChildren = containerSize / reinterpretedElementSize`
However, for step 1, clang will return us the *aligned* container
byte-size.
So for a type such as `float __attribute__((ext_vector_type(3)))`
(which is an array of 3 4-byte floats), clang will round up the
byte-width of the array to `16`.
(see
[here](https://github.com/llvm/llvm-project/blob/ab6a66dbec61654d0962f6abf6d6c5b776937584/clang/lib/AST/ASTContext.cpp#L1987-L1992))
This means that for vectors where the size isn't a power-of-2, LLDB
will miscalculate the number of elements.
**Solution**
This patch changes step 1 such that we calculate the container size
as `numElementsInSource * byteSizeOfElement`.
Added:
Modified:
lldb/source/DataFormatters/VectorType.cpp
lldb/test/API/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py
lldb/test/API/functionalities/data-formatter/vector-types/main.cpp
Removed:
################################################################################
diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp
index 4afcfa2e8e490e0..57dae0b2c71f0fa 100644
--- a/lldb/source/DataFormatters/VectorType.cpp
+++ b/lldb/source/DataFormatters/VectorType.cpp
@@ -169,21 +169,49 @@ static lldb::Format GetItemFormatForFormat(lldb::Format format,
}
}
-static size_t CalculateNumChildren(
- CompilerType container_type, CompilerType element_type,
- lldb_private::ExecutionContextScope *exe_scope =
- nullptr // does not matter here because all we trade in are basic types
- ) {
- std::optional<uint64_t> container_size =
- container_type.GetByteSize(exe_scope);
- std::optional<uint64_t> element_size = element_type.GetByteSize(exe_scope);
-
- if (container_size && element_size && *element_size) {
- if (*container_size % *element_size)
- return 0;
- return *container_size / *element_size;
- }
- return 0;
+/// Calculates the number of elements stored in a container (with
+/// element type 'container_elem_type') as if it had elements of type
+/// 'element_type'.
+///
+/// For example, a container of type
+/// `uint8_t __attribute__((vector_size(16)))` has 16 elements.
+/// But calling `CalculateNumChildren` with an 'element_type'
+/// of `float` (4-bytes) will return `4` because we are interpreting
+/// the byte-array as a `float32[]`.
+///
+/// \param[in] container_elem_type The type of the elements stored
+/// in the container we are calculating the children of.
+///
+/// \param[in] num_elements Number of 'container_elem_type's our
+/// container stores.
+///
+/// \param[in] element_type The type of elements we interpret
+/// container_type to contain for the purposes of calculating
+/// the number of children.
+///
+/// \returns The number of elements stored in a container of
+/// type 'element_type'. Returns a std::nullopt if the
+/// size of the container is not a multiple of 'element_type'
+/// or if an error occurs.
+static std::optional<size_t>
+CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements,
+ CompilerType element_type) {
+ std::optional<uint64_t> container_elem_size =
+ container_elem_type.GetByteSize(/* exe_scope */ nullptr);
+ if (!container_elem_size)
+ return {};
+
+ auto container_size = *container_elem_size * num_elements;
+
+ std::optional<uint64_t> element_size =
+ element_type.GetByteSize(/* exe_scope */ nullptr);
+ if (!element_size || !*element_size)
+ return {};
+
+ if (container_size % *element_size)
+ return {};
+
+ return container_size / *element_size;
}
namespace lldb_private {
@@ -221,11 +249,14 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
m_parent_format = m_backend.GetFormat();
CompilerType parent_type(m_backend.GetCompilerType());
CompilerType element_type;
- parent_type.IsVectorType(&element_type);
+ uint64_t num_elements;
+ parent_type.IsVectorType(&element_type, &num_elements);
m_child_type = ::GetCompilerTypeForFormat(
m_parent_format, element_type,
parent_type.GetTypeSystem().GetSharedPointer());
- m_num_children = ::CalculateNumChildren(parent_type, m_child_type);
+ m_num_children =
+ ::CalculateNumChildren(element_type, num_elements, m_child_type)
+ .value_or(0);
m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
return false;
}
diff --git a/lldb/test/API/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py b/lldb/test/API/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py
index 4103d62878c70f3..1839c28aeb29fc6 100644
--- a/lldb/test/API/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py
+++ b/lldb/test/API/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py
@@ -86,3 +86,10 @@ def cleanup():
v.SetFormat(lldb.eFormatVectorOfFloat32)
oldValueAgain = v.GetChildAtIndex(0).GetValue()
self.assertEqual(oldValue, oldValueAgain, "same format but
diff erent values")
+
+ # Test formatter for vector types whose size is not a power-of-2
+ f3 = self.frame().FindVariable("f3")
+ self.assertEqual(f3.GetNumChildren(), 3)
+ self.assertEqual(f3.GetChildAtIndex(0).GetData().float[0], 1.25)
+ self.assertEqual(f3.GetChildAtIndex(1).GetData().float[0], 2.50)
+ self.assertEqual(f3.GetChildAtIndex(2).GetData().float[0], 2.50)
diff --git a/lldb/test/API/functionalities/data-formatter/vector-types/main.cpp b/lldb/test/API/functionalities/data-formatter/vector-types/main.cpp
index ef0a227560bc253..7f2309e776bc27e 100644
--- a/lldb/test/API/functionalities/data-formatter/vector-types/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/vector-types/main.cpp
@@ -1,8 +1,10 @@
typedef float float4 __attribute__((ext_vector_type(4)));
-typedef unsigned char vec __attribute__((ext_vector_type(16)));
+typedef unsigned char vec __attribute__((ext_vector_type(16)));
+typedef float float3 __attribute__((ext_vector_type(3)));
int main() {
float4 f4 = {1.25, 1.25, 2.50, 2.50};
vec v = (vec)f4;
+ float3 f3 = f4.gba;
return 0; // break here
}
More information about the lldb-commits
mailing list