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