xref: /freebsd/contrib/llvm-project/lldb/source/API/SBTypeSummary.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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  
21  SBTypeSummaryOptions::SBTypeSummaryOptions() {
22    LLDB_INSTRUMENT_VA(this);
23  
24    m_opaque_up = std::make_unique<TypeSummaryOptions>();
25  }
26  
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  
36  bool SBTypeSummaryOptions::IsValid() {
37    LLDB_INSTRUMENT_VA(this);
38    return this->operator bool();
39  }
40  SBTypeSummaryOptions::operator bool() const {
41    LLDB_INSTRUMENT_VA(this);
42  
43    return m_opaque_up.get();
44  }
45  
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  
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  
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  
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  
76  lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::operator->() {
77    return m_opaque_up.get();
78  }
79  
80  const lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::
81  operator->() const {
82    return m_opaque_up.get();
83  }
84  
85  lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::get() {
86    return m_opaque_up.get();
87  }
88  
89  lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() {
90    return *m_opaque_up;
91  }
92  
93  const lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() const {
94    return *m_opaque_up;
95  }
96  
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  
103  SBTypeSummary::SBTypeSummary() { LLDB_INSTRUMENT_VA(this); }
104  
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  
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  
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  
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  
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  
170  bool SBTypeSummary::IsValid() const {
171    LLDB_INSTRUMENT_VA(this);
172    return this->operator bool();
173  }
174  SBTypeSummary::operator bool() const {
175    LLDB_INSTRUMENT_VA(this);
176  
177    return m_opaque_sp.get() != nullptr;
178  }
179  
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  
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  
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  
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  
233  uint32_t SBTypeSummary::GetOptions() {
234    LLDB_INSTRUMENT_VA(this);
235  
236    if (!IsValid())
237      return lldb::eTypeOptionNone;
238    return m_opaque_sp->GetOptions();
239  }
240  
241  void SBTypeSummary::SetOptions(uint32_t value) {
242    LLDB_INSTRUMENT_VA(this, value);
243  
244    if (!CopyOnWrite_Impl())
245      return;
246    m_opaque_sp->SetOptions(value);
247  }
248  
249  void SBTypeSummary::SetSummaryString(const char *data) {
250    LLDB_INSTRUMENT_VA(this, data);
251  
252    if (!IsValid())
253      return;
254    if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get()))
255      ChangeSummaryType(false);
256    if (StringSummaryFormat *string_summary_ptr =
257            llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
258      string_summary_ptr->SetSummaryString(data);
259  }
260  
261  void SBTypeSummary::SetFunctionName(const char *data) {
262    LLDB_INSTRUMENT_VA(this, data);
263  
264    if (!IsValid())
265      return;
266    if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
267      ChangeSummaryType(true);
268    if (ScriptSummaryFormat *script_summary_ptr =
269            llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
270      script_summary_ptr->SetFunctionName(data);
271  }
272  
273  void SBTypeSummary::SetFunctionCode(const char *data) {
274    LLDB_INSTRUMENT_VA(this, data);
275  
276    if (!IsValid())
277      return;
278    if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
279      ChangeSummaryType(true);
280    if (ScriptSummaryFormat *script_summary_ptr =
281            llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
282      script_summary_ptr->SetPythonScript(data);
283  }
284  
285  bool SBTypeSummary::GetDescription(lldb::SBStream &description,
286                                     lldb::DescriptionLevel description_level) {
287    LLDB_INSTRUMENT_VA(this, description, description_level);
288  
289    if (!CopyOnWrite_Impl())
290      return false;
291    else {
292      description.Printf("%s\n", m_opaque_sp->GetDescription().c_str());
293      return true;
294    }
295  }
296  
297  bool SBTypeSummary::DoesPrintValue(lldb::SBValue value) {
298    LLDB_INSTRUMENT_VA(this, value);
299  
300    if (!IsValid())
301      return false;
302    lldb::ValueObjectSP value_sp = value.GetSP();
303    return m_opaque_sp->DoesPrintValue(value_sp.get());
304  }
305  
306  lldb::SBTypeSummary &SBTypeSummary::operator=(const lldb::SBTypeSummary &rhs) {
307    LLDB_INSTRUMENT_VA(this, rhs);
308  
309    if (this != &rhs) {
310      m_opaque_sp = rhs.m_opaque_sp;
311    }
312    return *this;
313  }
314  
315  bool SBTypeSummary::operator==(lldb::SBTypeSummary &rhs) {
316    LLDB_INSTRUMENT_VA(this, rhs);
317  
318    if (!IsValid())
319      return !rhs.IsValid();
320    return m_opaque_sp == rhs.m_opaque_sp;
321  }
322  
323  bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) {
324    LLDB_INSTRUMENT_VA(this, rhs);
325  
326    if (IsValid()) {
327      // valid and invalid are different
328      if (!rhs.IsValid())
329        return false;
330    } else {
331      // invalid and valid are different
332      if (rhs.IsValid())
333        return false;
334      else
335        // both invalid are the same
336        return true;
337    }
338  
339    if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind())
340      return false;
341  
342    switch (m_opaque_sp->GetKind()) {
343    case TypeSummaryImpl::Kind::eCallback:
344      return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) ==
345             llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get());
346    case TypeSummaryImpl::Kind::eScript:
347      if (IsFunctionCode() != rhs.IsFunctionCode())
348        return false;
349      if (IsFunctionName() != rhs.IsFunctionName())
350        return false;
351      return GetOptions() == rhs.GetOptions();
352    case TypeSummaryImpl::Kind::eSummaryString:
353      if (IsSummaryString() != rhs.IsSummaryString())
354        return false;
355      return GetOptions() == rhs.GetOptions();
356    case TypeSummaryImpl::Kind::eInternal:
357      return (m_opaque_sp.get() == rhs.m_opaque_sp.get());
358    }
359  
360    return false;
361  }
362  
363  bool SBTypeSummary::operator!=(lldb::SBTypeSummary &rhs) {
364    LLDB_INSTRUMENT_VA(this, rhs);
365  
366    if (!IsValid())
367      return !rhs.IsValid();
368    return m_opaque_sp != rhs.m_opaque_sp;
369  }
370  
371  lldb::TypeSummaryImplSP SBTypeSummary::GetSP() { return m_opaque_sp; }
372  
373  void SBTypeSummary::SetSP(const lldb::TypeSummaryImplSP &typesummary_impl_sp) {
374    m_opaque_sp = typesummary_impl_sp;
375  }
376  
377  SBTypeSummary::SBTypeSummary(const lldb::TypeSummaryImplSP &typesummary_impl_sp)
378      : m_opaque_sp(typesummary_impl_sp) {}
379  
380  bool SBTypeSummary::CopyOnWrite_Impl() {
381    if (!IsValid())
382      return false;
383  
384    if (m_opaque_sp.use_count() == 1)
385      return true;
386  
387    TypeSummaryImplSP new_sp;
388  
389    if (CXXFunctionSummaryFormat *current_summary_ptr =
390            llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get())) {
391      new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(
392          GetOptions(), current_summary_ptr->m_impl,
393          current_summary_ptr->m_description.c_str()));
394    } else if (ScriptSummaryFormat *current_summary_ptr =
395                   llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) {
396      new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(
397          GetOptions(), current_summary_ptr->GetFunctionName(),
398          current_summary_ptr->GetPythonScript()));
399    } else if (StringSummaryFormat *current_summary_ptr =
400                   llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get())) {
401      new_sp = TypeSummaryImplSP(new StringSummaryFormat(
402          GetOptions(), current_summary_ptr->GetSummaryString()));
403    }
404  
405    SetSP(new_sp);
406  
407    return nullptr != new_sp.get();
408  }
409  
410  bool SBTypeSummary::ChangeSummaryType(bool want_script) {
411    if (!IsValid())
412      return false;
413  
414    TypeSummaryImplSP new_sp;
415  
416    if (want_script ==
417        (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript)) {
418      if (m_opaque_sp->GetKind() ==
419              lldb_private::TypeSummaryImpl::Kind::eCallback &&
420          !want_script)
421        new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
422      else
423        return CopyOnWrite_Impl();
424    }
425  
426    if (!new_sp) {
427      if (want_script)
428        new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
429      else
430        new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
431    }
432  
433    SetSP(new_sp);
434  
435    return true;
436  }
437