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