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 SBTypeSummary retval; 163 if (cb) { 164 retval.SetSP(TypeSummaryImplSP(new CXXFunctionSummaryFormat( 165 options, 166 [cb](ValueObject &valobj, Stream &stm, 167 const TypeSummaryOptions &opt) -> bool { 168 SBStream stream; 169 SBValue sb_value(valobj.GetSP()); 170 SBTypeSummaryOptions options(&opt); 171 if (!cb(sb_value, options, stream)) 172 return false; 173 stm.Write(stream.GetData(), stream.GetSize()); 174 return true; 175 }, 176 description ? description : "callback summary formatter"))); 177 } 178 179 return retval; 180 } 181 182 SBTypeSummary::SBTypeSummary(const lldb::SBTypeSummary &rhs) 183 : m_opaque_sp(rhs.m_opaque_sp) { 184 LLDB_RECORD_CONSTRUCTOR(SBTypeSummary, (const lldb::SBTypeSummary &), rhs); 185 } 186 187 SBTypeSummary::~SBTypeSummary() {} 188 189 bool SBTypeSummary::IsValid() const { 190 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummary, IsValid); 191 192 return m_opaque_sp.get() != NULL; 193 } 194 195 bool SBTypeSummary::IsFunctionCode() { 196 LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsFunctionCode); 197 198 if (!IsValid()) 199 return false; 200 if (ScriptSummaryFormat *script_summary_ptr = 201 llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) { 202 const char *ftext = script_summary_ptr->GetPythonScript(); 203 return (ftext && *ftext != 0); 204 } 205 return false; 206 } 207 208 bool SBTypeSummary::IsFunctionName() { 209 LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsFunctionName); 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::IsSummaryString() { 222 LLDB_RECORD_METHOD_NO_ARGS(bool, SBTypeSummary, IsSummaryString); 223 224 if (!IsValid()) 225 return false; 226 227 return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString; 228 } 229 230 const char *SBTypeSummary::GetData() { 231 LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeSummary, GetData); 232 233 if (!IsValid()) 234 return NULL; 235 if (ScriptSummaryFormat *script_summary_ptr = 236 llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) { 237 const char *fname = script_summary_ptr->GetFunctionName(); 238 const char *ftext = script_summary_ptr->GetPythonScript(); 239 if (ftext && *ftext) 240 return ftext; 241 return fname; 242 } else if (StringSummaryFormat *string_summary_ptr = 243 llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get())) 244 return string_summary_ptr->GetSummaryString(); 245 return nullptr; 246 } 247 248 uint32_t SBTypeSummary::GetOptions() { 249 LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBTypeSummary, GetOptions); 250 251 if (!IsValid()) 252 return lldb::eTypeOptionNone; 253 return m_opaque_sp->GetOptions(); 254 } 255 256 void SBTypeSummary::SetOptions(uint32_t value) { 257 LLDB_RECORD_METHOD(void, SBTypeSummary, SetOptions, (uint32_t), value); 258 259 if (!CopyOnWrite_Impl()) 260 return; 261 m_opaque_sp->SetOptions(value); 262 } 263 264 void SBTypeSummary::SetSummaryString(const char *data) { 265 LLDB_RECORD_METHOD(void, SBTypeSummary, SetSummaryString, (const char *), 266 data); 267 268 if (!IsValid()) 269 return; 270 if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get())) 271 ChangeSummaryType(false); 272 if (StringSummaryFormat *string_summary_ptr = 273 llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get())) 274 string_summary_ptr->SetSummaryString(data); 275 } 276 277 void SBTypeSummary::SetFunctionName(const char *data) { 278 LLDB_RECORD_METHOD(void, SBTypeSummary, SetFunctionName, (const char *), 279 data); 280 281 if (!IsValid()) 282 return; 283 if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get())) 284 ChangeSummaryType(true); 285 if (ScriptSummaryFormat *script_summary_ptr = 286 llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) 287 script_summary_ptr->SetFunctionName(data); 288 } 289 290 void SBTypeSummary::SetFunctionCode(const char *data) { 291 LLDB_RECORD_METHOD(void, SBTypeSummary, SetFunctionCode, (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->SetPythonScript(data); 301 } 302 303 bool SBTypeSummary::GetDescription(lldb::SBStream &description, 304 lldb::DescriptionLevel description_level) { 305 LLDB_RECORD_METHOD(bool, SBTypeSummary, GetDescription, 306 (lldb::SBStream &, lldb::DescriptionLevel), description, 307 description_level); 308 309 if (!CopyOnWrite_Impl()) 310 return false; 311 else { 312 description.Printf("%s\n", m_opaque_sp->GetDescription().c_str()); 313 return true; 314 } 315 } 316 317 bool SBTypeSummary::DoesPrintValue(lldb::SBValue value) { 318 LLDB_RECORD_METHOD(bool, SBTypeSummary, DoesPrintValue, (lldb::SBValue), 319 value); 320 321 if (!IsValid()) 322 return false; 323 lldb::ValueObjectSP value_sp = value.GetSP(); 324 return m_opaque_sp->DoesPrintValue(value_sp.get()); 325 } 326 327 lldb::SBTypeSummary &SBTypeSummary::operator=(const lldb::SBTypeSummary &rhs) { 328 LLDB_RECORD_METHOD(lldb::SBTypeSummary &, 329 SBTypeSummary, operator=,(const lldb::SBTypeSummary &), 330 rhs); 331 332 if (this != &rhs) { 333 m_opaque_sp = rhs.m_opaque_sp; 334 } 335 return *this; 336 } 337 338 bool SBTypeSummary::operator==(lldb::SBTypeSummary &rhs) { 339 LLDB_RECORD_METHOD(bool, SBTypeSummary, operator==,(lldb::SBTypeSummary &), 340 rhs); 341 342 if (!IsValid()) 343 return !rhs.IsValid(); 344 return m_opaque_sp == rhs.m_opaque_sp; 345 } 346 347 bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) { 348 LLDB_RECORD_METHOD(bool, SBTypeSummary, IsEqualTo, (lldb::SBTypeSummary &), 349 rhs); 350 351 if (IsValid()) { 352 // valid and invalid are different 353 if (!rhs.IsValid()) 354 return false; 355 } else { 356 // invalid and valid are different 357 if (rhs.IsValid()) 358 return false; 359 else 360 // both invalid are the same 361 return true; 362 } 363 364 if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind()) 365 return false; 366 367 switch (m_opaque_sp->GetKind()) { 368 case TypeSummaryImpl::Kind::eCallback: 369 return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) == 370 llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get()); 371 case TypeSummaryImpl::Kind::eScript: 372 if (IsFunctionCode() != rhs.IsFunctionCode()) 373 return false; 374 if (IsFunctionName() != rhs.IsFunctionName()) 375 return false; 376 return GetOptions() == rhs.GetOptions(); 377 case TypeSummaryImpl::Kind::eSummaryString: 378 if (IsSummaryString() != rhs.IsSummaryString()) 379 return false; 380 return GetOptions() == rhs.GetOptions(); 381 case TypeSummaryImpl::Kind::eInternal: 382 return (m_opaque_sp.get() == rhs.m_opaque_sp.get()); 383 } 384 385 return false; 386 } 387 388 bool SBTypeSummary::operator!=(lldb::SBTypeSummary &rhs) { 389 LLDB_RECORD_METHOD(bool, SBTypeSummary, operator!=,(lldb::SBTypeSummary &), 390 rhs); 391 392 if (!IsValid()) 393 return !rhs.IsValid(); 394 return m_opaque_sp != rhs.m_opaque_sp; 395 } 396 397 lldb::TypeSummaryImplSP SBTypeSummary::GetSP() { return m_opaque_sp; } 398 399 void SBTypeSummary::SetSP(const lldb::TypeSummaryImplSP &typesummary_impl_sp) { 400 m_opaque_sp = typesummary_impl_sp; 401 } 402 403 SBTypeSummary::SBTypeSummary(const lldb::TypeSummaryImplSP &typesummary_impl_sp) 404 : m_opaque_sp(typesummary_impl_sp) {} 405 406 bool SBTypeSummary::CopyOnWrite_Impl() { 407 if (!IsValid()) 408 return false; 409 410 if (m_opaque_sp.unique()) 411 return true; 412 413 TypeSummaryImplSP new_sp; 414 415 if (CXXFunctionSummaryFormat *current_summary_ptr = 416 llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get())) { 417 new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat( 418 GetOptions(), current_summary_ptr->m_impl, 419 current_summary_ptr->m_description.c_str())); 420 } else if (ScriptSummaryFormat *current_summary_ptr = 421 llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get())) { 422 new_sp = TypeSummaryImplSP(new ScriptSummaryFormat( 423 GetOptions(), current_summary_ptr->GetFunctionName(), 424 current_summary_ptr->GetPythonScript())); 425 } else if (StringSummaryFormat *current_summary_ptr = 426 llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get())) { 427 new_sp = TypeSummaryImplSP(new StringSummaryFormat( 428 GetOptions(), current_summary_ptr->GetSummaryString())); 429 } 430 431 SetSP(new_sp); 432 433 return nullptr != new_sp.get(); 434 } 435 436 bool SBTypeSummary::ChangeSummaryType(bool want_script) { 437 if (!IsValid()) 438 return false; 439 440 TypeSummaryImplSP new_sp; 441 442 if (want_script == 443 (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript)) { 444 if (m_opaque_sp->GetKind() == 445 lldb_private::TypeSummaryImpl::Kind::eCallback && 446 !want_script) 447 new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), "")); 448 else 449 return CopyOnWrite_Impl(); 450 } 451 452 if (!new_sp) { 453 if (want_script) 454 new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", "")); 455 else 456 new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), "")); 457 } 458 459 SetSP(new_sp); 460 461 return true; 462 } 463