1 //===-- VectorType.cpp ----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/DataFormatters/VectorType.h" 10 11 #include "lldb/DataFormatters/FormattersHelpers.h" 12 #include "lldb/Symbol/CompilerType.h" 13 #include "lldb/Symbol/TypeSystem.h" 14 #include "lldb/Target/Target.h" 15 #include "lldb/ValueObject/ValueObject.h" 16 #include "lldb/ValueObject/ValueObjectConstResult.h" 17 18 #include "lldb/Utility/LLDBAssert.h" 19 #include "lldb/Utility/Log.h" 20 #include <optional> 21 22 using namespace lldb; 23 using namespace lldb_private; 24 using namespace lldb_private::formatters; 25 26 static CompilerType GetCompilerTypeForFormat(lldb::Format format, 27 CompilerType element_type, 28 TypeSystemSP type_system) { 29 lldbassert(type_system && "type_system needs to be not NULL"); 30 if (!type_system) 31 return {}; 32 33 switch (format) { 34 case lldb::eFormatAddressInfo: 35 case lldb::eFormatPointer: 36 return type_system->GetBuiltinTypeForEncodingAndBitSize( 37 eEncodingUint, 8 * type_system->GetPointerByteSize()); 38 39 case lldb::eFormatBoolean: 40 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeBool); 41 42 case lldb::eFormatBytes: 43 case lldb::eFormatBytesWithASCII: 44 case lldb::eFormatChar: 45 case lldb::eFormatCharArray: 46 case lldb::eFormatCharPrintable: 47 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar); 48 49 case lldb::eFormatComplex /* lldb::eFormatComplexFloat */: 50 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloatComplex); 51 52 case lldb::eFormatCString: 53 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar) 54 .GetPointerType(); 55 56 case lldb::eFormatFloat: 57 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat); 58 59 case lldb::eFormatHex: 60 case lldb::eFormatHexUppercase: 61 case lldb::eFormatOctal: 62 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeInt); 63 64 case lldb::eFormatHexFloat: 65 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat); 66 67 case lldb::eFormatUnicode16: 68 case lldb::eFormatUnicode32: 69 70 case lldb::eFormatUnsigned: 71 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt); 72 73 case lldb::eFormatVectorOfChar: 74 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar); 75 76 case lldb::eFormatVectorOfFloat32: 77 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 78 32); 79 80 case lldb::eFormatVectorOfFloat64: 81 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 82 64); 83 84 case lldb::eFormatVectorOfSInt16: 85 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 16); 86 87 case lldb::eFormatVectorOfSInt32: 88 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32); 89 90 case lldb::eFormatVectorOfSInt64: 91 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64); 92 93 case lldb::eFormatVectorOfSInt8: 94 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 8); 95 96 case lldb::eFormatVectorOfUInt128: 97 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 128); 98 99 case lldb::eFormatVectorOfUInt16: 100 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16); 101 102 case lldb::eFormatVectorOfUInt32: 103 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 104 105 case lldb::eFormatVectorOfUInt64: 106 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64); 107 108 case lldb::eFormatVectorOfUInt8: 109 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8); 110 111 case lldb::eFormatDefault: 112 return element_type; 113 114 case lldb::eFormatBinary: 115 case lldb::eFormatComplexInteger: 116 case lldb::eFormatDecimal: 117 case lldb::eFormatEnum: 118 case lldb::eFormatInstruction: 119 case lldb::eFormatOSType: 120 case lldb::eFormatVoid: 121 default: 122 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8); 123 } 124 } 125 126 static lldb::Format GetItemFormatForFormat(lldb::Format format, 127 CompilerType element_type) { 128 switch (format) { 129 case lldb::eFormatVectorOfChar: 130 return lldb::eFormatChar; 131 132 case lldb::eFormatVectorOfFloat32: 133 case lldb::eFormatVectorOfFloat64: 134 return lldb::eFormatFloat; 135 136 case lldb::eFormatVectorOfSInt16: 137 case lldb::eFormatVectorOfSInt32: 138 case lldb::eFormatVectorOfSInt64: 139 case lldb::eFormatVectorOfSInt8: 140 return lldb::eFormatDecimal; 141 142 case lldb::eFormatVectorOfUInt128: 143 case lldb::eFormatVectorOfUInt16: 144 case lldb::eFormatVectorOfUInt32: 145 case lldb::eFormatVectorOfUInt64: 146 case lldb::eFormatVectorOfUInt8: 147 return lldb::eFormatUnsigned; 148 149 case lldb::eFormatBinary: 150 case lldb::eFormatComplexInteger: 151 case lldb::eFormatDecimal: 152 case lldb::eFormatEnum: 153 case lldb::eFormatInstruction: 154 case lldb::eFormatOSType: 155 case lldb::eFormatVoid: 156 return eFormatHex; 157 158 case lldb::eFormatDefault: { 159 // special case the (default, char) combination to actually display as an 160 // integer value most often, you won't want to see the ASCII characters... 161 // (and if you do, eFormatChar is a keystroke away) 162 bool is_char = element_type.IsCharType(); 163 bool is_signed = false; 164 element_type.IsIntegerType(is_signed); 165 return is_char ? (is_signed ? lldb::eFormatDecimal : eFormatHex) : format; 166 } break; 167 168 default: 169 return format; 170 } 171 } 172 173 /// Calculates the number of elements stored in a container (with 174 /// element type 'container_elem_type') as if it had elements of type 175 /// 'element_type'. 176 /// 177 /// For example, a container of type 178 /// `uint8_t __attribute__((vector_size(16)))` has 16 elements. 179 /// But calling `CalculateNumChildren` with an 'element_type' 180 /// of `float` (4-bytes) will return `4` because we are interpreting 181 /// the byte-array as a `float32[]`. 182 /// 183 /// \param[in] container_elem_type The type of the elements stored 184 /// in the container we are calculating the children of. 185 /// 186 /// \param[in] num_elements Number of 'container_elem_type's our 187 /// container stores. 188 /// 189 /// \param[in] element_type The type of elements we interpret 190 /// container_type to contain for the purposes of calculating 191 /// the number of children. 192 /// 193 /// \returns The number of elements stored in a container of 194 /// type 'element_type'. Returns a std::nullopt if the 195 /// size of the container is not a multiple of 'element_type' 196 /// or if an error occurs. 197 static std::optional<size_t> 198 CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements, 199 CompilerType element_type) { 200 std::optional<uint64_t> container_elem_size = 201 container_elem_type.GetByteSize(/* exe_scope */ nullptr); 202 if (!container_elem_size) 203 return {}; 204 205 auto container_size = *container_elem_size * num_elements; 206 207 std::optional<uint64_t> element_size = 208 element_type.GetByteSize(/* exe_scope */ nullptr); 209 if (!element_size || !*element_size) 210 return {}; 211 212 if (container_size % *element_size) 213 return {}; 214 215 return container_size / *element_size; 216 } 217 218 namespace lldb_private { 219 namespace formatters { 220 221 class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 222 public: 223 VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 224 : SyntheticChildrenFrontEnd(*valobj_sp), m_child_type() {} 225 226 ~VectorTypeSyntheticFrontEnd() override = default; 227 228 llvm::Expected<uint32_t> CalculateNumChildren() override { 229 return m_num_children; 230 } 231 232 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { 233 auto num_children_or_err = CalculateNumChildren(); 234 if (!num_children_or_err) 235 return ValueObjectConstResult::Create( 236 nullptr, Status::FromError(num_children_or_err.takeError())); 237 if (idx >= *num_children_or_err) 238 return {}; 239 std::optional<uint64_t> size = m_child_type.GetByteSize(nullptr); 240 if (!size) 241 return {}; 242 auto offset = idx * *size; 243 StreamString idx_name; 244 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 245 ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset( 246 offset, m_child_type, true, ConstString(idx_name.GetString()))); 247 if (!child_sp) 248 return child_sp; 249 250 child_sp->SetFormat(m_item_format); 251 252 return child_sp; 253 } 254 255 lldb::ChildCacheState Update() override { 256 m_parent_format = m_backend.GetFormat(); 257 CompilerType parent_type(m_backend.GetCompilerType()); 258 CompilerType element_type; 259 uint64_t num_elements; 260 parent_type.IsVectorType(&element_type, &num_elements); 261 m_child_type = ::GetCompilerTypeForFormat( 262 m_parent_format, element_type, 263 parent_type.GetTypeSystem().GetSharedPointer()); 264 m_num_children = 265 ::CalculateNumChildren(element_type, num_elements, m_child_type) 266 .value_or(0); 267 m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type); 268 return lldb::ChildCacheState::eRefetch; 269 } 270 271 bool MightHaveChildren() override { return true; } 272 273 size_t GetIndexOfChildWithName(ConstString name) override { 274 const char *item_name = name.GetCString(); 275 uint32_t idx = ExtractIndexFromString(item_name); 276 if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 277 return UINT32_MAX; 278 return idx; 279 } 280 281 private: 282 lldb::Format m_parent_format = eFormatInvalid; 283 lldb::Format m_item_format = eFormatInvalid; 284 CompilerType m_child_type; 285 size_t m_num_children = 0; 286 }; 287 288 } // namespace formatters 289 } // namespace lldb_private 290 291 bool lldb_private::formatters::VectorTypeSummaryProvider( 292 ValueObject &valobj, Stream &s, const TypeSummaryOptions &) { 293 auto synthetic_children = 294 VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP()); 295 if (!synthetic_children) 296 return false; 297 298 synthetic_children->Update(); 299 300 s.PutChar('('); 301 bool first = true; 302 303 size_t idx = 0, 304 len = synthetic_children->CalculateNumChildrenIgnoringErrors(); 305 306 for (; idx < len; idx++) { 307 auto child_sp = synthetic_children->GetChildAtIndex(idx); 308 if (!child_sp) 309 continue; 310 child_sp = child_sp->GetQualifiedRepresentationIfAvailable( 311 lldb::eDynamicDontRunTarget, true); 312 313 const char *child_value = child_sp->GetValueAsCString(); 314 if (child_value && *child_value) { 315 if (first) { 316 s.Printf("%s", child_value); 317 first = false; 318 } else { 319 s.Printf(", %s", child_value); 320 } 321 } 322 } 323 324 s.PutChar(')'); 325 326 return true; 327 } 328 329 lldb_private::SyntheticChildrenFrontEnd * 330 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator( 331 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 332 if (!valobj_sp) 333 return nullptr; 334 return new VectorTypeSyntheticFrontEnd(valobj_sp); 335 } 336