blob: 067768537c06848920cd552d063ca4ffa691a179 [file] [log] [blame]
//===-- RegisterTypeBuilderClang.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 "clang/AST/DeclCXX.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "RegisterTypeBuilderClang.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/RegisterFlags.h"
#include "lldb/lldb-enumerations.h"
using namespace lldb_private;
LLDB_PLUGIN_DEFINE(RegisterTypeBuilderClang)
void RegisterTypeBuilderClang::Initialize() {
static llvm::once_flag g_once_flag;
llvm::call_once(g_once_flag, []() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance);
});
}
void RegisterTypeBuilderClang::Terminate() {}
lldb::RegisterTypeBuilderSP
RegisterTypeBuilderClang::CreateInstance(Target &target) {
return std::make_shared<RegisterTypeBuilderClang>(target);
}
RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target)
: m_target(target) {}
CompilerType RegisterTypeBuilderClang::GetRegisterType(
const std::string &name, const lldb_private::RegisterFlags &flags,
uint32_t byte_size) {
lldb::TypeSystemClangSP type_system =
ScratchTypeSystemClang::GetForTarget(m_target);
assert(type_system);
std::string register_type_name = "__lldb_register_fields_";
register_type_name += name;
// See if we have made this type before and can reuse it.
CompilerType fields_type =
type_system->GetTypeForIdentifier<clang::CXXRecordDecl>(
register_type_name);
if (!fields_type) {
// In most ABI, a change of field type means a change in storage unit.
// We want it all in one unit, so we use a field type the same as the
// register's size.
CompilerType field_uint_type =
type_system->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
byte_size * 8);
fields_type = type_system->CreateRecordType(
nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
register_type_name, llvm::to_underlying(clang::TagTypeKind::Struct),
lldb::eLanguageTypeC);
type_system->StartTagDeclarationDefinition(fields_type);
// We assume that RegisterFlags has padded and sorted the fields
// already.
for (const RegisterFlags::Field &field : flags.GetFields()) {
type_system->AddFieldToRecordType(fields_type, field.GetName(),
field_uint_type, lldb::eAccessPublic,
field.GetSizeInBits());
}
type_system->CompleteTagDeclarationDefinition(fields_type);
// So that the size of the type matches the size of the register.
type_system->SetIsPacked(fields_type);
// This should be true if RegisterFlags padded correctly.
assert(*fields_type.GetByteSize(nullptr) == flags.GetSize());
}
return fields_type;
}