llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Bar Soloveychik (barsolo2000) <details> <summary>Changes</summary> This patch introduces `RegisterTypeBuiltin`, an internal representation of GDB predefined types such as `uint32`, `bool`, `ieee_half`, and `data_ptr`. - Store each builtin's encoding, display format, and optional fixed byte size. - Use `std::nullopt` for target-dependent types such as pointers. - Teach `RegisterTypeBuilderClang` to create the corresponding Clang `CompilerType`. - Validate that the resulting type exactly matches the register size. - Do not serialize builtins because GDB defines them implicitly by name. - Add tests for fixed-size, named, pointer-sized, mismatched, and non-serialized builtins. This provides the scalar element types needed to build register vectors in later patches. It does not parse or display vectors yet. --- Full diff: https://github.com/llvm/llvm-project/pull/218725.diff 6 Files Affected: - (modified) lldb/include/lldb/Utility/RegisterType.h (+36-2) - (modified) lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp (+36) - (modified) lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h (+4) - (modified) lldb/source/Utility/RegisterType.cpp (+12) - (modified) lldb/unittests/Target/RegisterTypeBuilderClangTest.cpp (+65) - (modified) lldb/unittests/Utility/RegisterTypeTest.cpp (+32) ``````````diff diff --git a/lldb/include/lldb/Utility/RegisterType.h b/lldb/include/lldb/Utility/RegisterType.h index 6734aca5a0b7c..bc403ae51c1db 100644 --- a/lldb/include/lldb/Utility/RegisterType.h +++ b/lldb/include/lldb/Utility/RegisterType.h @@ -9,9 +9,11 @@ #ifndef LLDB_UTILITY_REGISTERTYPE_H #define LLDB_UTILITY_REGISTERTYPE_H +#include "lldb/lldb-enumerations.h" #include "llvm/ADT/StringRef.h" #include <cstdint> +#include <optional> #include <string> #include <unordered_set> #include <vector> @@ -26,6 +28,7 @@ class RegisterType { enum RegisterTypeKind { eRegisterTypeKindFlags, eRegisterTypeKindEnum, + eRegisterTypeKindBuiltin, }; RegisterTypeKind getKind() const { return m_kind; } @@ -39,8 +42,9 @@ class RegisterType { /// Output XML that describes this type, to be inserted into a target XML /// file. Reserved characters like "<" are replaced with their XML safe /// equivalents like "<". - void ToXML(Stream &strm, std::unordered_set<std::string> &previously_emitted, - const RegisterType *user = nullptr) const; + virtual void ToXML(Stream &strm, + std::unordered_set<std::string> &previously_emitted, + const RegisterType *user = nullptr) const; /// Print a string escaped for use as an XML attribute value. static void PrintXMLAttributeValue(Stream &strm, llvm::StringRef value); @@ -60,6 +64,9 @@ class RegisterType { /// reused after this instance is destroyed. uint64_t GetUID() const { return m_uid; } + /// Return this type's fixed size in bytes, if it has one. + virtual std::optional<uint64_t> GetByteSize() const { return std::nullopt; } + void SetDependencies(std::vector<const RegisterType *> dependencies) { m_dependencies = dependencies; } @@ -71,6 +78,33 @@ class RegisterType { std::vector<const RegisterType *> m_dependencies; }; +/// A predefined GDB target-description type. Builtin types are referenced by +/// name and are not emitted as XML definitions. +class RegisterTypeBuiltin : public RegisterType { +public: + /// A missing byte size means the size depends on the target. + RegisterTypeBuiltin(std::string id, lldb::Encoding encoding, + lldb::Format format, std::optional<uint64_t> byte_size); + + lldb::Encoding GetEncoding() const { return m_encoding; } + lldb::Format GetFormat() const { return m_format; } + std::optional<uint64_t> GetByteSize() const override { return m_byte_size; } + + void ToXML(Stream &strm, std::unordered_set<std::string> &previously_emitted, + const RegisterType *user = nullptr) const override; + void ToXMLElement(Stream &strm, + const RegisterType *user = nullptr) const override; + + static bool classof(const RegisterType *type) { + return type->getKind() == eRegisterTypeKindBuiltin; + } + +private: + const lldb::Encoding m_encoding; + const lldb::Format m_format; + const std::optional<uint64_t> m_byte_size; +}; + } // namespace lldb_private #endif // LLDB_UTILITY_REGISTERTYPE_H diff --git a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp index 7a49c75f181bd..e06e92e3ba8a9 100644 --- a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp +++ b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp @@ -10,6 +10,7 @@ #include "RegisterTypeBuilderClang.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Utility/RegisterType.h" #include "lldb/lldb-enumerations.h" using namespace lldb_private; @@ -33,6 +34,37 @@ RegisterTypeBuilderClang::CreateInstance(Target &target) { RegisterTypeBuilderClang::RegisterTypeBuilderClang(Target &target) : m_target(target) {} +CompilerType RegisterTypeBuilderClang::BuildBuiltinType( + const RegisterTypeBuiltin *builtin_type, uint32_t expected_byte_size, + lldb::TypeSystemClangSP type_system) { + if (auto type = GetExistingCompilerType(builtin_type, expected_byte_size)) + return *type; + + CompilerType compiler_type; + clang::ASTContext &ast = type_system->getASTContext(); + // These GDB types have semantics that encoding and byte size cannot express. + if (builtin_type->GetID() == "data_ptr" || + builtin_type->GetID() == "code_ptr") + compiler_type = type_system->GetType(ast.VoidPtrTy); + else if (builtin_type->GetID() == "bool") + compiler_type = type_system->GetType(ast.BoolTy); + else if (builtin_type->GetID() == "bfloat16") + compiler_type = type_system->GetType(ast.BFloat16Ty); + else if (std::optional<uint64_t> byte_size = builtin_type->GetByteSize()) + compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize( + builtin_type->GetEncoding(), *byte_size * 8); + + if (!compiler_type.IsValid() || + llvm::expectedToOptional(compiler_type.GetByteSize(nullptr)) != + expected_byte_size) + return {}; + + m_type_cache.try_emplace( + std::make_pair(builtin_type->GetUID(), expected_byte_size), + compiler_type); + return compiler_type; +} + CompilerType RegisterTypeBuilderClang::BuildEnumType(const RegisterTypeEnum *enum_type_info, uint32_t register_byte_size, @@ -128,6 +160,10 @@ RegisterTypeBuilderClang::GetRegisterType(const RegisterInfo ®_info) { // methods may call each other (Flags may use Enums for example). switch (reg_info.register_type->getKind()) { + case RegisterType::eRegisterTypeKindBuiltin: + return BuildBuiltinType( + llvm::cast<RegisterTypeBuiltin>(reg_info.register_type), + reg_info.byte_size, type_system); case RegisterType::eRegisterTypeKindFlags: return BuildFlagsType( llvm::dyn_cast<RegisterTypeFlags>(reg_info.register_type), diff --git a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h index 8d970367a15b2..e4734a85269d4 100644 --- a/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h +++ b/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.h @@ -33,6 +33,10 @@ class RegisterTypeBuilderClang : public RegisterTypeBuilder { CompilerType GetRegisterType(const RegisterInfo ®_info) override; private: + CompilerType BuildBuiltinType(const RegisterTypeBuiltin *builtin_type, + uint32_t expected_byte_size, + lldb::TypeSystemClangSP type_system); + CompilerType BuildEnumType(const RegisterTypeEnum *enum_type_info, uint32_t register_byte_size, lldb::TypeSystemClangSP type_system); diff --git a/lldb/source/Utility/RegisterType.cpp b/lldb/source/Utility/RegisterType.cpp index 4734b939ffdaf..583930915f3b9 100644 --- a/lldb/source/Utility/RegisterType.cpp +++ b/lldb/source/Utility/RegisterType.cpp @@ -43,3 +43,15 @@ void RegisterType::PrintXMLAttributeValue(Stream &strm, llvm::StringRef value) { llvm::printHTMLEscaped(value, escape_strm); strm << escaped; } + +RegisterTypeBuiltin::RegisterTypeBuiltin(std::string id, + lldb::Encoding encoding, + lldb::Format format, + std::optional<uint64_t> byte_size) + : RegisterType(eRegisterTypeKindBuiltin, std::move(id)), + m_encoding(encoding), m_format(format), m_byte_size(byte_size) {} + +void RegisterTypeBuiltin::ToXML(Stream &, std::unordered_set<std::string> &, + const RegisterType *) const {} + +void RegisterTypeBuiltin::ToXMLElement(Stream &, const RegisterType *) const {} diff --git a/lldb/unittests/Target/RegisterTypeBuilderClangTest.cpp b/lldb/unittests/Target/RegisterTypeBuilderClangTest.cpp index c24c3e35957f9..33c014e92fc02 100644 --- a/lldb/unittests/Target/RegisterTypeBuilderClangTest.cpp +++ b/lldb/unittests/Target/RegisterTypeBuilderClangTest.cpp @@ -16,6 +16,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/RegisterInfo.h" +#include "lldb/Utility/RegisterType.h" #include "lldb/Utility/RegisterTypeFlags.h" #include "gtest/gtest.h" @@ -160,4 +161,68 @@ TEST_F(RegisterTypeBuilderClangTest, CacheFollowsScratchTypeSystem) { EXPECT_NE(first, second); } +TEST_F(RegisterTypeBuilderClangTest, BuildsFixedSizeBuiltin) { + Target &target = m_debugger_sp->GetDummyTarget(); + RegisterTypeBuiltin builtin("uint32", eEncodingUint, eFormatHex, 4); + RegisterTypeBuilderClang builder(target); + + CompilerType type = builder.GetRegisterType(MakeRegisterInfo(builtin, 4)); + lldb::TypeSystemClangSP type_system = + ScratchTypeSystemClang::GetForTarget(target); + + ASSERT_TRUE(type); + ASSERT_TRUE(type_system); + EXPECT_EQ(type, + type_system->GetType(type_system->getASTContext().UnsignedIntTy)); +} + +TEST_F(RegisterTypeBuilderClangTest, BuildsNamedBuiltins) { + Target &target = m_debugger_sp->GetDummyTarget(); + RegisterTypeBuiltin boolean("bool", eEncodingUint, eFormatBoolean, 1); + RegisterTypeBuiltin ieee_half("ieee_half", eEncodingIEEE754, eFormatFloat, 2); + RegisterTypeBuiltin bfloat16("bfloat16", eEncodingIEEE754, eFormatFloat, 2); + RegisterTypeBuilderClang builder(target); + + CompilerType bool_type = + builder.GetRegisterType(MakeRegisterInfo(boolean, 1)); + CompilerType half_type = + builder.GetRegisterType(MakeRegisterInfo(ieee_half, 2)); + CompilerType bfloat_type = + builder.GetRegisterType(MakeRegisterInfo(bfloat16, 2)); + lldb::TypeSystemClangSP type_system = + ScratchTypeSystemClang::GetForTarget(target); + + ASSERT_TRUE(type_system); + clang::ASTContext &ast = type_system->getASTContext(); + EXPECT_EQ(bool_type, type_system->GetType(ast.BoolTy)); + EXPECT_EQ(half_type, type_system->GetType(ast.HalfTy)); + EXPECT_EQ(bfloat_type, type_system->GetType(ast.BFloat16Ty)); +} + +TEST_F(RegisterTypeBuilderClangTest, BuildsTargetSizedPointer) { + Target &target = m_debugger_sp->GetDummyTarget(); + RegisterTypeBuiltin builtin("data_ptr", eEncodingUint, eFormatAddressInfo, + std::nullopt); + RegisterTypeBuilderClang builder(target); + + CompilerType type = builder.GetRegisterType(MakeRegisterInfo(builtin, 8)); + lldb::TypeSystemClangSP type_system = + ScratchTypeSystemClang::GetForTarget(target); + + ASSERT_TRUE(type); + ASSERT_TRUE(type_system); + EXPECT_EQ(type, type_system->GetType(type_system->getASTContext().VoidPtrTy)); +} + +TEST_F(RegisterTypeBuilderClangTest, RejectsSizeMismatch) { + Target &target = m_debugger_sp->GetDummyTarget(); + RegisterTypeBuiltin uint32("uint32", eEncodingUint, eFormatHex, 4); + RegisterTypeBuiltin pointer("data_ptr", eEncodingUint, eFormatAddressInfo, + std::nullopt); + RegisterTypeBuilderClang builder(target); + + EXPECT_FALSE(builder.GetRegisterType(MakeRegisterInfo(uint32, 8))); + EXPECT_FALSE(builder.GetRegisterType(MakeRegisterInfo(pointer, 4))); +} + } // namespace diff --git a/lldb/unittests/Utility/RegisterTypeTest.cpp b/lldb/unittests/Utility/RegisterTypeTest.cpp index 6fd2d546dabc4..34de8c15b69c6 100644 --- a/lldb/unittests/Utility/RegisterTypeTest.cpp +++ b/lldb/unittests/Utility/RegisterTypeTest.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Utility/RegisterType.h" #include "lldb/Utility/RegisterTypeFlags.h" #include "lldb/Utility/StreamString.h" #include "gmock/gmock.h" @@ -597,3 +598,34 @@ TEST(RegisterTypeTest, XMLDefinitionsAreDeduplicatedByID) { " <evalue name=\"first\" value=\"0\"/>\n" "</enum>\n"); } + +TEST(RegisterTypeBuiltinTest, Construction) { + RegisterTypeBuiltin type("uint32", eEncodingUint, eFormatHex, 4); + + EXPECT_EQ(type.GetID(), "uint32"); + EXPECT_EQ(type.GetEncoding(), eEncodingUint); + EXPECT_EQ(type.GetFormat(), eFormatHex); + ASSERT_TRUE(type.GetByteSize()); + EXPECT_EQ(*type.GetByteSize(), 4u); +} + +TEST(RegisterTypeBuiltinTest, TargetDependentByteSize) { + RegisterTypeBuiltin type("data_ptr", eEncodingUint, eFormatAddressInfo, + std::nullopt); + + EXPECT_FALSE(type.GetByteSize()); +} + +TEST(RegisterTypeBuiltinTest, DoesNotSerialize) { + RegisterTypeBuiltin builtin("uint8", eEncodingUint, eFormatHex, 1); + const RegisterType &type = builtin; + StreamString strm; + std::unordered_set<std::string> previously_emitted; + + type.ToXML(strm, previously_emitted); + EXPECT_TRUE(strm.GetString().empty()); + EXPECT_TRUE(previously_emitted.empty()); + + type.ToXMLElement(strm); + EXPECT_TRUE(strm.GetString().empty()); +} `````````` </details> https://github.com/llvm/llvm-project/pull/218725 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
