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 
GetCompilerTypeForFormat(lldb::Format format,CompilerType element_type,TypeSystem * type_system)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 
GetItemFormatForFormat(lldb::Format format,CompilerType element_type)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 
CalculateNumChildren(CompilerType container_type,CompilerType element_type,lldb_private::ExecutionContextScope * exe_scope=nullptr)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:
VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)191   VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
192       : SyntheticChildrenFrontEnd(*valobj_sp), m_parent_format(eFormatInvalid),
193         m_item_format(eFormatInvalid), m_child_type(), m_num_children(0) {}
194 
195   ~VectorTypeSyntheticFrontEnd() override = default;
196 
CalculateNumChildren()197   size_t CalculateNumChildren() override { return m_num_children; }
198 
GetChildAtIndex(size_t idx)199   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
200     if (idx >= CalculateNumChildren())
201       return {};
202     llvm::Optional<uint64_t> size = m_child_type.GetByteSize(nullptr);
203     if (!size)
204       return {};
205     auto offset = idx * *size;
206     StreamString idx_name;
207     idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
208     ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset(
209         offset, m_child_type, true, ConstString(idx_name.GetString())));
210     if (!child_sp)
211       return child_sp;
212 
213     child_sp->SetFormat(m_item_format);
214 
215     return child_sp;
216   }
217 
Update()218   bool Update() override {
219     m_parent_format = m_backend.GetFormat();
220     CompilerType parent_type(m_backend.GetCompilerType());
221     CompilerType element_type;
222     parent_type.IsVectorType(&element_type, nullptr);
223     m_child_type = ::GetCompilerTypeForFormat(m_parent_format, element_type,
224                                               parent_type.GetTypeSystem());
225     m_num_children = ::CalculateNumChildren(parent_type, m_child_type);
226     m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
227     return false;
228   }
229 
MightHaveChildren()230   bool MightHaveChildren() override { return true; }
231 
GetIndexOfChildWithName(ConstString name)232   size_t GetIndexOfChildWithName(ConstString name) override {
233     const char *item_name = name.GetCString();
234     uint32_t idx = ExtractIndexFromString(item_name);
235     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
236       return UINT32_MAX;
237     return idx;
238   }
239 
240 private:
241   lldb::Format m_parent_format;
242   lldb::Format m_item_format;
243   CompilerType m_child_type;
244   size_t m_num_children;
245 };
246 
247 } // namespace formatters
248 } // namespace lldb_private
249 
VectorTypeSummaryProvider(ValueObject & valobj,Stream & s,const TypeSummaryOptions &)250 bool lldb_private::formatters::VectorTypeSummaryProvider(
251     ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
252   auto synthetic_children =
253       VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP());
254   if (!synthetic_children)
255     return false;
256 
257   synthetic_children->Update();
258 
259   s.PutChar('(');
260   bool first = true;
261 
262   size_t idx = 0, len = synthetic_children->CalculateNumChildren();
263 
264   for (; idx < len; idx++) {
265     auto child_sp = synthetic_children->GetChildAtIndex(idx);
266     if (!child_sp)
267       continue;
268     child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
269         lldb::eDynamicDontRunTarget, true);
270 
271     const char *child_value = child_sp->GetValueAsCString();
272     if (child_value && *child_value) {
273       if (first) {
274         s.Printf("%s", child_value);
275         first = false;
276       } else {
277         s.Printf(", %s", child_value);
278       }
279     }
280   }
281 
282   s.PutChar(')');
283 
284   return true;
285 }
286 
287 lldb_private::SyntheticChildrenFrontEnd *
VectorTypeSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)288 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator(
289     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
290   if (!valobj_sp)
291     return nullptr;
292   return new VectorTypeSyntheticFrontEnd(valobj_sp);
293 }
294