Skip to content

Commit ef32cc3

Browse files
committed
[lldb][DataFormatter] VectorType: fix format for arrays with size not a power-of-2 (llvm#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`. (cherry picked from commit 0dfcfb5)
1 parent 1511e98 commit ef32cc3

File tree

3 files changed

+58
-18
lines changed

3 files changed

+58
-18
lines changed

lldb/source/DataFormatters/VectorType.cpp

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -168,21 +168,49 @@ static lldb::Format GetItemFormatForFormat(lldb::Format format,
168168
}
169169
}
170170

171-
static size_t CalculateNumChildren(
172-
CompilerType container_type, CompilerType element_type,
173-
lldb_private::ExecutionContextScope *exe_scope =
174-
nullptr // does not matter here because all we trade in are basic types
175-
) {
176-
llvm::Optional<uint64_t> container_size =
177-
container_type.GetByteSize(exe_scope);
178-
llvm::Optional<uint64_t> element_size = element_type.GetByteSize(exe_scope);
179-
180-
if (container_size && element_size && *element_size) {
181-
if (*container_size % *element_size)
182-
return 0;
183-
return *container_size / *element_size;
184-
}
185-
return 0;
171+
/// Calculates the number of elements stored in a container (with
172+
/// element type 'container_elem_type') as if it had elements of type
173+
/// 'element_type'.
174+
///
175+
/// For example, a container of type
176+
/// `uint8_t __attribute__((vector_size(16)))` has 16 elements.
177+
/// But calling `CalculateNumChildren` with an 'element_type'
178+
/// of `float` (4-bytes) will return `4` because we are interpreting
179+
/// the byte-array as a `float32[]`.
180+
///
181+
/// \param[in] container_elem_type The type of the elements stored
182+
/// in the container we are calculating the children of.
183+
///
184+
/// \param[in] num_elements Number of 'container_elem_type's our
185+
/// container stores.
186+
///
187+
/// \param[in] element_type The type of elements we interpret
188+
/// container_type to contain for the purposes of calculating
189+
/// the number of children.
190+
///
191+
/// \returns The number of elements stored in a container of
192+
/// type 'element_type'. Returns a std::nullopt if the
193+
/// size of the container is not a multiple of 'element_type'
194+
/// or if an error occurs.
195+
static llvm::Optional<size_t>
196+
CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements,
197+
CompilerType element_type) {
198+
llvm::Optional<uint64_t> container_elem_size =
199+
container_elem_type.GetByteSize(/* exe_scope */ nullptr);
200+
if (!container_elem_size)
201+
return {};
202+
203+
auto container_size = *container_elem_size * num_elements;
204+
205+
llvm::Optional<uint64_t> element_size =
206+
element_type.GetByteSize(/* exe_scope */ nullptr);
207+
if (!element_size || !*element_size)
208+
return {};
209+
210+
if (container_size % *element_size)
211+
return {};
212+
213+
return container_size / *element_size;
186214
}
187215

188216
namespace lldb_private {
@@ -220,11 +248,14 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
220248
m_parent_format = m_backend.GetFormat();
221249
CompilerType parent_type(m_backend.GetCompilerType());
222250
CompilerType element_type;
223-
parent_type.IsVectorType(&element_type);
251+
uint64_t num_elements;
252+
parent_type.IsVectorType(&element_type, &num_elements);
224253
m_child_type = ::GetCompilerTypeForFormat(
225254
m_parent_format, element_type,
226255
parent_type.GetTypeSystem().GetSharedPointer());
227-
m_num_children = ::CalculateNumChildren(parent_type, m_child_type);
256+
m_num_children =
257+
::CalculateNumChildren(element_type, num_elements, m_child_type)
258+
.value_or(0);
228259
m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
229260
return false;
230261
}

lldb/test/API/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,10 @@ def cleanup():
8686
v.SetFormat(lldb.eFormatVectorOfFloat32)
8787
oldValueAgain = v.GetChildAtIndex(0).GetValue()
8888
self.assertEqual(oldValue, oldValueAgain, "same format but different values")
89+
90+
# Test formatter for vector types whose size is not a power-of-2
91+
f3 = self.frame().FindVariable("f3")
92+
self.assertEqual(f3.GetNumChildren(), 3)
93+
self.assertEqual(f3.GetChildAtIndex(0).GetData().float[0], 1.25)
94+
self.assertEqual(f3.GetChildAtIndex(1).GetData().float[0], 2.50)
95+
self.assertEqual(f3.GetChildAtIndex(2).GetData().float[0], 2.50)
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
typedef float float4 __attribute__((ext_vector_type(4)));
2-
typedef unsigned char vec __attribute__((ext_vector_type(16)));
2+
typedef unsigned char vec __attribute__((ext_vector_type(16)));
3+
typedef float float3 __attribute__((ext_vector_type(3)));
34

45
int main() {
56
float4 f4 = {1.25, 1.25, 2.50, 2.50};
67
vec v = (vec)f4;
8+
float3 f3 = f4.gba;
79
return 0; // break here
810
}

0 commit comments

Comments
 (0)