blob: 11371918830bdff595c8f51e930b1bd04b25639f [file] [log] [blame]
//===-- VectorType.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
static CompilerType GetCompilerTypeForFormat(lldb::Format format,
CompilerType element_type,
TypeSystem *type_system) {
lldbassert(type_system && "type_system needs to be not NULL");
switch (format) {
case lldb::eFormatAddressInfo:
case lldb::eFormatPointer:
return type_system->GetBuiltinTypeForEncodingAndBitSize(
eEncodingUint, 8 * type_system->GetPointerByteSize());
case lldb::eFormatBoolean:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeBool);
case lldb::eFormatBytes:
case lldb::eFormatBytesWithASCII:
case lldb::eFormatChar:
case lldb::eFormatCharArray:
case lldb::eFormatCharPrintable:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar);
case lldb::eFormatComplex /* lldb::eFormatComplexFloat */:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloatComplex);
case lldb::eFormatCString:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar)
.GetPointerType();
case lldb::eFormatFloat:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
case lldb::eFormatHex:
case lldb::eFormatHexUppercase:
case lldb::eFormatOctal:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeInt);
case lldb::eFormatHexFloat:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
case lldb::eFormatUnicode16:
case lldb::eFormatUnicode32:
case lldb::eFormatUnsigned:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt);
case lldb::eFormatVectorOfChar:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar);
case lldb::eFormatVectorOfFloat32:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754,
32);
case lldb::eFormatVectorOfFloat64:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754,
64);
case lldb::eFormatVectorOfSInt16:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 16);
case lldb::eFormatVectorOfSInt32:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32);
case lldb::eFormatVectorOfSInt64:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64);
case lldb::eFormatVectorOfSInt8:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 8);
case lldb::eFormatVectorOfUInt128:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 128);
case lldb::eFormatVectorOfUInt16:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);
case lldb::eFormatVectorOfUInt32:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
case lldb::eFormatVectorOfUInt64:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64);
case lldb::eFormatVectorOfUInt8:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
case lldb::eFormatDefault:
return element_type;
case lldb::eFormatBinary:
case lldb::eFormatComplexInteger:
case lldb::eFormatDecimal:
case lldb::eFormatEnum:
case lldb::eFormatInstruction:
case lldb::eFormatOSType:
case lldb::eFormatVoid:
default:
return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
}
}
static lldb::Format GetItemFormatForFormat(lldb::Format format,
CompilerType element_type) {
switch (format) {
case lldb::eFormatVectorOfChar:
return lldb::eFormatChar;
case lldb::eFormatVectorOfFloat32:
case lldb::eFormatVectorOfFloat64:
return lldb::eFormatFloat;
case lldb::eFormatVectorOfSInt16:
case lldb::eFormatVectorOfSInt32:
case lldb::eFormatVectorOfSInt64:
case lldb::eFormatVectorOfSInt8:
return lldb::eFormatDecimal;
case lldb::eFormatVectorOfUInt128:
case lldb::eFormatVectorOfUInt16:
case lldb::eFormatVectorOfUInt32:
case lldb::eFormatVectorOfUInt64:
case lldb::eFormatVectorOfUInt8:
return lldb::eFormatUnsigned;
case lldb::eFormatBinary:
case lldb::eFormatComplexInteger:
case lldb::eFormatDecimal:
case lldb::eFormatEnum:
case lldb::eFormatInstruction:
case lldb::eFormatOSType:
case lldb::eFormatVoid:
return eFormatHex;
case lldb::eFormatDefault: {
// special case the (default, char) combination to actually display as an
// integer value most often, you won't want to see the ASCII characters...
// (and if you do, eFormatChar is a keystroke away)
bool is_char = element_type.IsCharType();
bool is_signed = false;
element_type.IsIntegerType(is_signed);
return is_char ? (is_signed ? lldb::eFormatDecimal : eFormatHex) : format;
} break;
default:
return format;
}
}
static size_t CalculateNumChildren(
CompilerType container_type, CompilerType element_type,
lldb_private::ExecutionContextScope *exe_scope =
nullptr // does not matter here because all we trade in are basic types
) {
llvm::Optional<uint64_t> container_size =
container_type.GetByteSize(exe_scope);
llvm::Optional<uint64_t> element_size = element_type.GetByteSize(exe_scope);
if (container_size && element_size && *element_size) {
if (*container_size % *element_size)
return 0;
return *container_size / *element_size;
}
return 0;
}
namespace lldb_private {
namespace formatters {
class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
VectorTypeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp), m_parent_format(eFormatInvalid),
m_item_format(eFormatInvalid), m_child_type(), m_num_children(0) {}
~VectorTypeSyntheticFrontEnd() override = default;
size_t CalculateNumChildren() override { return m_num_children; }
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
if (idx >= CalculateNumChildren())
return {};
llvm::Optional<uint64_t> size = m_child_type.GetByteSize(nullptr);
if (!size)
return {};
auto offset = idx * *size;
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset(
offset, m_child_type, true, ConstString(idx_name.GetString())));
if (!child_sp)
return child_sp;
child_sp->SetFormat(m_item_format);
return child_sp;
}
bool Update() override {
m_parent_format = m_backend.GetFormat();
CompilerType parent_type(m_backend.GetCompilerType());
CompilerType element_type;
parent_type.IsVectorType(&element_type);
m_child_type = ::GetCompilerTypeForFormat(m_parent_format, element_type,
parent_type.GetTypeSystem());
m_num_children = ::CalculateNumChildren(parent_type, m_child_type);
m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type);
return false;
}
bool MightHaveChildren() override { return true; }
size_t GetIndexOfChildWithName(ConstString name) override {
const char *item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
return UINT32_MAX;
return idx;
}
private:
lldb::Format m_parent_format;
lldb::Format m_item_format;
CompilerType m_child_type;
size_t m_num_children;
};
} // namespace formatters
} // namespace lldb_private
bool lldb_private::formatters::VectorTypeSummaryProvider(
ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
auto synthetic_children =
VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP());
if (!synthetic_children)
return false;
synthetic_children->Update();
s.PutChar('(');
bool first = true;
size_t idx = 0, len = synthetic_children->CalculateNumChildren();
for (; idx < len; idx++) {
auto child_sp = synthetic_children->GetChildAtIndex(idx);
if (!child_sp)
continue;
child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
lldb::eDynamicDontRunTarget, true);
const char *child_value = child_sp->GetValueAsCString();
if (child_value && *child_value) {
if (first) {
s.Printf("%s", child_value);
first = false;
} else {
s.Printf(", %s", child_value);
}
}
}
s.PutChar(')');
return true;
}
lldb_private::SyntheticChildrenFrontEnd *
lldb_private::formatters::VectorTypeSyntheticFrontEndCreator(
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
if (!valobj_sp)
return nullptr;
return new VectorTypeSyntheticFrontEnd(valobj_sp);
}