1 //===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef lldb_TypeSynthetic_h_ 11 #define lldb_TypeSynthetic_h_ 12 13 #include <stdint.h> 14 15 #include <functional> 16 #include <initializer_list> 17 #include <memory> 18 #include <string> 19 #include <vector> 20 21 #include "lldb/lldb-enumerations.h" 22 #include "lldb/lldb-public.h" 23 24 #include "lldb/Core/ValueObject.h" 25 #include "lldb/Utility/StructuredData.h" 26 27 namespace lldb_private { 28 class SyntheticChildrenFrontEnd { 29 protected: 30 ValueObject &m_backend; 31 SetValid(bool valid)32 void SetValid(bool valid) { m_valid = valid; } 33 IsValid()34 bool IsValid() { return m_valid; } 35 36 public: SyntheticChildrenFrontEnd(ValueObject & backend)37 SyntheticChildrenFrontEnd(ValueObject &backend) 38 : m_backend(backend), m_valid(true) {} 39 40 virtual ~SyntheticChildrenFrontEnd() = default; 41 42 virtual size_t CalculateNumChildren() = 0; 43 CalculateNumChildren(uint32_t max)44 virtual size_t CalculateNumChildren(uint32_t max) { 45 auto count = CalculateNumChildren(); 46 return count <= max ? count : max; 47 } 48 49 virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx) = 0; 50 51 virtual size_t GetIndexOfChildWithName(const ConstString &name) = 0; 52 53 // this function is assumed to always succeed and it if fails, the front-end 54 // should know to deal with it in the correct way (most probably, by refusing 55 // to return any children) the return value of Update() should actually be 56 // interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true, 57 // ValueObjectSyntheticFilter is allowed to use the children it fetched 58 // previously and cached if =false, ValueObjectSyntheticFilter must throw 59 // away its cache, and query again for children 60 virtual bool Update() = 0; 61 62 // if this function returns false, then CalculateNumChildren() MUST return 0 63 // since UI frontends might validly decide not to inquire for children given 64 // a false return value from this call if it returns true, then 65 // CalculateNumChildren() can return any number >= 0 (0 being valid) it 66 // should if at all possible be more efficient than CalculateNumChildren() 67 virtual bool MightHaveChildren() = 0; 68 69 // if this function returns a non-null ValueObject, then the returned 70 // ValueObject will stand for this ValueObject whenever a "value" request is 71 // made to this ValueObject GetSyntheticValue()72 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; } 73 74 // if this function returns a non-empty ConstString, then clients are 75 // expected to use the return as the name of the type of this ValueObject for 76 // display purposes GetSyntheticTypeName()77 virtual ConstString GetSyntheticTypeName() { return ConstString(); } 78 79 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; 80 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer; 81 82 protected: 83 lldb::ValueObjectSP 84 CreateValueObjectFromExpression(llvm::StringRef name, 85 llvm::StringRef expression, 86 const ExecutionContext &exe_ctx); 87 88 lldb::ValueObjectSP 89 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, 90 const ExecutionContext &exe_ctx, 91 CompilerType type); 92 93 lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, 94 const DataExtractor &data, 95 const ExecutionContext &exe_ctx, 96 CompilerType type); 97 98 private: 99 bool m_valid; 100 DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); 101 }; 102 103 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd { 104 public: SyntheticValueProviderFrontEnd(ValueObject & backend)105 SyntheticValueProviderFrontEnd(ValueObject &backend) 106 : SyntheticChildrenFrontEnd(backend) {} 107 108 ~SyntheticValueProviderFrontEnd() override = default; 109 CalculateNumChildren()110 size_t CalculateNumChildren() override { return 0; } 111 GetChildAtIndex(size_t idx)112 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return nullptr; } 113 GetIndexOfChildWithName(const ConstString & name)114 size_t GetIndexOfChildWithName(const ConstString &name) override { 115 return UINT32_MAX; 116 } 117 Update()118 bool Update() override { return false; } 119 MightHaveChildren()120 bool MightHaveChildren() override { return false; } 121 122 lldb::ValueObjectSP GetSyntheticValue() override = 0; 123 124 private: 125 DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd); 126 }; 127 128 class SyntheticChildren { 129 public: 130 class Flags { 131 public: Flags()132 Flags() : m_flags(lldb::eTypeOptionCascade) {} 133 Flags(const Flags & other)134 Flags(const Flags &other) : m_flags(other.m_flags) {} 135 Flags(uint32_t value)136 Flags(uint32_t value) : m_flags(value) {} 137 138 Flags &operator=(const Flags &rhs) { 139 if (&rhs != this) 140 m_flags = rhs.m_flags; 141 142 return *this; 143 } 144 145 Flags &operator=(const uint32_t &rhs) { 146 m_flags = rhs; 147 return *this; 148 } 149 Clear()150 Flags &Clear() { 151 m_flags = 0; 152 return *this; 153 } 154 GetCascades()155 bool GetCascades() const { 156 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; 157 } 158 159 Flags &SetCascades(bool value = true) { 160 if (value) 161 m_flags |= lldb::eTypeOptionCascade; 162 else 163 m_flags &= ~lldb::eTypeOptionCascade; 164 return *this; 165 } 166 GetSkipPointers()167 bool GetSkipPointers() const { 168 return (m_flags & lldb::eTypeOptionSkipPointers) == 169 lldb::eTypeOptionSkipPointers; 170 } 171 172 Flags &SetSkipPointers(bool value = true) { 173 if (value) 174 m_flags |= lldb::eTypeOptionSkipPointers; 175 else 176 m_flags &= ~lldb::eTypeOptionSkipPointers; 177 return *this; 178 } 179 GetSkipReferences()180 bool GetSkipReferences() const { 181 return (m_flags & lldb::eTypeOptionSkipReferences) == 182 lldb::eTypeOptionSkipReferences; 183 } 184 185 Flags &SetSkipReferences(bool value = true) { 186 if (value) 187 m_flags |= lldb::eTypeOptionSkipReferences; 188 else 189 m_flags &= ~lldb::eTypeOptionSkipReferences; 190 return *this; 191 } 192 GetNonCacheable()193 bool GetNonCacheable() const { 194 return (m_flags & lldb::eTypeOptionNonCacheable) == 195 lldb::eTypeOptionNonCacheable; 196 } 197 198 Flags &SetNonCacheable(bool value = true) { 199 if (value) 200 m_flags |= lldb::eTypeOptionNonCacheable; 201 else 202 m_flags &= ~lldb::eTypeOptionNonCacheable; 203 return *this; 204 } 205 GetFrontEndWantsDereference()206 bool GetFrontEndWantsDereference() const { 207 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) == 208 lldb::eTypeOptionFrontEndWantsDereference; 209 } 210 211 Flags &SetFrontEndWantsDereference(bool value = true) { 212 if (value) 213 m_flags |= lldb::eTypeOptionFrontEndWantsDereference; 214 else 215 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference; 216 return *this; 217 } 218 GetValue()219 uint32_t GetValue() { return m_flags; } 220 SetValue(uint32_t value)221 void SetValue(uint32_t value) { m_flags = value; } 222 223 private: 224 uint32_t m_flags; 225 }; 226 SyntheticChildren(const Flags & flags)227 SyntheticChildren(const Flags &flags) : m_flags(flags) {} 228 229 virtual ~SyntheticChildren() = default; 230 Cascades()231 bool Cascades() const { return m_flags.GetCascades(); } 232 SkipsPointers()233 bool SkipsPointers() const { return m_flags.GetSkipPointers(); } 234 SkipsReferences()235 bool SkipsReferences() const { return m_flags.GetSkipReferences(); } 236 NonCacheable()237 bool NonCacheable() const { return m_flags.GetNonCacheable(); } 238 WantsDereference()239 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();} 240 SetCascades(bool value)241 void SetCascades(bool value) { m_flags.SetCascades(value); } 242 SetSkipsPointers(bool value)243 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); } 244 SetSkipsReferences(bool value)245 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); } 246 SetNonCacheable(bool value)247 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); } 248 GetOptions()249 uint32_t GetOptions() { return m_flags.GetValue(); } 250 SetOptions(uint32_t value)251 void SetOptions(uint32_t value) { m_flags.SetValue(value); } 252 253 virtual bool IsScripted() = 0; 254 255 virtual std::string GetDescription() = 0; 256 257 virtual SyntheticChildrenFrontEnd::AutoPointer 258 GetFrontEnd(ValueObject &backend) = 0; 259 260 typedef std::shared_ptr<SyntheticChildren> SharedPointer; 261 GetRevision()262 uint32_t &GetRevision() { return m_my_revision; } 263 264 protected: 265 uint32_t m_my_revision; 266 Flags m_flags; 267 268 private: 269 DISALLOW_COPY_AND_ASSIGN(SyntheticChildren); 270 }; 271 272 class TypeFilterImpl : public SyntheticChildren { 273 std::vector<std::string> m_expression_paths; 274 275 public: TypeFilterImpl(const SyntheticChildren::Flags & flags)276 TypeFilterImpl(const SyntheticChildren::Flags &flags) 277 : SyntheticChildren(flags), m_expression_paths() {} 278 TypeFilterImpl(const SyntheticChildren::Flags & flags,const std::initializer_list<const char * > items)279 TypeFilterImpl(const SyntheticChildren::Flags &flags, 280 const std::initializer_list<const char *> items) 281 : SyntheticChildren(flags), m_expression_paths() { 282 for (auto path : items) 283 AddExpressionPath(path); 284 } 285 AddExpressionPath(const char * path)286 void AddExpressionPath(const char *path) { 287 AddExpressionPath(std::string(path)); 288 } 289 Clear()290 void Clear() { m_expression_paths.clear(); } 291 GetCount()292 size_t GetCount() const { return m_expression_paths.size(); } 293 GetExpressionPathAtIndex(size_t i)294 const char *GetExpressionPathAtIndex(size_t i) const { 295 return m_expression_paths[i].c_str(); 296 } 297 SetExpressionPathAtIndex(size_t i,const char * path)298 bool SetExpressionPathAtIndex(size_t i, const char *path) { 299 return SetExpressionPathAtIndex(i, std::string(path)); 300 } 301 302 void AddExpressionPath(const std::string &path); 303 304 bool SetExpressionPathAtIndex(size_t i, const std::string &path); 305 IsScripted()306 bool IsScripted() override { return false; } 307 308 std::string GetDescription() override; 309 310 class FrontEnd : public SyntheticChildrenFrontEnd { 311 public: FrontEnd(TypeFilterImpl * flt,ValueObject & backend)312 FrontEnd(TypeFilterImpl *flt, ValueObject &backend) 313 : SyntheticChildrenFrontEnd(backend), filter(flt) {} 314 315 ~FrontEnd() override = default; 316 CalculateNumChildren()317 size_t CalculateNumChildren() override { return filter->GetCount(); } 318 GetChildAtIndex(size_t idx)319 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { 320 if (idx >= filter->GetCount()) 321 return lldb::ValueObjectSP(); 322 return m_backend.GetSyntheticExpressionPathChild( 323 filter->GetExpressionPathAtIndex(idx), true); 324 } 325 Update()326 bool Update() override { return false; } 327 MightHaveChildren()328 bool MightHaveChildren() override { return filter->GetCount() > 0; } 329 330 size_t GetIndexOfChildWithName(const ConstString &name) override; 331 332 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; 333 334 private: 335 TypeFilterImpl *filter; 336 337 DISALLOW_COPY_AND_ASSIGN(FrontEnd); 338 }; 339 340 SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject & backend)341 GetFrontEnd(ValueObject &backend) override { 342 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); 343 } 344 345 typedef std::shared_ptr<TypeFilterImpl> SharedPointer; 346 347 private: 348 DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); 349 }; 350 351 class CXXSyntheticChildren : public SyntheticChildren { 352 public: 353 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *, 354 lldb::ValueObjectSP)> 355 CreateFrontEndCallback; CXXSyntheticChildren(const SyntheticChildren::Flags & flags,const char * description,CreateFrontEndCallback callback)356 CXXSyntheticChildren(const SyntheticChildren::Flags &flags, 357 const char *description, CreateFrontEndCallback callback) 358 : SyntheticChildren(flags), m_create_callback(callback), 359 m_description(description ? description : "") {} 360 IsScripted()361 bool IsScripted() override { return false; } 362 363 std::string GetDescription() override; 364 365 SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject & backend)366 GetFrontEnd(ValueObject &backend) override { 367 return SyntheticChildrenFrontEnd::AutoPointer( 368 m_create_callback(this, backend.GetSP())); 369 } 370 371 protected: 372 CreateFrontEndCallback m_create_callback; 373 std::string m_description; 374 375 private: 376 DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren); 377 }; 378 379 #ifndef LLDB_DISABLE_PYTHON 380 381 class ScriptedSyntheticChildren : public SyntheticChildren { 382 std::string m_python_class; 383 std::string m_python_code; 384 385 public: 386 ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags, 387 const char *pclass, const char *pcode = nullptr) SyntheticChildren(flags)388 : SyntheticChildren(flags), m_python_class(), m_python_code() { 389 if (pclass) 390 m_python_class = pclass; 391 if (pcode) 392 m_python_code = pcode; 393 } 394 GetPythonClassName()395 const char *GetPythonClassName() { return m_python_class.c_str(); } 396 GetPythonCode()397 const char *GetPythonCode() { return m_python_code.c_str(); } 398 SetPythonClassName(const char * fname)399 void SetPythonClassName(const char *fname) { 400 m_python_class.assign(fname); 401 m_python_code.clear(); 402 } 403 SetPythonCode(const char * script)404 void SetPythonCode(const char *script) { m_python_code.assign(script); } 405 406 std::string GetDescription() override; 407 IsScripted()408 bool IsScripted() override { return true; } 409 410 class FrontEnd : public SyntheticChildrenFrontEnd { 411 public: 412 FrontEnd(std::string pclass, ValueObject &backend); 413 414 ~FrontEnd() override; 415 416 bool IsValid(); 417 418 size_t CalculateNumChildren() override; 419 420 size_t CalculateNumChildren(uint32_t max) override; 421 422 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 423 424 bool Update() override; 425 426 bool MightHaveChildren() override; 427 428 size_t GetIndexOfChildWithName(const ConstString &name) override; 429 430 lldb::ValueObjectSP GetSyntheticValue() override; 431 432 ConstString GetSyntheticTypeName() override; 433 434 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; 435 436 private: 437 std::string m_python_class; 438 StructuredData::ObjectSP m_wrapper_sp; 439 ScriptInterpreter *m_interpreter; 440 441 DISALLOW_COPY_AND_ASSIGN(FrontEnd); 442 }; 443 444 SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject & backend)445 GetFrontEnd(ValueObject &backend) override { 446 auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer( 447 new FrontEnd(m_python_class, backend)); 448 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid()) 449 return synth_ptr; 450 return nullptr; 451 } 452 453 private: 454 DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren); 455 }; 456 #endif 457 } // namespace lldb_private 458 459 #endif // lldb_TypeSynthetic_h_ 460