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