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