1 //===-- LibCxxBitset.cpp ----------------------------------------*- 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 #include "LibCxx.h" 11 #include "lldb/DataFormatters/FormattersHelpers.h" 12 #include "lldb/Symbol/ClangASTContext.h" 13 #include "lldb/Target/Target.h" 14 15 using namespace lldb; 16 using namespace lldb_private; 17 18 namespace { 19 20 class BitsetFrontEnd : public SyntheticChildrenFrontEnd { 21 public: 22 BitsetFrontEnd(ValueObject &valobj); 23 24 size_t GetIndexOfChildWithName(const ConstString &name) override { 25 return formatters::ExtractIndexFromString(name.GetCString()); 26 } 27 28 bool MightHaveChildren() override { return true; } 29 bool Update() override; 30 size_t CalculateNumChildren() override { return m_elements.size(); } 31 ValueObjectSP GetChildAtIndex(size_t idx) override; 32 33 private: 34 std::vector<ValueObjectSP> m_elements; 35 ValueObjectSP m_first; 36 CompilerType m_bool_type; 37 ByteOrder m_byte_order = eByteOrderInvalid; 38 uint8_t m_byte_size = 0; 39 }; 40 } // namespace 41 42 BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) 43 : SyntheticChildrenFrontEnd(valobj) { 44 m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool); 45 if (auto target_sp = m_backend.GetTargetSP()) { 46 m_byte_order = target_sp->GetArchitecture().GetByteOrder(); 47 m_byte_size = target_sp->GetArchitecture().GetAddressByteSize(); 48 Update(); 49 } 50 } 51 52 bool BitsetFrontEnd::Update() { 53 m_elements.clear(); 54 m_first.reset(); 55 56 TargetSP target_sp = m_backend.GetTargetSP(); 57 if (!target_sp) 58 return false; 59 size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay(); 60 61 size_t size = 0; 62 if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) 63 size = arg->value.getLimitedValue(capping_size); 64 65 m_elements.assign(size, ValueObjectSP()); 66 67 m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); 68 return false; 69 } 70 71 ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { 72 if (idx >= m_elements.size() || !m_first) 73 return ValueObjectSP(); 74 75 if (m_elements[idx]) 76 return m_elements[idx]; 77 78 ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false); 79 CompilerType type; 80 ValueObjectSP chunk; 81 // For small bitsets __first_ is not an array, but a plain size_t. 82 if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) { 83 llvm::Optional<uint64_t> bit_size = 84 type.GetBitSize(ctx.GetBestExecutionContextScope()); 85 if (!bit_size || *bit_size == 0) 86 return {}; 87 chunk = m_first->GetChildAtIndex(idx / *bit_size, true); 88 } else { 89 type = m_first->GetCompilerType(); 90 chunk = m_first; 91 } 92 if (!type || !chunk) 93 return {}; 94 95 llvm::Optional<uint64_t> bit_size = 96 type.GetBitSize(ctx.GetBestExecutionContextScope()); 97 if (!bit_size || *bit_size == 0) 98 return {}; 99 size_t chunk_idx = idx % *bit_size; 100 uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx)); 101 DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size); 102 103 m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), 104 data, ctx, m_bool_type); 105 106 return m_elements[idx]; 107 } 108 109 SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator( 110 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 111 if (valobj_sp) 112 return new BitsetFrontEnd(*valobj_sp); 113 return nullptr; 114 } 115