15ffd83dbSDimitry Andric //===-- VectorType.cpp ----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/DataFormatters/VectorType.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
120b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
130b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
140b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h"
150b57cec5SDimitry Andric #include "lldb/Target/Target.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
189dba64beSDimitry Andric #include "lldb/Utility/Log.h"
19bdd1243dSDimitry Andric #include <optional>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace lldb;
220b57cec5SDimitry Andric using namespace lldb_private;
230b57cec5SDimitry Andric using namespace lldb_private::formatters;
240b57cec5SDimitry Andric 
GetCompilerTypeForFormat(lldb::Format format,CompilerType element_type,TypeSystemSP type_system)250b57cec5SDimitry Andric static CompilerType GetCompilerTypeForFormat(lldb::Format format,
260b57cec5SDimitry Andric                                              CompilerType element_type,
27bdd1243dSDimitry Andric                                              TypeSystemSP type_system) {
280b57cec5SDimitry Andric   lldbassert(type_system && "type_system needs to be not NULL");
29bdd1243dSDimitry Andric   if (!type_system)
30bdd1243dSDimitry Andric     return {};
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   switch (format) {
330b57cec5SDimitry Andric   case lldb::eFormatAddressInfo:
340b57cec5SDimitry Andric   case lldb::eFormatPointer:
350b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(
360b57cec5SDimitry Andric         eEncodingUint, 8 * type_system->GetPointerByteSize());
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   case lldb::eFormatBoolean:
390b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeBool);
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   case lldb::eFormatBytes:
420b57cec5SDimitry Andric   case lldb::eFormatBytesWithASCII:
430b57cec5SDimitry Andric   case lldb::eFormatChar:
440b57cec5SDimitry Andric   case lldb::eFormatCharArray:
450b57cec5SDimitry Andric   case lldb::eFormatCharPrintable:
460b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar);
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   case lldb::eFormatComplex /* lldb::eFormatComplexFloat */:
490b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloatComplex);
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   case lldb::eFormatCString:
520b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar)
530b57cec5SDimitry Andric         .GetPointerType();
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   case lldb::eFormatFloat:
560b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   case lldb::eFormatHex:
590b57cec5SDimitry Andric   case lldb::eFormatHexUppercase:
600b57cec5SDimitry Andric   case lldb::eFormatOctal:
610b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeInt);
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   case lldb::eFormatHexFloat:
640b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   case lldb::eFormatUnicode16:
670b57cec5SDimitry Andric   case lldb::eFormatUnicode32:
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   case lldb::eFormatUnsigned:
700b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt);
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   case lldb::eFormatVectorOfChar:
730b57cec5SDimitry Andric     return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   case lldb::eFormatVectorOfFloat32:
760b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754,
770b57cec5SDimitry Andric                                                             32);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   case lldb::eFormatVectorOfFloat64:
800b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754,
810b57cec5SDimitry Andric                                                             64);
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt16:
840b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 16);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt32:
870b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32);
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt64:
900b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64);
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt8:
930b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 8);
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt128:
960b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 128);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt16:
990b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt32:
1020b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt64:
1050b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64);
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt8:
1080b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   case lldb::eFormatDefault:
1110b57cec5SDimitry Andric     return element_type;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   case lldb::eFormatBinary:
1140b57cec5SDimitry Andric   case lldb::eFormatComplexInteger:
1150b57cec5SDimitry Andric   case lldb::eFormatDecimal:
1160b57cec5SDimitry Andric   case lldb::eFormatEnum:
1170b57cec5SDimitry Andric   case lldb::eFormatInstruction:
1180b57cec5SDimitry Andric   case lldb::eFormatOSType:
1190b57cec5SDimitry Andric   case lldb::eFormatVoid:
1200b57cec5SDimitry Andric   default:
1210b57cec5SDimitry Andric     return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
GetItemFormatForFormat(lldb::Format format,CompilerType element_type)1250b57cec5SDimitry Andric static lldb::Format GetItemFormatForFormat(lldb::Format format,
1260b57cec5SDimitry Andric                                            CompilerType element_type) {
1270b57cec5SDimitry Andric   switch (format) {
1280b57cec5SDimitry Andric   case lldb::eFormatVectorOfChar:
1290b57cec5SDimitry Andric     return lldb::eFormatChar;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   case lldb::eFormatVectorOfFloat32:
1320b57cec5SDimitry Andric   case lldb::eFormatVectorOfFloat64:
1330b57cec5SDimitry Andric     return lldb::eFormatFloat;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt16:
1360b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt32:
1370b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt64:
1380b57cec5SDimitry Andric   case lldb::eFormatVectorOfSInt8:
1390b57cec5SDimitry Andric     return lldb::eFormatDecimal;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt128:
1420b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt16:
1430b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt32:
1440b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt64:
1450b57cec5SDimitry Andric   case lldb::eFormatVectorOfUInt8:
1460b57cec5SDimitry Andric     return lldb::eFormatUnsigned;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   case lldb::eFormatBinary:
1490b57cec5SDimitry Andric   case lldb::eFormatComplexInteger:
1500b57cec5SDimitry Andric   case lldb::eFormatDecimal:
1510b57cec5SDimitry Andric   case lldb::eFormatEnum:
1520b57cec5SDimitry Andric   case lldb::eFormatInstruction:
1530b57cec5SDimitry Andric   case lldb::eFormatOSType:
1540b57cec5SDimitry Andric   case lldb::eFormatVoid:
1550b57cec5SDimitry Andric     return eFormatHex;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   case lldb::eFormatDefault: {
1580b57cec5SDimitry Andric     // special case the (default, char) combination to actually display as an
1590b57cec5SDimitry Andric     // integer value most often, you won't want to see the ASCII characters...
1600b57cec5SDimitry Andric     // (and if you do, eFormatChar is a keystroke away)
1610b57cec5SDimitry Andric     bool is_char = element_type.IsCharType();
1620b57cec5SDimitry Andric     bool is_signed = false;
1630b57cec5SDimitry Andric     element_type.IsIntegerType(is_signed);
1640b57cec5SDimitry Andric     return is_char ? (is_signed ? lldb::eFormatDecimal : eFormatHex) : format;
1650b57cec5SDimitry Andric   } break;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   default:
1680b57cec5SDimitry Andric     return format;
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1725f757f3fSDimitry Andric /// Calculates the number of elements stored in a container (with
1735f757f3fSDimitry Andric /// element type 'container_elem_type') as if it had elements of type
1745f757f3fSDimitry Andric /// 'element_type'.
1755f757f3fSDimitry Andric ///
1765f757f3fSDimitry Andric /// For example, a container of type
1775f757f3fSDimitry Andric /// `uint8_t __attribute__((vector_size(16)))` has 16 elements.
1785f757f3fSDimitry Andric /// But calling `CalculateNumChildren` with an 'element_type'
1795f757f3fSDimitry Andric /// of `float` (4-bytes) will return `4` because we are interpreting
1805f757f3fSDimitry Andric /// the byte-array as a `float32[]`.
1815f757f3fSDimitry Andric ///
1825f757f3fSDimitry Andric /// \param[in] container_elem_type The type of the elements stored
1835f757f3fSDimitry Andric /// in the container we are calculating the children of.
1845f757f3fSDimitry Andric ///
1855f757f3fSDimitry Andric /// \param[in] num_elements Number of 'container_elem_type's our
1865f757f3fSDimitry Andric /// container stores.
1875f757f3fSDimitry Andric ///
1885f757f3fSDimitry Andric /// \param[in] element_type The type of elements we interpret
1895f757f3fSDimitry Andric /// container_type to contain for the purposes of calculating
1905f757f3fSDimitry Andric /// the number of children.
1915f757f3fSDimitry Andric ///
1925f757f3fSDimitry Andric /// \returns The number of elements stored in a container of
1935f757f3fSDimitry Andric /// type 'element_type'. Returns a std::nullopt if the
1945f757f3fSDimitry Andric /// size of the container is not a multiple of 'element_type'
1955f757f3fSDimitry Andric /// or if an error occurs.
1965f757f3fSDimitry Andric static std::optional<size_t>
CalculateNumChildren(CompilerType container_elem_type,uint64_t num_elements,CompilerType element_type)1975f757f3fSDimitry Andric CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements,
1985f757f3fSDimitry Andric                      CompilerType element_type) {
1995f757f3fSDimitry Andric   std::optional<uint64_t> container_elem_size =
2005f757f3fSDimitry Andric       container_elem_type.GetByteSize(/* exe_scope */ nullptr);
2015f757f3fSDimitry Andric   if (!container_elem_size)
2025f757f3fSDimitry Andric     return {};
2030b57cec5SDimitry Andric 
2045f757f3fSDimitry Andric   auto container_size = *container_elem_size * num_elements;
2055f757f3fSDimitry Andric 
2065f757f3fSDimitry Andric   std::optional<uint64_t> element_size =
2075f757f3fSDimitry Andric       element_type.GetByteSize(/* exe_scope */ nullptr);
2085f757f3fSDimitry Andric   if (!element_size || !*element_size)
2095f757f3fSDimitry Andric     return {};
2105f757f3fSDimitry Andric 
2115f757f3fSDimitry Andric   if (container_size % *element_size)
2125f757f3fSDimitry Andric     return {};
2135f757f3fSDimitry Andric 
2145f757f3fSDimitry Andric   return container_size / *element_size;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric namespace lldb_private {
2180b57cec5SDimitry Andric namespace formatters {
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
2210b57cec5SDimitry Andric public:
VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)2220b57cec5SDimitry Andric   VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
22381ad6265SDimitry Andric       : SyntheticChildrenFrontEnd(*valobj_sp), m_child_type() {}
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   ~VectorTypeSyntheticFrontEnd() override = default;
2260b57cec5SDimitry Andric 
CalculateNumChildren()2270b57cec5SDimitry Andric   size_t CalculateNumChildren() override { return m_num_children; }
2280b57cec5SDimitry Andric 
GetChildAtIndex(size_t idx)2290b57cec5SDimitry Andric   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
2300b57cec5SDimitry Andric     if (idx >= CalculateNumChildren())
2310b57cec5SDimitry Andric       return {};
232bdd1243dSDimitry Andric     std::optional<uint64_t> size = m_child_type.GetByteSize(nullptr);
2330b57cec5SDimitry Andric     if (!size)
2340b57cec5SDimitry Andric       return {};
2350b57cec5SDimitry Andric     auto offset = idx * *size;
2360b57cec5SDimitry Andric     StreamString idx_name;
2370b57cec5SDimitry Andric     idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
2380b57cec5SDimitry Andric     ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset(
2390b57cec5SDimitry Andric         offset, m_child_type, true, ConstString(idx_name.GetString())));
2400b57cec5SDimitry Andric     if (!child_sp)
2410b57cec5SDimitry Andric       return child_sp;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric     child_sp->SetFormat(m_item_format);
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric     return child_sp;
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric 
Update()2480b57cec5SDimitry Andric   bool Update() override {
2490b57cec5SDimitry Andric     m_parent_format = m_backend.GetFormat();
2500b57cec5SDimitry Andric     CompilerType parent_type(m_backend.GetCompilerType());
2510b57cec5SDimitry Andric     CompilerType element_type;
2525f757f3fSDimitry Andric     uint64_t num_elements;
2535f757f3fSDimitry Andric     parent_type.IsVectorType(&element_type, &num_elements);
254bdd1243dSDimitry Andric     m_child_type = ::GetCompilerTypeForFormat(
255bdd1243dSDimitry Andric         m_parent_format, element_type,
256bdd1243dSDimitry Andric         parent_type.GetTypeSystem().GetSharedPointer());
2575f757f3fSDimitry Andric     m_num_children =
2585f757f3fSDimitry Andric         ::CalculateNumChildren(element_type, num_elements, m_child_type)
2595f757f3fSDimitry Andric             .value_or(0);
2600b57cec5SDimitry Andric     m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
2610b57cec5SDimitry Andric     return false;
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
MightHaveChildren()2640b57cec5SDimitry Andric   bool MightHaveChildren() override { return true; }
2650b57cec5SDimitry Andric 
GetIndexOfChildWithName(ConstString name)2660b57cec5SDimitry Andric   size_t GetIndexOfChildWithName(ConstString name) override {
2670b57cec5SDimitry Andric     const char *item_name = name.GetCString();
2680b57cec5SDimitry Andric     uint32_t idx = ExtractIndexFromString(item_name);
2690b57cec5SDimitry Andric     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2700b57cec5SDimitry Andric       return UINT32_MAX;
2710b57cec5SDimitry Andric     return idx;
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric private:
27581ad6265SDimitry Andric   lldb::Format m_parent_format = eFormatInvalid;
27681ad6265SDimitry Andric   lldb::Format m_item_format = eFormatInvalid;
2770b57cec5SDimitry Andric   CompilerType m_child_type;
27881ad6265SDimitry Andric   size_t m_num_children = 0;
2790b57cec5SDimitry Andric };
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric } // namespace formatters
2820b57cec5SDimitry Andric } // namespace lldb_private
2830b57cec5SDimitry Andric 
VectorTypeSummaryProvider(ValueObject & valobj,Stream & s,const TypeSummaryOptions &)2840b57cec5SDimitry Andric bool lldb_private::formatters::VectorTypeSummaryProvider(
2850b57cec5SDimitry Andric     ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
2860b57cec5SDimitry Andric   auto synthetic_children =
2870b57cec5SDimitry Andric       VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP());
2880b57cec5SDimitry Andric   if (!synthetic_children)
2890b57cec5SDimitry Andric     return false;
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   synthetic_children->Update();
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   s.PutChar('(');
2940b57cec5SDimitry Andric   bool first = true;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   size_t idx = 0, len = synthetic_children->CalculateNumChildren();
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   for (; idx < len; idx++) {
2990b57cec5SDimitry Andric     auto child_sp = synthetic_children->GetChildAtIndex(idx);
3000b57cec5SDimitry Andric     if (!child_sp)
3010b57cec5SDimitry Andric       continue;
3020b57cec5SDimitry Andric     child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
3030b57cec5SDimitry Andric         lldb::eDynamicDontRunTarget, true);
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric     const char *child_value = child_sp->GetValueAsCString();
3060b57cec5SDimitry Andric     if (child_value && *child_value) {
3070b57cec5SDimitry Andric       if (first) {
3080b57cec5SDimitry Andric         s.Printf("%s", child_value);
3090b57cec5SDimitry Andric         first = false;
3100b57cec5SDimitry Andric       } else {
3110b57cec5SDimitry Andric         s.Printf(", %s", child_value);
3120b57cec5SDimitry Andric       }
3130b57cec5SDimitry Andric     }
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   s.PutChar(')');
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   return true;
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric lldb_private::SyntheticChildrenFrontEnd *
VectorTypeSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)3220b57cec5SDimitry Andric lldb_private::formatters::VectorTypeSyntheticFrontEndCreator(
3230b57cec5SDimitry Andric     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
3240b57cec5SDimitry Andric   if (!valobj_sp)
3250b57cec5SDimitry Andric     return nullptr;
3260b57cec5SDimitry Andric   return new VectorTypeSyntheticFrontEnd(valobj_sp);
3270b57cec5SDimitry Andric }
328