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/Core/ValueObject.h" 12 #include "lldb/DataFormatters/FormattersHelpers.h" 13 #include "lldb/Symbol/CompilerType.h" 14 #include "lldb/Symbol/TypeSystem.h" 15 #include "lldb/Target/Target.h" 16 17 #include "lldb/Utility/LLDBAssert.h" 18 #include "lldb/Utility/Log.h" 19 #include <optional> 20 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace lldb_private::formatters; 24 25 static CompilerType GetCompilerTypeForFormat(lldb::Format format, 26 CompilerType element_type, 27 TypeSystemSP type_system) { 28 lldbassert(type_system && "type_system needs to be not NULL"); 29 if (!type_system) 30 return {}; 31 32 switch (format) { 33 case lldb::eFormatAddressInfo: 34 case lldb::eFormatPointer: 35 return type_system->GetBuiltinTypeForEncodingAndBitSize( 36 eEncodingUint, 8 * type_system->GetPointerByteSize()); 37 38 case lldb::eFormatBoolean: 39 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeBool); 40 41 case lldb::eFormatBytes: 42 case lldb::eFormatBytesWithASCII: 43 case lldb::eFormatChar: 44 case lldb::eFormatCharArray: 45 case lldb::eFormatCharPrintable: 46 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar); 47 48 case lldb::eFormatComplex /* lldb::eFormatComplexFloat */: 49 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloatComplex); 50 51 case lldb::eFormatCString: 52 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar) 53 .GetPointerType(); 54 55 case lldb::eFormatFloat: 56 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat); 57 58 case lldb::eFormatHex: 59 case lldb::eFormatHexUppercase: 60 case lldb::eFormatOctal: 61 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeInt); 62 63 case lldb::eFormatHexFloat: 64 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat); 65 66 case lldb::eFormatUnicode16: 67 case lldb::eFormatUnicode32: 68 69 case lldb::eFormatUnsigned: 70 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt); 71 72 case lldb::eFormatVectorOfChar: 73 return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar); 74 75 case lldb::eFormatVectorOfFloat32: 76 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 77 32); 78 79 case lldb::eFormatVectorOfFloat64: 80 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 81 64); 82 83 case lldb::eFormatVectorOfSInt16: 84 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 16); 85 86 case lldb::eFormatVectorOfSInt32: 87 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32); 88 89 case lldb::eFormatVectorOfSInt64: 90 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64); 91 92 case lldb::eFormatVectorOfSInt8: 93 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 8); 94 95 case lldb::eFormatVectorOfUInt128: 96 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 128); 97 98 case lldb::eFormatVectorOfUInt16: 99 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16); 100 101 case lldb::eFormatVectorOfUInt32: 102 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 103 104 case lldb::eFormatVectorOfUInt64: 105 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64); 106 107 case lldb::eFormatVectorOfUInt8: 108 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8); 109 110 case lldb::eFormatDefault: 111 return element_type; 112 113 case lldb::eFormatBinary: 114 case lldb::eFormatComplexInteger: 115 case lldb::eFormatDecimal: 116 case lldb::eFormatEnum: 117 case lldb::eFormatInstruction: 118 case lldb::eFormatOSType: 119 case lldb::eFormatVoid: 120 default: 121 return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8); 122 } 123 } 124 125 static lldb::Format GetItemFormatForFormat(lldb::Format format, 126 CompilerType element_type) { 127 switch (format) { 128 case lldb::eFormatVectorOfChar: 129 return lldb::eFormatChar; 130 131 case lldb::eFormatVectorOfFloat32: 132 case lldb::eFormatVectorOfFloat64: 133 return lldb::eFormatFloat; 134 135 case lldb::eFormatVectorOfSInt16: 136 case lldb::eFormatVectorOfSInt32: 137 case lldb::eFormatVectorOfSInt64: 138 case lldb::eFormatVectorOfSInt8: 139 return lldb::eFormatDecimal; 140 141 case lldb::eFormatVectorOfUInt128: 142 case lldb::eFormatVectorOfUInt16: 143 case lldb::eFormatVectorOfUInt32: 144 case lldb::eFormatVectorOfUInt64: 145 case lldb::eFormatVectorOfUInt8: 146 return lldb::eFormatUnsigned; 147 148 case lldb::eFormatBinary: 149 case lldb::eFormatComplexInteger: 150 case lldb::eFormatDecimal: 151 case lldb::eFormatEnum: 152 case lldb::eFormatInstruction: 153 case lldb::eFormatOSType: 154 case lldb::eFormatVoid: 155 return eFormatHex; 156 157 case lldb::eFormatDefault: { 158 // special case the (default, char) combination to actually display as an 159 // integer value most often, you won't want to see the ASCII characters... 160 // (and if you do, eFormatChar is a keystroke away) 161 bool is_char = element_type.IsCharType(); 162 bool is_signed = false; 163 element_type.IsIntegerType(is_signed); 164 return is_char ? (is_signed ? lldb::eFormatDecimal : eFormatHex) : format; 165 } break; 166 167 default: 168 return format; 169 } 170 } 171 172 static size_t CalculateNumChildren( 173 CompilerType container_type, CompilerType element_type, 174 lldb_private::ExecutionContextScope *exe_scope = 175 nullptr // does not matter here because all we trade in are basic types 176 ) { 177 std::optional<uint64_t> container_size = 178 container_type.GetByteSize(exe_scope); 179 std::optional<uint64_t> element_size = element_type.GetByteSize(exe_scope); 180 181 if (container_size && element_size && *element_size) { 182 if (*container_size % *element_size) 183 return 0; 184 return *container_size / *element_size; 185 } 186 return 0; 187 } 188 189 namespace lldb_private { 190 namespace formatters { 191 192 class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 193 public: 194 VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 195 : SyntheticChildrenFrontEnd(*valobj_sp), m_child_type() {} 196 197 ~VectorTypeSyntheticFrontEnd() override = default; 198 199 size_t CalculateNumChildren() override { return m_num_children; } 200 201 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { 202 if (idx >= CalculateNumChildren()) 203 return {}; 204 std::optional<uint64_t> size = m_child_type.GetByteSize(nullptr); 205 if (!size) 206 return {}; 207 auto offset = idx * *size; 208 StreamString idx_name; 209 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 210 ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset( 211 offset, m_child_type, true, ConstString(idx_name.GetString()))); 212 if (!child_sp) 213 return child_sp; 214 215 child_sp->SetFormat(m_item_format); 216 217 return child_sp; 218 } 219 220 bool Update() override { 221 m_parent_format = m_backend.GetFormat(); 222 CompilerType parent_type(m_backend.GetCompilerType()); 223 CompilerType element_type; 224 parent_type.IsVectorType(&element_type); 225 m_child_type = ::GetCompilerTypeForFormat( 226 m_parent_format, element_type, 227 parent_type.GetTypeSystem().GetSharedPointer()); 228 m_num_children = ::CalculateNumChildren(parent_type, m_child_type); 229 m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type); 230 return false; 231 } 232 233 bool MightHaveChildren() override { return true; } 234 235 size_t GetIndexOfChildWithName(ConstString name) override { 236 const char *item_name = name.GetCString(); 237 uint32_t idx = ExtractIndexFromString(item_name); 238 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 239 return UINT32_MAX; 240 return idx; 241 } 242 243 private: 244 lldb::Format m_parent_format = eFormatInvalid; 245 lldb::Format m_item_format = eFormatInvalid; 246 CompilerType m_child_type; 247 size_t m_num_children = 0; 248 }; 249 250 } // namespace formatters 251 } // namespace lldb_private 252 253 bool lldb_private::formatters::VectorTypeSummaryProvider( 254 ValueObject &valobj, Stream &s, const TypeSummaryOptions &) { 255 auto synthetic_children = 256 VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP()); 257 if (!synthetic_children) 258 return false; 259 260 synthetic_children->Update(); 261 262 s.PutChar('('); 263 bool first = true; 264 265 size_t idx = 0, len = synthetic_children->CalculateNumChildren(); 266 267 for (; idx < len; idx++) { 268 auto child_sp = synthetic_children->GetChildAtIndex(idx); 269 if (!child_sp) 270 continue; 271 child_sp = child_sp->GetQualifiedRepresentationIfAvailable( 272 lldb::eDynamicDontRunTarget, true); 273 274 const char *child_value = child_sp->GetValueAsCString(); 275 if (child_value && *child_value) { 276 if (first) { 277 s.Printf("%s", child_value); 278 first = false; 279 } else { 280 s.Printf(", %s", child_value); 281 } 282 } 283 } 284 285 s.PutChar(')'); 286 287 return true; 288 } 289 290 lldb_private::SyntheticChildrenFrontEnd * 291 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator( 292 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 293 if (!valobj_sp) 294 return nullptr; 295 return new VectorTypeSyntheticFrontEnd(valobj_sp); 296 } 297