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