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(src: 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>(args: 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(src: stream.GetData(), src_len: 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>(Val: 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>(Val: 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>(Val: 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>(Val: 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>(Val: m_opaque_sp.get())) |
255 | ChangeSummaryType(want_script: false); |
256 | if (StringSummaryFormat *string_summary_ptr = |
257 | llvm::dyn_cast<StringSummaryFormat>(Val: 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>(Val: m_opaque_sp.get())) |
267 | ChangeSummaryType(want_script: true); |
268 | if (ScriptSummaryFormat *script_summary_ptr = |
269 | llvm::dyn_cast<ScriptSummaryFormat>(Val: 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>(Val: m_opaque_sp.get())) |
279 | ChangeSummaryType(want_script: true); |
280 | if (ScriptSummaryFormat *script_summary_ptr = |
281 | llvm::dyn_cast<ScriptSummaryFormat>(Val: 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(format: "%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(valobj: 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>(Val: m_opaque_sp.get()) == |
345 | llvm::dyn_cast<CXXFunctionSummaryFormat>(Val: 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>(Val: 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>(Val: 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>(Val: 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 | |