xref: /freebsd/contrib/llvm-project/lldb/source/API/SBTypeSummary.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- SBTypeSummary.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/API/SBTypeSummary.h"
10 #include "Utils.h"
11 #include "lldb/API/SBStream.h"
12 #include "lldb/API/SBValue.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 #include "lldb/Utility/Instrumentation.h"
15 
16 #include "llvm/Support/Casting.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
SBTypeSummaryOptions()21 SBTypeSummaryOptions::SBTypeSummaryOptions() {
22   LLDB_INSTRUMENT_VA(this);
23 
24   m_opaque_up = std::make_unique<TypeSummaryOptions>();
25 }
26 
SBTypeSummaryOptions(const lldb::SBTypeSummaryOptions & rhs)27 SBTypeSummaryOptions::SBTypeSummaryOptions(
28     const lldb::SBTypeSummaryOptions &rhs) {
29   LLDB_INSTRUMENT_VA(this, rhs);
30 
31   m_opaque_up = clone(rhs.m_opaque_up);
32 }
33 
34 SBTypeSummaryOptions::~SBTypeSummaryOptions() = default;
35 
IsValid()36 bool SBTypeSummaryOptions::IsValid() {
37   LLDB_INSTRUMENT_VA(this);
38   return this->operator bool();
39 }
operator bool() const40 SBTypeSummaryOptions::operator bool() const {
41   LLDB_INSTRUMENT_VA(this);
42 
43   return m_opaque_up.get();
44 }
45 
GetLanguage()46 lldb::LanguageType SBTypeSummaryOptions::GetLanguage() {
47   LLDB_INSTRUMENT_VA(this);
48 
49   if (IsValid())
50     return m_opaque_up->GetLanguage();
51   return lldb::eLanguageTypeUnknown;
52 }
53 
GetCapping()54 lldb::TypeSummaryCapping SBTypeSummaryOptions::GetCapping() {
55   LLDB_INSTRUMENT_VA(this);
56 
57   if (IsValid())
58     return m_opaque_up->GetCapping();
59   return eTypeSummaryCapped;
60 }
61 
SetLanguage(lldb::LanguageType l)62 void SBTypeSummaryOptions::SetLanguage(lldb::LanguageType l) {
63   LLDB_INSTRUMENT_VA(this, l);
64 
65   if (IsValid())
66     m_opaque_up->SetLanguage(l);
67 }
68 
SetCapping(lldb::TypeSummaryCapping c)69 void SBTypeSummaryOptions::SetCapping(lldb::TypeSummaryCapping c) {
70   LLDB_INSTRUMENT_VA(this, c);
71 
72   if (IsValid())
73     m_opaque_up->SetCapping(c);
74 }
75 
operator ->()76 lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::operator->() {
77   return m_opaque_up.get();
78 }
79 
80 const lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::
operator ->() const81 operator->() const {
82   return m_opaque_up.get();
83 }
84 
get()85 lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::get() {
86   return m_opaque_up.get();
87 }
88 
ref()89 lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() {
90   return *m_opaque_up;
91 }
92 
ref() const93 const lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() const {
94   return *m_opaque_up;
95 }
96 
SBTypeSummaryOptions(const lldb_private::TypeSummaryOptions & lldb_object)97 SBTypeSummaryOptions::SBTypeSummaryOptions(
98     const lldb_private::TypeSummaryOptions &lldb_object)
99     : m_opaque_up(std::make_unique<TypeSummaryOptions>(lldb_object)) {
100   LLDB_INSTRUMENT_VA(this, lldb_object);
101 }
102 
SBTypeSummary()103 SBTypeSummary::SBTypeSummary() { LLDB_INSTRUMENT_VA(this); }
104 
CreateWithSummaryString(const char * data,uint32_t options)105 SBTypeSummary SBTypeSummary::CreateWithSummaryString(const char *data,
106                                                      uint32_t options) {
107   LLDB_INSTRUMENT_VA(data, options);
108 
109   if (!data || data[0] == 0)
110     return SBTypeSummary();
111 
112   return SBTypeSummary(
113       TypeSummaryImplSP(new StringSummaryFormat(options, data)));
114 }
115 
CreateWithFunctionName(const char * data,uint32_t options)116 SBTypeSummary SBTypeSummary::CreateWithFunctionName(const char *data,
117                                                     uint32_t options) {
118   LLDB_INSTRUMENT_VA(data, options);
119 
120   if (!data || data[0] == 0)
121     return SBTypeSummary();
122 
123   return SBTypeSummary(
124       TypeSummaryImplSP(new ScriptSummaryFormat(options, data)));
125 }
126 
CreateWithScriptCode(const char * data,uint32_t options)127 SBTypeSummary SBTypeSummary::CreateWithScriptCode(const char *data,
128                                                   uint32_t options) {
129   LLDB_INSTRUMENT_VA(data, options);
130 
131   if (!data || data[0] == 0)
132     return SBTypeSummary();
133 
134   return SBTypeSummary(
135       TypeSummaryImplSP(new ScriptSummaryFormat(options, "", data)));
136 }
137 
CreateWithCallback(FormatCallback cb,uint32_t options,const char * description)138 SBTypeSummary SBTypeSummary::CreateWithCallback(FormatCallback cb,
139                                                 uint32_t options,
140                                                 const char *description) {
141   LLDB_INSTRUMENT_VA(cb, options, description);
142 
143   SBTypeSummary retval;
144   if (cb) {
145     retval.SetSP(TypeSummaryImplSP(new CXXFunctionSummaryFormat(
146         options,
147         [cb](ValueObject &valobj, Stream &stm,
148              const TypeSummaryOptions &opt) -> bool {
149           SBStream stream;
150           SBValue sb_value(valobj.GetSP());
151           SBTypeSummaryOptions options(opt);
152           if (!cb(sb_value, options, stream))
153             return false;
154           stm.Write(stream.GetData(), stream.GetSize());
155           return true;
156         },
157         description ? description : "callback summary formatter")));
158   }
159 
160   return retval;
161 }
162 
SBTypeSummary(const lldb::SBTypeSummary & rhs)163 SBTypeSummary::SBTypeSummary(const lldb::SBTypeSummary &rhs)
164     : m_opaque_sp(rhs.m_opaque_sp) {
165   LLDB_INSTRUMENT_VA(this, rhs);
166 }
167 
168 SBTypeSummary::~SBTypeSummary() = default;
169 
IsValid() const170 bool SBTypeSummary::IsValid() const {
171   LLDB_INSTRUMENT_VA(this);
172   return this->operator bool();
173 }
operator bool() const174 SBTypeSummary::operator bool() const {
175   LLDB_INSTRUMENT_VA(this);
176 
177   return m_opaque_sp.get() != nullptr;
178 }
179 
IsFunctionCode()180 bool SBTypeSummary::IsFunctionCode() {
181   LLDB_INSTRUMENT_VA(this);
182 
183   if (!IsValid())
184     return false;
185   if (ScriptSummaryFormat *script_summary_ptr =
186           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
187     const char *ftext = script_summary_ptr->GetPythonScript();
188     return (ftext && *ftext != 0);
189   }
190   return false;
191 }
192 
IsFunctionName()193 bool SBTypeSummary::IsFunctionName() {
194   LLDB_INSTRUMENT_VA(this);
195 
196   if (!IsValid())
197     return false;
198   if (ScriptSummaryFormat *script_summary_ptr =
199           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
200     const char *ftext = script_summary_ptr->GetPythonScript();
201     return (!ftext || *ftext == 0);
202   }
203   return false;
204 }
205 
IsSummaryString()206 bool SBTypeSummary::IsSummaryString() {
207   LLDB_INSTRUMENT_VA(this);
208 
209   if (!IsValid())
210     return false;
211 
212   return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString;
213 }
214 
GetData()215 const char *SBTypeSummary::GetData() {
216   LLDB_INSTRUMENT_VA(this);
217 
218   if (!IsValid())
219     return nullptr;
220   if (ScriptSummaryFormat *script_summary_ptr =
221           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
222     const char *fname = script_summary_ptr->GetFunctionName();
223     const char *ftext = script_summary_ptr->GetPythonScript();
224     if (ftext && *ftext)
225       return ConstString(ftext).GetCString();
226     return ConstString(fname).GetCString();
227   } else if (StringSummaryFormat *string_summary_ptr =
228                  llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
229     return ConstString(string_summary_ptr->GetSummaryString()).GetCString();
230   return nullptr;
231 }
232 
GetPtrMatchDepth()233 uint32_t SBTypeSummary::GetPtrMatchDepth() {
234   LLDB_INSTRUMENT_VA(this);
235 
236   if (!IsValid())
237     return 0;
238   return m_opaque_sp->GetPtrMatchDepth();
239 }
240 
SetPtrMatchDepth(uint32_t ptr_match_depth)241 void SBTypeSummary::SetPtrMatchDepth(uint32_t ptr_match_depth) {
242   LLDB_INSTRUMENT_VA(this);
243 
244   if (!IsValid())
245     return;
246   return m_opaque_sp->SetPtrMatchDepth(ptr_match_depth);
247 }
248 
GetOptions()249 uint32_t SBTypeSummary::GetOptions() {
250   LLDB_INSTRUMENT_VA(this);
251 
252   if (!IsValid())
253     return lldb::eTypeOptionNone;
254   return m_opaque_sp->GetOptions();
255 }
256 
SetOptions(uint32_t value)257 void SBTypeSummary::SetOptions(uint32_t value) {
258   LLDB_INSTRUMENT_VA(this, value);
259 
260   if (!CopyOnWrite_Impl())
261     return;
262   m_opaque_sp->SetOptions(value);
263 }
264 
SetSummaryString(const char * data)265 void SBTypeSummary::SetSummaryString(const char *data) {
266   LLDB_INSTRUMENT_VA(this, data);
267 
268   if (!IsValid())
269     return;
270   if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get()))
271     ChangeSummaryType(false);
272   if (StringSummaryFormat *string_summary_ptr =
273           llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
274     string_summary_ptr->SetSummaryString(data);
275 }
276 
SetFunctionName(const char * data)277 void SBTypeSummary::SetFunctionName(const char *data) {
278   LLDB_INSTRUMENT_VA(this, data);
279 
280   if (!IsValid())
281     return;
282   if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
283     ChangeSummaryType(true);
284   if (ScriptSummaryFormat *script_summary_ptr =
285           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
286     script_summary_ptr->SetFunctionName(data);
287 }
288 
SetFunctionCode(const char * data)289 void SBTypeSummary::SetFunctionCode(const char *data) {
290   LLDB_INSTRUMENT_VA(this, data);
291 
292   if (!IsValid())
293     return;
294   if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
295     ChangeSummaryType(true);
296   if (ScriptSummaryFormat *script_summary_ptr =
297           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
298     script_summary_ptr->SetPythonScript(data);
299 }
300 
GetDescription(lldb::SBStream & description,lldb::DescriptionLevel description_level)301 bool SBTypeSummary::GetDescription(lldb::SBStream &description,
302                                    lldb::DescriptionLevel description_level) {
303   LLDB_INSTRUMENT_VA(this, description, description_level);
304 
305   if (!CopyOnWrite_Impl())
306     return false;
307   else {
308     description.Printf("%s\n", m_opaque_sp->GetDescription().c_str());
309     return true;
310   }
311 }
312 
DoesPrintValue(lldb::SBValue value)313 bool SBTypeSummary::DoesPrintValue(lldb::SBValue value) {
314   LLDB_INSTRUMENT_VA(this, value);
315 
316   if (!IsValid())
317     return false;
318   lldb::ValueObjectSP value_sp = value.GetSP();
319   return m_opaque_sp->DoesPrintValue(value_sp.get());
320 }
321 
operator =(const lldb::SBTypeSummary & rhs)322 lldb::SBTypeSummary &SBTypeSummary::operator=(const lldb::SBTypeSummary &rhs) {
323   LLDB_INSTRUMENT_VA(this, rhs);
324 
325   if (this != &rhs) {
326     m_opaque_sp = rhs.m_opaque_sp;
327   }
328   return *this;
329 }
330 
operator ==(lldb::SBTypeSummary & rhs)331 bool SBTypeSummary::operator==(lldb::SBTypeSummary &rhs) {
332   LLDB_INSTRUMENT_VA(this, rhs);
333 
334   if (!IsValid())
335     return !rhs.IsValid();
336   return m_opaque_sp == rhs.m_opaque_sp;
337 }
338 
IsEqualTo(lldb::SBTypeSummary & rhs)339 bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) {
340   LLDB_INSTRUMENT_VA(this, rhs);
341 
342   if (IsValid()) {
343     // valid and invalid are different
344     if (!rhs.IsValid())
345       return false;
346   } else {
347     // invalid and valid are different
348     if (rhs.IsValid())
349       return false;
350     else
351       // both invalid are the same
352       return true;
353   }
354 
355   if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind())
356     return false;
357 
358   switch (m_opaque_sp->GetKind()) {
359   case TypeSummaryImpl::Kind::eCallback:
360     return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) ==
361            llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get());
362   case TypeSummaryImpl::Kind::eBytecode:
363   case TypeSummaryImpl::Kind::eScript:
364     if (IsFunctionCode() != rhs.IsFunctionCode())
365       return false;
366     if (IsFunctionName() != rhs.IsFunctionName())
367       return false;
368     return GetOptions() == rhs.GetOptions();
369   case TypeSummaryImpl::Kind::eSummaryString:
370     if (IsSummaryString() != rhs.IsSummaryString())
371       return false;
372     return GetOptions() == rhs.GetOptions();
373   case TypeSummaryImpl::Kind::eInternal:
374     return (m_opaque_sp.get() == rhs.m_opaque_sp.get());
375   }
376 
377   return false;
378 }
379 
operator !=(lldb::SBTypeSummary & rhs)380 bool SBTypeSummary::operator!=(lldb::SBTypeSummary &rhs) {
381   LLDB_INSTRUMENT_VA(this, rhs);
382 
383   if (!IsValid())
384     return !rhs.IsValid();
385   return m_opaque_sp != rhs.m_opaque_sp;
386 }
387 
GetSP()388 lldb::TypeSummaryImplSP SBTypeSummary::GetSP() { return m_opaque_sp; }
389 
SetSP(const lldb::TypeSummaryImplSP & typesummary_impl_sp)390 void SBTypeSummary::SetSP(const lldb::TypeSummaryImplSP &typesummary_impl_sp) {
391   m_opaque_sp = typesummary_impl_sp;
392 }
393 
SBTypeSummary(const lldb::TypeSummaryImplSP & typesummary_impl_sp)394 SBTypeSummary::SBTypeSummary(const lldb::TypeSummaryImplSP &typesummary_impl_sp)
395     : m_opaque_sp(typesummary_impl_sp) {}
396 
CopyOnWrite_Impl()397 bool SBTypeSummary::CopyOnWrite_Impl() {
398   if (!IsValid())
399     return false;
400 
401   if (m_opaque_sp.use_count() == 1)
402     return true;
403 
404   TypeSummaryImplSP new_sp;
405 
406   if (CXXFunctionSummaryFormat *current_summary_ptr =
407           llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get())) {
408     new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(
409         GetOptions(), current_summary_ptr->m_impl,
410         current_summary_ptr->m_description.c_str()));
411   } else if (ScriptSummaryFormat *current_summary_ptr =
412                  llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
413     new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(
414         GetOptions(), current_summary_ptr->GetFunctionName(),
415         current_summary_ptr->GetPythonScript()));
416   } else if (StringSummaryFormat *current_summary_ptr =
417                  llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get())) {
418     new_sp = TypeSummaryImplSP(new StringSummaryFormat(
419         GetOptions(), current_summary_ptr->GetSummaryString()));
420   }
421 
422   SetSP(new_sp);
423 
424   return nullptr != new_sp.get();
425 }
426 
ChangeSummaryType(bool want_script)427 bool SBTypeSummary::ChangeSummaryType(bool want_script) {
428   if (!IsValid())
429     return false;
430 
431   TypeSummaryImplSP new_sp;
432 
433   if (want_script ==
434       (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript)) {
435     if (m_opaque_sp->GetKind() ==
436             lldb_private::TypeSummaryImpl::Kind::eCallback &&
437         !want_script)
438       new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
439     else
440       return CopyOnWrite_Impl();
441   }
442 
443   if (!new_sp) {
444     if (want_script)
445       new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
446     else
447       new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
448   }
449 
450   SetSP(new_sp);
451 
452   return true;
453 }
454