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