From 5d04940855e460d40eefab9ea719f4c9b2e3d004 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 14 Nov 2018 12:53:36 -0700 Subject: [PATCH] Read template parameters for structure types Read DW_TAG_template_type_parameter and apply to structure types. --- lldb/include/lldb/Symbol/RustASTContext.h | 11 ++++- .../lang/rust/types/TestRustASTContext.py | 8 ++++ .../lldbsuite/test/lang/rust/types/main.rs | 4 ++ .../SymbolFile/DWARF/DWARFASTParserRust.cpp | 18 ++++++-- .../SymbolFile/DWARF/DWARFASTParserRust.h | 3 +- lldb/source/Symbol/RustASTContext.cpp | 46 +++++++++++++++++++ 6 files changed, 83 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Symbol/RustASTContext.h b/lldb/include/lldb/Symbol/RustASTContext.h index f9b54b5b0544a7..390579c4a8872f 100644 --- a/lldb/include/lldb/Symbol/RustASTContext.h +++ b/lldb/include/lldb/Symbol/RustASTContext.h @@ -132,6 +132,8 @@ class RustASTContext : public TypeSystem { bool is_default, uint64_t discriminant); void FinishAggregateInitialization(const CompilerType &type); + void AddTemplateParameter(const CompilerType &type, const CompilerType ¶m); + bool TypeHasDiscriminant(const CompilerType &type); bool IsTupleType(const CompilerType &type); @@ -327,10 +329,15 @@ class RustASTContext : public TypeSystem { const char *name, bool omit_empty_base_classes, std::vector &child_indexes) override; - size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override { - return 0; + lldb::TemplateArgumentKind GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, + size_t idx) override { + // Rust currently only has types. + return lldb::eTemplateArgumentKindType; } + CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx) override; + size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override; + //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- diff --git a/lldb/packages/Python/lldbsuite/test/lang/rust/types/TestRustASTContext.py b/lldb/packages/Python/lldbsuite/test/lang/rust/types/TestRustASTContext.py index 91ffbc03a8b6ae..7e6f15867d8524 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/rust/types/TestRustASTContext.py +++ b/lldb/packages/Python/lldbsuite/test/lang/rust/types/TestRustASTContext.py @@ -26,6 +26,7 @@ def test_with_dsym_and_python_api(self): self.check_main_function() self.check_structs() self.check_enums() + self.check_generics() def setUp(self): # Call super's setUp(). @@ -167,7 +168,14 @@ def check_enums(self): # See https://github.com/rust-lang-nursery/lldb/issues/24 # self.assertEqual(name, v.GetType().name) self.assertEqual(size, v.GetType().GetByteSize()) + self.assertEqual(0, v.GetType().num_template_args) # Some values can't really be checked. if value is not None: expected = "(" + name + ") " + vname + " = " + value self.assertEqual(expected, str(v.dynamic)) + + def check_generics(self): + t = self.var('vgeneric').GetType() + self.assertEqual(1, t.num_template_args) + self.assertEqual('T', t.template_args[0].name) + self.assertEqual('i32', t.template_args[0].GetTypedefedType().name) diff --git a/lldb/packages/Python/lldbsuite/test/lang/rust/types/main.rs b/lldb/packages/Python/lldbsuite/test/lang/rust/types/main.rs index 797a412e5ccc99..f294861d1600f0 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/rust/types/main.rs +++ b/lldb/packages/Python/lldbsuite/test/lang/rust/types/main.rs @@ -32,6 +32,8 @@ pub enum OptimizedEnum { NonNull(Box) } +pub struct Generic(T); + fn main() { let vbool: bool = true; @@ -72,5 +74,7 @@ fn main() { let voptenum = OptimizedEnum::Null; let voptenum2 = OptimizedEnum::NonNull(Box::new(7)); + let vgeneric = Generic(23i32); + do_nothing(); // breakpoint } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.cpp index ea0cb6f2c50f9b..7bd31a4be6034a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.cpp @@ -491,7 +491,7 @@ std::vector DWARFASTParserRust::ParseFields(const DWARFDIE &die, std::vector &discriminant_path, bool &is_tuple, uint64_t &discr_offset, uint64_t &discr_byte_size, - bool &saw_discr) { + bool &saw_discr, std::vector &template_params) { SymbolFileDWARF *dwarf = die.GetDWARF(); // We construct a list of fields and then apply them later so that @@ -631,8 +631,8 @@ DWARFASTParserRust::ParseFields(const DWARFDIE &die, std::vector &discri // New-style enum representation -- nothing useful is in the // enclosing struct, so we can just recurse here. return ParseFields(child_die, discriminant_path, is_tuple, - discr_offset, discr_byte_size, saw_discr); - } else { + discr_offset, discr_byte_size, saw_discr, template_params); + } else if (child_die.Tag() == DW_TAG_member) { if (new_field.is_discriminant) { // Don't check this field name, and don't increment field_index. // When we see a tuple with fields like @@ -650,6 +650,11 @@ DWARFASTParserRust::ParseFields(const DWARFDIE &die, std::vector &discri } fields.push_back(new_field); + } else if (child_die.Tag() == DW_TAG_template_type_parameter) { + Type *param_type = dwarf->ResolveTypeUID(child_die, true); + if (param_type) { + template_params.push_back(param_type->GetForwardCompilerType()); + } } } @@ -728,8 +733,10 @@ TypeSP DWARFASTParserRust::ParseStructureType(const DWARFDIE &die) { bool saw_discr = false; uint64_t discr_offset, discr_byte_size; std::vector discriminant_path; + std::vector template_params; std::vector fields = ParseFields(die, discriminant_path, is_tuple, - discr_offset, discr_byte_size, saw_discr); + discr_offset, discr_byte_size, saw_discr, + template_params); // This is true if this is a union, there are multiple fields and // each field's type has a discriminant. @@ -834,6 +841,9 @@ TypeSP DWARFASTParserRust::ParseStructureType(const DWARFDIE &die) { } } + for (const CompilerType ¶m_type : template_params) + m_ast.AddTemplateParameter(compiler_type, param_type); + m_ast.FinishAggregateInitialization(compiler_type); // Add our type to the unique type map so we don't diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.h index e2d54931954a12..62c9c62c7ec6c1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserRust.h @@ -104,7 +104,8 @@ class DWARFASTParserRust : public DWARFASTParser { std::vector &discriminant_path, bool &is_tuple, uint64_t &discr_offset, uint64_t &discr_byte_size, - bool &saw_discr); + bool &saw_discr, + std::vector &template_params); lldb_private::RustASTContext &m_ast; diff --git a/lldb/source/Symbol/RustASTContext.cpp b/lldb/source/Symbol/RustASTContext.cpp index bd76b75acaad2a..2b5277724bf728 100644 --- a/lldb/source/Symbol/RustASTContext.cpp +++ b/lldb/source/Symbol/RustASTContext.cpp @@ -400,6 +400,10 @@ class RustAggregateBase : public RustType { m_fields.emplace_back(name, type, offset); } + void AddTemplateParameter(const CompilerType &ctype) { + m_template_args.push_back(ctype); + } + virtual void FinishInitialization() { } @@ -423,6 +427,14 @@ class RustAggregateBase : public RustType { return &m_fields[idx]; } + size_t GetNumTemplateArguments() const { + return m_template_args.size(); + } + + CompilerType GetTypeTemplateArgument(size_t idx) const { + return m_template_args[idx]; + } + typedef std::vector::const_iterator const_iterator; const_iterator begin() const { @@ -472,6 +484,7 @@ class RustAggregateBase : public RustType { uint64_t m_byte_size; std::vector m_fields; bool m_has_discriminant; + std::vector m_template_args; }; class RustTuple : public RustAggregateBase { @@ -2148,3 +2161,36 @@ bool RustASTContext::GetCABITypeDeclaration(CompilerType type, const std::string *result = rtype->GetCABITypeDeclaration(name_map, varname); return true; } + +CompilerType RustASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, + size_t idx) { + if (type) { + RustType *t = static_cast(type); + if (RustAggregateBase *a = t->AsAggregate()) { + return a->GetTypeTemplateArgument(idx); + } + } + return CompilerType(); +} + +size_t RustASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { + if (type) { + RustType *t = static_cast(type); + if (RustAggregateBase *a = t->AsAggregate()) { + return a->GetNumTemplateArguments(); + } + } + return 0; +} + +void RustASTContext::AddTemplateParameter(const CompilerType &type, const CompilerType ¶m) { + if (!type) + return; + RustASTContext *ast = llvm::dyn_cast_or_null(type.GetTypeSystem()); + if (!ast) + return; + RustType *t = static_cast(type.GetOpaqueQualType()); + if (RustAggregateBase *a = t->AsAggregate()) { + a->AddTemplateParameter(param); + } +}