1 //===-- SBTypeSummary.cpp -----------------------------------------*- C++
2 //-*-===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/API/SBTypeSummary.h"
11 #include "SBReproducerPrivate.h"
12 #include "Utils.h"
13 #include "lldb/API/SBStream.h"
14 #include "lldb/API/SBValue.h"
15 #include "lldb/DataFormatters/DataVisualization.h"
16 
17 #include "llvm/Support/Casting.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 SBTypeSummaryOptions::SBTypeSummaryOptions() {
23   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTypeSummaryOptions);
24 
25   m_opaque_up.reset(new TypeSummaryOptions());
26 }
27 
28 SBTypeSummaryOptions::SBTypeSummaryOptions(
29     const lldb::SBTypeSummaryOptions &rhs) {
30   LLDB_RECORD_CONSTRUCTOR(SBTypeSummaryOptions,
31                           (const lldb::SBTypeSummaryOptions &), rhs);
32 
33   m_opaque_up = clone(rhs.m_opaque_up);
34 }
35 
36 SBTypeSummaryOptions::~SBTypeSummaryOptions() {}
37 
38 bool SBTypeSummaryOptions::IsValid() {
39   LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummaryOptions, IsValid);
40   return this->operator bool();
41 }
42 SBTypeSummaryOptions::operator bool() const {
43   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummaryOptions, operator bool);
44 
45   return m_opaque_up.get();
46 }
47 
48 lldb::LanguageType SBTypeSummaryOptions::GetLanguage() {
49   LLDB_RECORD_METHOD_NO_ARGS(lldb::LanguageType, SBTypeSummaryOptions,
50                              GetLanguage);
51 
52   if (IsValid())
53     return m_opaque_up->GetLanguage();
54   return lldb::eLanguageTypeUnknown;
55 }
56 
57 lldb::TypeSummaryCapping SBTypeSummaryOptions::GetCapping() {
58   LLDB_RECORD_METHOD_NO_ARGS(lldb::TypeSummaryCapping, SBTypeSummaryOptions,
59                              GetCapping);
60 
61   if (IsValid())
62     return m_opaque_up->GetCapping();
63   return eTypeSummaryCapped;
64 }
65 
66 void SBTypeSummaryOptions::SetLanguage(lldb::LanguageType l) {
67   LLDB_RECORD_METHOD(void, SBTypeSummaryOptions, SetLanguage,
68                      (lldb::LanguageType), l);
69 
70   if (IsValid())
71     m_opaque_up->SetLanguage(l);
72 }
73 
74 void SBTypeSummaryOptions::SetCapping(lldb::TypeSummaryCapping c) {
75   LLDB_RECORD_METHOD(void, SBTypeSummaryOptions, SetCapping,
76                      (lldb::TypeSummaryCapping), c);
77 
78   if (IsValid())
79     m_opaque_up->SetCapping(c);
80 }
81 
82 lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::operator->() {
83   return m_opaque_up.get();
84 }
85 
86 const lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::
87 operator->() const {
88   return m_opaque_up.get();
89 }
90 
91 lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::get() {
92   return m_opaque_up.get();
93 }
94 
95 lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() {
96   return *m_opaque_up;
97 }
98 
99 const lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() const {
100   return *m_opaque_up;
101 }
102 
103 SBTypeSummaryOptions::SBTypeSummaryOptions(
104     const lldb_private::TypeSummaryOptions *lldb_object_ptr) {
105   LLDB_RECORD_CONSTRUCTOR(SBTypeSummaryOptions,
106                           (const lldb_private::TypeSummaryOptions *),
107                           lldb_object_ptr);
108 
109   SetOptions(lldb_object_ptr);
110 }
111 
112 void SBTypeSummaryOptions::SetOptions(
113     const lldb_private::TypeSummaryOptions *lldb_object_ptr) {
114   if (lldb_object_ptr)
115     m_opaque_up.reset(new TypeSummaryOptions(*lldb_object_ptr));
116   else
117     m_opaque_up.reset(new TypeSummaryOptions());
118 }
119 
120 SBTypeSummary::SBTypeSummary() : m_opaque_sp() {
121   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTypeSummary);
122 }
123 
124 SBTypeSummary SBTypeSummary::CreateWithSummaryString(const char *data,
125                                                      uint32_t options) {
126   LLDB_RECORD_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary,
127                             CreateWithSummaryString, (const char *, uint32_t),
128                             data, options);
129 
130   if (!data || data[0] == 0)
131     return LLDB_RECORD_RESULT(SBTypeSummary());
132 
133   return LLDB_RECORD_RESULT(
134       SBTypeSummary(TypeSummaryImplSP(new StringSummaryFormat(options, data))));
135 }
136 
137 SBTypeSummary SBTypeSummary::CreateWithFunctionName(const char *data,
138                                                     uint32_t options) {
139   LLDB_RECORD_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary,
140                             CreateWithFunctionName, (const char *, uint32_t),
141                             data, options);
142 
143   if (!data || data[0] == 0)
144     return LLDB_RECORD_RESULT(SBTypeSummary());
145 
146   return LLDB_RECORD_RESULT(
147       SBTypeSummary(TypeSummaryImplSP(new ScriptSummaryFormat(options, data))));
148 }
149 
150 SBTypeSummary SBTypeSummary::CreateWithScriptCode(const char *data,
151                                                   uint32_t options) {
152   LLDB_RECORD_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary,
153                             CreateWithScriptCode, (const char *, uint32_t),
154                             data, options);
155 
156   if (!data || data[0] == 0)
157     return LLDB_RECORD_RESULT(SBTypeSummary());
158 
159   return LLDB_RECORD_RESULT(SBTypeSummary(
160       TypeSummaryImplSP(new ScriptSummaryFormat(options, "", data))));
161 }
162 
163 SBTypeSummary SBTypeSummary::CreateWithCallback(FormatCallback cb,
164                                                 uint32_t options,
165                                                 const char *description) {
166   LLDB_RECORD_DUMMY(
167       lldb::SBTypeSummary, SBTypeSummary, CreateWithCallback,
168       (lldb::SBTypeSummary::FormatCallback, uint32_t, const char *), cb,
169       options, description);
170 
171   SBTypeSummary retval;
172   if (cb) {
173     retval.SetSP(TypeSummaryImplSP(new CXXFunctionSummaryFormat(
174         options,
175         [cb](ValueObject &valobj, Stream &stm,
176              const TypeSummaryOptions &opt) -> bool {
177           SBStream stream;
178           SBValue sb_value(valobj.GetSP());
179           SBTypeSummaryOptions options(&opt);
180           if (!cb(sb_value, options, stream))
181             return false;
182           stm.Write(stream.GetData(), stream.GetSize());
183           return true;
184         },
185         description ? description : "callback summary formatter")));
186   }
187 
188   return retval;
189 }
190 
191 SBTypeSummary::SBTypeSummary(const lldb::SBTypeSummary &rhs)
192     : m_opaque_sp(rhs.m_opaque_sp) {
193   LLDB_RECORD_CONSTRUCTOR(SBTypeSummary, (const lldb::SBTypeSummary &), rhs);
194 }
195 
196 SBTypeSummary::~SBTypeSummary() {}
197 
198 bool SBTypeSummary::IsValid() const {
199   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummary, IsValid);
200   return this->operator bool();
201 }
202 SBTypeSummary::operator bool() const {
203   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummary, operator bool);
204 
205   return m_opaque_sp.get() != nullptr;
206 }
207 
208 bool SBTypeSummary::IsFunctionCode() {
209   LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsFunctionCode);
210 
211   if (!IsValid())
212     return false;
213   if (ScriptSummaryFormat *script_summary_ptr =
214           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
215     const char *ftext = script_summary_ptr->GetPythonScript();
216     return (ftext && *ftext != 0);
217   }
218   return false;
219 }
220 
221 bool SBTypeSummary::IsFunctionName() {
222   LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsFunctionName);
223 
224   if (!IsValid())
225     return false;
226   if (ScriptSummaryFormat *script_summary_ptr =
227           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
228     const char *ftext = script_summary_ptr->GetPythonScript();
229     return (!ftext || *ftext == 0);
230   }
231   return false;
232 }
233 
234 bool SBTypeSummary::IsSummaryString() {
235   LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsSummaryString);
236 
237   if (!IsValid())
238     return false;
239 
240   return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString;
241 }
242 
243 const char *SBTypeSummary::GetData() {
244   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeSummary, GetData);
245 
246   if (!IsValid())
247     return nullptr;
248   if (ScriptSummaryFormat *script_summary_ptr =
249           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
250     const char *fname = script_summary_ptr->GetFunctionName();
251     const char *ftext = script_summary_ptr->GetPythonScript();
252     if (ftext && *ftext)
253       return ftext;
254     return fname;
255   } else if (StringSummaryFormat *string_summary_ptr =
256                  llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
257     return string_summary_ptr->GetSummaryString();
258   return nullptr;
259 }
260 
261 uint32_t SBTypeSummary::GetOptions() {
262   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBTypeSummary, GetOptions);
263 
264   if (!IsValid())
265     return lldb::eTypeOptionNone;
266   return m_opaque_sp->GetOptions();
267 }
268 
269 void SBTypeSummary::SetOptions(uint32_t value) {
270   LLDB_RECORD_METHOD(void, SBTypeSummary, SetOptions, (uint32_t), value);
271 
272   if (!CopyOnWrite_Impl())
273     return;
274   m_opaque_sp->SetOptions(value);
275 }
276 
277 void SBTypeSummary::SetSummaryString(const char *data) {
278   LLDB_RECORD_METHOD(void, SBTypeSummary, SetSummaryString, (const char *),
279                      data);
280 
281   if (!IsValid())
282     return;
283   if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get()))
284     ChangeSummaryType(false);
285   if (StringSummaryFormat *string_summary_ptr =
286           llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
287     string_summary_ptr->SetSummaryString(data);
288 }
289 
290 void SBTypeSummary::SetFunctionName(const char *data) {
291   LLDB_RECORD_METHOD(void, SBTypeSummary, SetFunctionName, (const char *),
292                      data);
293 
294   if (!IsValid())
295     return;
296   if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
297     ChangeSummaryType(true);
298   if (ScriptSummaryFormat *script_summary_ptr =
299           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
300     script_summary_ptr->SetFunctionName(data);
301 }
302 
303 void SBTypeSummary::SetFunctionCode(const char *data) {
304   LLDB_RECORD_METHOD(void, SBTypeSummary, SetFunctionCode, (const char *),
305                      data);
306 
307   if (!IsValid())
308     return;
309   if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
310     ChangeSummaryType(true);
311   if (ScriptSummaryFormat *script_summary_ptr =
312           llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
313     script_summary_ptr->SetPythonScript(data);
314 }
315 
316 bool SBTypeSummary::GetDescription(lldb::SBStream &description,
317                                    lldb::DescriptionLevel description_level) {
318   LLDB_RECORD_METHOD(bool, SBTypeSummary, GetDescription,
319                      (lldb::SBStream &, lldb::DescriptionLevel), description,
320                      description_level);
321 
322   if (!CopyOnWrite_Impl())
323     return false;
324   else {
325     description.Printf("%s\n", m_opaque_sp->GetDescription().c_str());
326     return true;
327   }
328 }
329 
330 bool SBTypeSummary::DoesPrintValue(lldb::SBValue value) {
331   LLDB_RECORD_METHOD(bool, SBTypeSummary, DoesPrintValue, (lldb::SBValue),
332                      value);
333 
334   if (!IsValid())
335     return false;
336   lldb::ValueObjectSP value_sp = value.GetSP();
337   return m_opaque_sp->DoesPrintValue(value_sp.get());
338 }
339 
340 lldb::SBTypeSummary &SBTypeSummary::operator=(const lldb::SBTypeSummary &rhs) {
341   LLDB_RECORD_METHOD(lldb::SBTypeSummary &,
342                      SBTypeSummary, operator=,(const lldb::SBTypeSummary &),
343                      rhs);
344 
345   if (this != &rhs) {
346     m_opaque_sp = rhs.m_opaque_sp;
347   }
348   return LLDB_RECORD_RESULT(*this);
349 }
350 
351 bool SBTypeSummary::operator==(lldb::SBTypeSummary &rhs) {
352   LLDB_RECORD_METHOD(bool, SBTypeSummary, operator==,(lldb::SBTypeSummary &),
353                      rhs);
354 
355   if (!IsValid())
356     return !rhs.IsValid();
357   return m_opaque_sp == rhs.m_opaque_sp;
358 }
359 
360 bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) {
361   LLDB_RECORD_METHOD(bool, SBTypeSummary, IsEqualTo, (lldb::SBTypeSummary &),
362                      rhs);
363 
364   if (IsValid()) {
365     // valid and invalid are different
366     if (!rhs.IsValid())
367       return false;
368   } else {
369     // invalid and valid are different
370     if (rhs.IsValid())
371       return false;
372     else
373       // both invalid are the same
374       return true;
375   }
376 
377   if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind())
378     return false;
379 
380   switch (m_opaque_sp->GetKind()) {
381   case TypeSummaryImpl::Kind::eCallback:
382     return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) ==
383            llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get());
384   case TypeSummaryImpl::Kind::eScript:
385     if (IsFunctionCode() != rhs.IsFunctionCode())
386       return false;
387     if (IsFunctionName() != rhs.IsFunctionName())
388       return false;
389     return GetOptions() == rhs.GetOptions();
390   case TypeSummaryImpl::Kind::eSummaryString:
391     if (IsSummaryString() != rhs.IsSummaryString())
392       return false;
393     return GetOptions() == rhs.GetOptions();
394   case TypeSummaryImpl::Kind::eInternal:
395     return (m_opaque_sp.get() == rhs.m_opaque_sp.get());
396   }
397 
398   return false;
399 }
400 
401 bool SBTypeSummary::operator!=(lldb::SBTypeSummary &rhs) {
402   LLDB_RECORD_METHOD(bool, SBTypeSummary, operator!=,(lldb::SBTypeSummary &),
403                      rhs);
404 
405   if (!IsValid())
406     return !rhs.IsValid();
407   return m_opaque_sp != rhs.m_opaque_sp;
408 }
409 
410 lldb::TypeSummaryImplSP SBTypeSummary::GetSP() { return m_opaque_sp; }
411 
412 void SBTypeSummary::SetSP(const lldb::TypeSummaryImplSP &typesummary_impl_sp) {
413   m_opaque_sp = typesummary_impl_sp;
414 }
415 
416 SBTypeSummary::SBTypeSummary(const lldb::TypeSummaryImplSP &typesummary_impl_sp)
417     : m_opaque_sp(typesummary_impl_sp) {}
418 
419 bool SBTypeSummary::CopyOnWrite_Impl() {
420   if (!IsValid())
421     return false;
422 
423   if (m_opaque_sp.unique())
424     return true;
425 
426   TypeSummaryImplSP new_sp;
427 
428   if (CXXFunctionSummaryFormat *current_summary_ptr =
429           llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get())) {
430     new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(
431         GetOptions(), current_summary_ptr->m_impl,
432         current_summary_ptr->m_description.c_str()));
433   } else if (ScriptSummaryFormat *current_summary_ptr =
434                  llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
435     new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(
436         GetOptions(), current_summary_ptr->GetFunctionName(),
437         current_summary_ptr->GetPythonScript()));
438   } else if (StringSummaryFormat *current_summary_ptr =
439                  llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get())) {
440     new_sp = TypeSummaryImplSP(new StringSummaryFormat(
441         GetOptions(), current_summary_ptr->GetSummaryString()));
442   }
443 
444   SetSP(new_sp);
445 
446   return nullptr != new_sp.get();
447 }
448 
449 bool SBTypeSummary::ChangeSummaryType(bool want_script) {
450   if (!IsValid())
451     return false;
452 
453   TypeSummaryImplSP new_sp;
454 
455   if (want_script ==
456       (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript)) {
457     if (m_opaque_sp->GetKind() ==
458             lldb_private::TypeSummaryImpl::Kind::eCallback &&
459         !want_script)
460       new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
461     else
462       return CopyOnWrite_Impl();
463   }
464 
465   if (!new_sp) {
466     if (want_script)
467       new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
468     else
469       new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
470   }
471 
472   SetSP(new_sp);
473 
474   return true;
475 }
476 
477 namespace lldb_private {
478 namespace repro {
479 
480 template <>
481 void RegisterMethods<SBTypeSummaryOptions>(Registry &R) {
482   LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions, ());
483   LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions,
484                             (const lldb::SBTypeSummaryOptions &));
485   LLDB_REGISTER_METHOD(bool, SBTypeSummaryOptions, IsValid, ());
486   LLDB_REGISTER_METHOD_CONST(bool, SBTypeSummaryOptions, operator bool, ());
487   LLDB_REGISTER_METHOD(lldb::LanguageType, SBTypeSummaryOptions, GetLanguage,
488                        ());
489   LLDB_REGISTER_METHOD(lldb::TypeSummaryCapping, SBTypeSummaryOptions,
490                        GetCapping, ());
491   LLDB_REGISTER_METHOD(void, SBTypeSummaryOptions, SetLanguage,
492                        (lldb::LanguageType));
493   LLDB_REGISTER_METHOD(void, SBTypeSummaryOptions, SetCapping,
494                        (lldb::TypeSummaryCapping));
495   LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions,
496                             (const lldb_private::TypeSummaryOptions *));
497 }
498 
499 template <>
500 void RegisterMethods<SBTypeSummary>(Registry &R) {
501   LLDB_REGISTER_CONSTRUCTOR(SBTypeSummary, ());
502   LLDB_REGISTER_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary,
503                               CreateWithSummaryString,
504                               (const char *, uint32_t));
505   LLDB_REGISTER_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary,
506                               CreateWithFunctionName,
507                               (const char *, uint32_t));
508   LLDB_REGISTER_STATIC_METHOD(lldb::SBTypeSummary, SBTypeSummary,
509                               CreateWithScriptCode, (const char *, uint32_t));
510   LLDB_REGISTER_CONSTRUCTOR(SBTypeSummary, (const lldb::SBTypeSummary &));
511   LLDB_REGISTER_METHOD_CONST(bool, SBTypeSummary, IsValid, ());
512   LLDB_REGISTER_METHOD_CONST(bool, SBTypeSummary, operator bool, ());
513   LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsFunctionCode, ());
514   LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsFunctionName, ());
515   LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsSummaryString, ());
516   LLDB_REGISTER_METHOD(const char *, SBTypeSummary, GetData, ());
517   LLDB_REGISTER_METHOD(uint32_t, SBTypeSummary, GetOptions, ());
518   LLDB_REGISTER_METHOD(void, SBTypeSummary, SetOptions, (uint32_t));
519   LLDB_REGISTER_METHOD(void, SBTypeSummary, SetSummaryString, (const char *));
520   LLDB_REGISTER_METHOD(void, SBTypeSummary, SetFunctionName, (const char *));
521   LLDB_REGISTER_METHOD(void, SBTypeSummary, SetFunctionCode, (const char *));
522   LLDB_REGISTER_METHOD(bool, SBTypeSummary, GetDescription,
523                        (lldb::SBStream &, lldb::DescriptionLevel));
524   LLDB_REGISTER_METHOD(bool, SBTypeSummary, DoesPrintValue, (lldb::SBValue));
525   LLDB_REGISTER_METHOD(
526       lldb::SBTypeSummary &,
527       SBTypeSummary, operator=,(const lldb::SBTypeSummary &));
528   LLDB_REGISTER_METHOD(bool,
529                        SBTypeSummary, operator==,(lldb::SBTypeSummary &));
530   LLDB_REGISTER_METHOD(bool, SBTypeSummary, IsEqualTo,
531                        (lldb::SBTypeSummary &));
532   LLDB_REGISTER_METHOD(bool,
533                        SBTypeSummary, operator!=,(lldb::SBTypeSummary &));
534 }
535 
536 }
537 }
538