VectorType.cpp revision 360784
1//===-- VectorType.cpp ------------------------------------------*- C++ -*-===//
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
20using namespace lldb;
21using namespace lldb_private;
22using namespace lldb_private::formatters;
23
24static 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
122static 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
169static 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
186namespace lldb_private {
187namespace formatters {
188
189class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
190public:
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
197  size_t CalculateNumChildren() override { return m_num_children; }
198
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
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    TypeSystem *type_system = nullptr;
224    if (auto target_sp = m_backend.GetTargetSP()) {
225      auto type_system_or_err =
226          target_sp->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC);
227      if (auto err = type_system_or_err.takeError()) {
228        LLDB_LOG_ERROR(
229            lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS),
230            std::move(err), "Unable to update from scratch TypeSystem");
231      } else {
232        type_system = &type_system_or_err.get();
233      }
234    }
235    m_child_type =
236        ::GetCompilerTypeForFormat(m_parent_format, element_type, type_system);
237    m_num_children = ::CalculateNumChildren(parent_type, m_child_type);
238    m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
239    return false;
240  }
241
242  bool MightHaveChildren() override { return true; }
243
244  size_t GetIndexOfChildWithName(ConstString name) override {
245    const char *item_name = name.GetCString();
246    uint32_t idx = ExtractIndexFromString(item_name);
247    if (idx < UINT32_MAX && idx >= CalculateNumChildren())
248      return UINT32_MAX;
249    return idx;
250  }
251
252private:
253  lldb::Format m_parent_format;
254  lldb::Format m_item_format;
255  CompilerType m_child_type;
256  size_t m_num_children;
257};
258
259} // namespace formatters
260} // namespace lldb_private
261
262bool lldb_private::formatters::VectorTypeSummaryProvider(
263    ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
264  auto synthetic_children =
265      VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP());
266  if (!synthetic_children)
267    return false;
268
269  synthetic_children->Update();
270
271  s.PutChar('(');
272  bool first = true;
273
274  size_t idx = 0, len = synthetic_children->CalculateNumChildren();
275
276  for (; idx < len; idx++) {
277    auto child_sp = synthetic_children->GetChildAtIndex(idx);
278    if (!child_sp)
279      continue;
280    child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
281        lldb::eDynamicDontRunTarget, true);
282
283    const char *child_value = child_sp->GetValueAsCString();
284    if (child_value && *child_value) {
285      if (first) {
286        s.Printf("%s", child_value);
287        first = false;
288      } else {
289        s.Printf(", %s", child_value);
290      }
291    }
292  }
293
294  s.PutChar(')');
295
296  return true;
297}
298
299lldb_private::SyntheticChildrenFrontEnd *
300lldb_private::formatters::VectorTypeSyntheticFrontEndCreator(
301    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
302  if (!valobj_sp)
303    return nullptr;
304  return new VectorTypeSyntheticFrontEnd(valobj_sp);
305}
306