blob: e2644832ada4c6619f58addb50b3800669514ad5 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "Variables.h"
#include "lldb/Utility/DataExtractor.h"
#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <utility>
namespace symbols_backend {
namespace {
template <typename T>
llvm::Expected<T> ChainErrors(llvm::Expected<T>&& value,
llvm::Optional<llvm::Error>&& error) {
if (!error || value) {
if (error) {
llvm::consumeError(std::move(*error));
}
return std::move(value);
}
return joinErrors(value.takeError(), std::move(*error));
}
} // namespace
static lldb_private::CompilerType BaseType(lldb_private::CompilerType t) {
while (t.IsTypedefType()) {
t = t.GetTypedefedType();
}
return t;
}
static void CreateMemberInfo(llvm::SmallVectorImpl<SubObjectInfo>& members,
lldb_private::CompilerType type) {
type = BaseType(type);
for (size_t base_class = 0, e = type.GetNumDirectBaseClasses();
base_class < e; ++base_class) {
CreateMemberInfo(members,
type.GetDirectBaseClassAtIndex(base_class, nullptr));
}
for (size_t base_class = 0, e = type.GetNumVirtualBaseClasses();
base_class < e; ++base_class) {
CreateMemberInfo(members,
type.GetVirtualBaseClassAtIndex(base_class, nullptr));
}
for (size_t child = 0, e = type.GetNumFields(); child < e; ++child) {
std::string child_name;
uint64_t bit_offset;
auto child_type =
type.GetFieldAtIndex(child, child_name, &bit_offset, nullptr, nullptr);
assert(bit_offset % 8 == 0 && "Expecting fields to be byte-aligned");
if (child_name.empty()) {
// TODO(pfaffe) Are unions truly the only case here?
child_name = "<union>";
}
members.emplace_back(child_name, bit_offset / 8, child_type);
}
}
/*static */ llvm::SmallVector<SubObjectInfo, 1> SubObjectInfo::GetMembers(
lldb_private::CompilerType type) {
type = BaseType(type);
lldb_private::CompilerType pointee_type;
if (type.IsPointerType(&pointee_type)) {
SubObjectInfo info("*", 0, pointee_type);
return llvm::SmallVector<SubObjectInfo, 1>{{info}};
}
if (type.IsArrayType(&pointee_type, nullptr, nullptr) ||
type.IsVectorType(&pointee_type, nullptr)) {
SubObjectInfo info("0", 0, pointee_type);
return llvm::SmallVector<SubObjectInfo, 1>{{info}};
}
if (type.IsReferenceType()) {
SubObjectInfo info("*", 0, type.GetNonReferenceType());
return llvm::SmallVector<SubObjectInfo, 1>{{info}};
}
if (type.IsAggregateType()) {
llvm::SmallVector<SubObjectInfo, 1> members;
CreateMemberInfo(members, type);
return members;
}
return {};
}
} // namespace symbols_backend