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