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