| //===-- 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; |
| } |