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